Merge "Keep the native mdns daemon alive for pre-S application"
diff --git a/Android.bp b/Android.bp
index 0277af0..d3bced1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -357,9 +357,6 @@
     srcs: [
         "core/java/android/net/annotations/PolicyDirection.java",
         "core/java/com/android/internal/util/HexDump.java",
-        "core/java/com/android/internal/util/IState.java",
-        "core/java/com/android/internal/util/State.java",
-        "core/java/com/android/internal/util/StateMachine.java",
         "core/java/com/android/internal/util/WakeupMessage.java",
         "services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java",
         "telephony/java/android/telephony/Annotation.java",
@@ -408,11 +405,9 @@
     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",
         "core/java/com/android/internal/util/Protocol.java",
-        "core/java/com/android/internal/util/Preconditions.java",
         "telephony/java/android/telephony/Annotation.java",
         ":net-utils-framework-wifi-common-srcs",
     ],
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 65a6547..1767678 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -77,22 +77,16 @@
         // Module sources
         ":art.module.public.api{.public.stubs.source}",
         ":conscrypt.module.public.api{.public.stubs.source}",
-        ":framework-connectivity-sources",
-        ":framework-mediaprovider-sources",
-        ":framework-permission-sources",
-        ":framework-sdkextensions-sources",
-        ":framework-statsd-sources",
-        ":framework-tethering-srcs",
-        ":framework-wifi-updatable-sources",
         ":i18n.module.public.api{.public.stubs.source}",
-        ":ike-srcs",
-        ":updatable-media-srcs",
 
         // No longer part of the stubs, but are included in the docs.
         ":android-test-base-sources",
         ":android-test-mock-sources",
         ":android-test-runner-sources",
     ],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
     libs: framework_docs_only_libs,
     create_doc_stubs: true,
     annotations_enabled: true,
@@ -106,6 +100,7 @@
     merge_annotations_dirs: [
         "metalava-manual",
     ],
+    write_sdk_values: true,
 }
 
 droidstubs {
@@ -114,6 +109,24 @@
     args: metalava_framework_docs_args,
 }
 
+// Defaults module for doc-stubs targets that use module source code as input.
+// This is the default/normal.
+stubs_defaults {
+    name: "framework-doc-stubs-sources-default",
+    defaults: ["framework-doc-stubs-default"],
+    srcs: [
+        ":framework-connectivity-sources",
+        ":framework-mediaprovider-sources",
+        ":framework-permission-sources",
+        ":framework-sdkextensions-sources",
+        ":framework-statsd-sources",
+        ":framework-tethering-srcs",
+        ":framework-wifi-updatable-sources",
+        ":ike-srcs",
+        ":updatable-media-srcs",
+    ],
+}
+
 droidstubs {
     name: "android-non-updatable-doc-stubs-system",
     defaults: ["android-non-updatable-doc-stubs-defaults"],
@@ -123,26 +136,46 @@
 
 droidstubs {
     name: "framework-doc-stubs",
-    defaults: ["framework-doc-stubs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
+    defaults: ["framework-doc-stubs-sources-default"],
     args: metalava_framework_docs_args,
-    write_sdk_values: true,
 }
 
 droidstubs {
     name: "framework-doc-system-stubs",
-    defaults: ["framework-doc-stubs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
+    defaults: ["framework-doc-stubs-sources-default"],
     args: metalava_framework_docs_args +
         " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
-    write_sdk_values: true,
     api_levels_sdk_type: "system",
 }
 
+// Experimental target building doc stubs with module stub source code as input.
+// This is intended to eventually replace framework-doc-stubs, once all diffs
+// have been eliminated.
+droidstubs {
+    name: "framework-doc-stubs-module-stubs",
+    defaults: ["framework-doc-stubs-default"],
+    args: metalava_framework_docs_args,
+    srcs: [
+        ":android.net.ipsec.ike{.public.stubs.source}",
+        ":framework-connectivity{.public.stubs.source}",
+        ":framework-media{.public.stubs.source}",
+        ":framework-mediaprovider{.public.stubs.source}",
+        ":framework-permission{.public.stubs.source}",
+        ":framework-sdkextensions{.public.stubs.source}",
+        ":framework-statsd{.public.stubs.source}",
+        ":framework-tethering{.public.stubs.source}",
+        ":framework-wifi{.public.stubs.source}",
+    ],
+    aidl: {
+        local_include_dirs: [
+            "apex/media/aidl/stable",
+        ],
+        include_dirs: [
+            "packages/modules/Connectivity/framework/aidl-export",
+        ],
+    },
+}
+
 /////////////////////////////////////////////////////////////////////
 // API docs are created from the generated stub source files
 // using droiddoc
diff --git a/OWNERS b/OWNERS
index 03cfac9..ab5bd18 100644
--- a/OWNERS
+++ b/OWNERS
@@ -23,6 +23,9 @@
 # via https://android.git.corp.google.com/All-Projects/+/refs/meta/config/rules.pl.
 per-file */api/*current.txt = *
 
+# Test mapping changes can be made by anyone
+per-file */TEST_MAPPING = *
+
 # Support bulk translation updates
 per-file */res*/values*/*.xml = byi@google.com, delphij@google.com
 
diff --git a/TestProtoLibraries.bp b/TestProtoLibraries.bp
index 513d45f..afc11bb 100644
--- a/TestProtoLibraries.bp
+++ b/TestProtoLibraries.bp
@@ -30,6 +30,6 @@
         type: "full",
     },
     errorprone: {
-        javacflags: ["-Xep:MissingOverride:OFF"], // b/72714520
+        enabled: false,
     },
 }
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index 91e2074..c967e51 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -31,5 +31,6 @@
     ],
     platform_apis: true,
     test_suites: ["device-tests"],
+    data: ["trace_configs/*"],
     certificate: "platform",
 }
diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml
index 9117561..bec3cc9 100644
--- a/apct-tests/perftests/multiuser/AndroidTest.xml
+++ b/apct-tests/perftests/multiuser/AndroidTest.xml
@@ -16,14 +16,51 @@
 <configuration description="Runs MultiUserPerfTests 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="MultiUserPerfTests.apk" />
         <option name="test-file-name" value="MultiUserPerfDummyApp.apk" />
     </target_preparer>
 
+    <!-- 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_multi_user.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_multi_user.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.multiuser" />
         <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" />
+
+        <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
+
     </test>
 </configuration>
diff --git a/apct-tests/perftests/multiuser/trace_configs/trace_config_multi_user.textproto b/apct-tests/perftests/multiuser/trace_configs/trace_config_multi_user.textproto
new file mode 100644
index 0000000..93b06e8
--- /dev/null
+++ b/apct-tests/perftests/multiuser/trace_configs/trace_config_multi_user.textproto
@@ -0,0 +1,154 @@
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# proto-message: TraceConfig
+
+# Enable periodic flushing of the trace buffer into the output file.
+write_into_file: true
+
+# Writes the userspace buffer into the file every 1s.
+file_write_period_ms: 1000
+
+# See b/126487238 - we need to guarantee ordering of events.
+flush_period_ms: 10000
+
+# The trace buffers needs to be big enough to hold |file_write_period_ms| of
+# trace data. The trace buffer sizing depends on the number of trace categories
+# enabled and the device activity.
+
+# RSS events
+buffers {
+  size_kb: 32768
+  fill_policy: RING_BUFFER
+}
+
+# procfs polling
+buffers {
+  size_kb: 8192
+  fill_policy: RING_BUFFER
+}
+
+data_sources {
+  config {
+    name: "linux.ftrace"
+    target_buffer: 0
+    ftrace_config {
+      # These parameters affect only the kernel trace buffer size and how
+      # frequently it gets moved into the userspace buffer defined above.
+      buffer_size_kb: 16384
+      drain_period_ms: 250
+
+      # Store certain high-volume "sched" ftrace events in a denser format
+      # (falling back to the default format if not supported by the tracer).
+      compact_sched {
+        enabled: true
+      }
+
+      # Enables symbol name resolution against /proc/kallsyms
+      symbolize_ksyms: true
+
+      # We need to do process tracking to ensure kernel ftrace events targeted at short-lived
+      # threads are associated correctly
+      ftrace_events: "task/task_newtask"
+      ftrace_events: "task/task_rename"
+      ftrace_events: "sched/sched_process_exit"
+      ftrace_events: "sched/sched_process_free"
+
+      # Memory events
+      ftrace_events: "rss_stat"
+      ftrace_events: "ion_heap_shrink"
+      ftrace_events: "ion_heap_grow"
+      ftrace_events: "ion/ion_stat"
+      ftrace_events: "dmabuf_heap/dma_heap_stat"
+      ftrace_events: "oom_score_adj_update"
+      ftrace_events: "gpu_mem/gpu_mem_total"
+
+      # Old (kernel) LMK
+      ftrace_events: "lowmemorykiller/lowmemory_kill"
+
+      atrace_apps: "*"
+
+      atrace_categories: "am"
+      atrace_categories: "binder_driver"
+      atrace_categories: "bionic"
+      atrace_categories: "dalvik"
+      atrace_categories: "input"
+      atrace_categories: "pm"
+      atrace_categories: "res"
+      atrace_categories: "rro"
+      atrace_categories: "ss"
+      atrace_categories: "view"
+      atrace_categories: "wm"
+
+      atrace_categories: "freq"
+      atrace_categories: "sched"
+      atrace_categories: "sync"
+      atrace_categories: "workq"
+
+    }
+  }
+}
+
+data_sources: {
+  config {
+    name: "android.gpu.memory"
+    target_buffer: 0
+  }
+}
+
+data_sources {
+  config {
+    name: "linux.process_stats"
+    target_buffer: 1
+    process_stats_config {
+      proc_stats_poll_ms: 10000
+    }
+  }
+}
+
+data_sources {
+  config {
+    name: "linux.sys_stats"
+    target_buffer: 1
+    sys_stats_config {
+      meminfo_period_ms: 1000
+      meminfo_counters: MEMINFO_MEM_TOTAL
+      meminfo_counters: MEMINFO_MEM_FREE
+      meminfo_counters: MEMINFO_MEM_AVAILABLE
+      meminfo_counters: MEMINFO_BUFFERS
+      meminfo_counters: MEMINFO_CACHED
+      meminfo_counters: MEMINFO_SWAP_CACHED
+      meminfo_counters: MEMINFO_ACTIVE
+      meminfo_counters: MEMINFO_INACTIVE
+      meminfo_counters: MEMINFO_ACTIVE_ANON
+      meminfo_counters: MEMINFO_INACTIVE_ANON
+      meminfo_counters: MEMINFO_ACTIVE_FILE
+      meminfo_counters: MEMINFO_INACTIVE_FILE
+      meminfo_counters: MEMINFO_UNEVICTABLE
+      meminfo_counters: MEMINFO_SWAP_TOTAL
+      meminfo_counters: MEMINFO_SWAP_FREE
+      meminfo_counters: MEMINFO_DIRTY
+      meminfo_counters: MEMINFO_WRITEBACK
+      meminfo_counters: MEMINFO_ANON_PAGES
+      meminfo_counters: MEMINFO_MAPPED
+      meminfo_counters: MEMINFO_SHMEM
+    }
+  }
+}
+
+data_sources: {
+  config: {
+    name: "android.surfaceflinger.frametimeline"
+  }
+}
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
index ced2fb5..73f02d3 100644
--- a/apex/media/OWNERS
+++ b/apex/media/OWNERS
@@ -1,10 +1,10 @@
-andrewlewis@google.com
-aquilescanta@google.com
-chz@google.com
+# Bug component: 1344
 hdmoon@google.com
 hkuang@google.com
 jinpark@google.com
 klhyun@google.com
 lnilsson@google.com
-marcone@google.com
 sungsoo@google.com
+
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/api/Android.bp b/api/Android.bp
index fbfbc7c..0acd759 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -24,9 +24,8 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-python_binary_host {
-    name: "api_versions_trimmer",
-    srcs: ["api_versions_trimmer.py"],
+python_defaults {
+    name: "python3_version_defaults",
     version: {
         py2: {
             enabled: false,
@@ -38,6 +37,12 @@
     },
 }
 
+python_binary_host {
+    name: "api_versions_trimmer",
+    srcs: ["api_versions_trimmer.py"],
+    defaults: ["python3_version_defaults"],
+}
+
 python_test_host {
     name: "api_versions_trimmer_unittests",
     main: "api_versions_trimmer_unittests.py",
@@ -45,24 +50,35 @@
         "api_versions_trimmer_unittests.py",
         "api_versions_trimmer.py",
     ],
+    defaults: ["python3_version_defaults"],
     test_options: {
         unit_test: true,
     },
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-            embedded_launcher: false,
-        },
+}
+
+python_binary_host {
+    name: "merge_annotation_zips",
+    srcs: ["merge_annotation_zips.py"],
+    defaults: ["python3_version_defaults"],
+}
+
+python_test_host {
+    name: "merge_annotation_zips_test",
+    main: "merge_annotation_zips_test.py",
+    srcs: [
+        "merge_annotation_zips.py",
+        "merge_annotation_zips_test.py",
+    ],
+    defaults: ["python3_version_defaults"],
+    test_options: {
+        unit_test: true,
     },
 }
 
 metalava_cmd = "$(location metalava)"
 // Silence reflection warnings. See b/168689341
 metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
-metalava_cmd += " --no-banner --format=v2 "
+metalava_cmd += " --quiet --no-banner --format=v2 "
 
 genrule {
     name: "current-api-xml",
@@ -118,13 +134,13 @@
         ":android-incompatibilities.api.public.latest",
         ":frameworks-base-api-current.txt",
     ],
-    out: ["stdout.txt"],
+    out: ["updated-baseline.txt"],
     tools: ["metalava"],
     cmd: metalava_cmd +
         "--check-compatibility:api:released $(location :android.api.public.latest) " +
         "--baseline:compatibility:released $(location :android-incompatibilities.api.public.latest) " +
-        "$(location :frameworks-base-api-current.txt) " +
-        "> $(genDir)/stdout.txt",
+        "--update-baseline:compatibility:released $(genDir)/updated-baseline.txt " +
+        "$(location :frameworks-base-api-current.txt)",
 }
 
 genrule {
@@ -231,14 +247,14 @@
         ":frameworks-base-api-current.txt",
         ":frameworks-base-api-system-current.txt",
     ],
-    out: ["stdout.txt"],
+    out: ["updated-baseline.txt"],
     tools: ["metalava"],
     cmd: metalava_cmd +
         "--check-compatibility:api:released $(location :android.api.system.latest) " +
         "--check-compatibility:base $(location :frameworks-base-api-current.txt) " +
         "--baseline:compatibility:released $(location :android-incompatibilities.api.system.latest) " +
-        "$(location :frameworks-base-api-system-current.txt) " +
-        "> $(genDir)/stdout.txt",
+        "--update-baseline:compatibility:released $(genDir)/updated-baseline.txt " +
+        "$(location :frameworks-base-api-system-current.txt)",
 }
 
 genrule {
@@ -320,7 +336,7 @@
         ":frameworks-base-api-current.txt",
         ":frameworks-base-api-module-lib-current.txt",
     ],
-    out: ["stdout.txt"],
+    out: ["updated-baseline.txt"],
     tools: ["metalava"],
     cmd: metalava_cmd +
         "--check-compatibility:api:released $(location :android.api.module-lib.latest) " +
@@ -329,8 +345,8 @@
         // MODULE_LIBS -> public.
         "--check-compatibility:base $(location :frameworks-base-api-current.txt) " +
         "--baseline:compatibility:released $(location :android-incompatibilities.api.module-lib.latest) " +
-        "$(location :frameworks-base-api-module-lib-current.txt) " +
-        "> $(genDir)/stdout.txt",
+        "--update-baseline:compatibility:released $(genDir)/updated-baseline.txt " +
+        "$(location :frameworks-base-api-module-lib-current.txt)",
 }
 
 genrule {
diff --git a/api/api_versions_trimmer_unittests.py b/api/api_versions_trimmer_unittests.py
index 4eb929e..d2e5b7d 100644
--- a/api/api_versions_trimmer_unittests.py
+++ b/api/api_versions_trimmer_unittests.py
@@ -304,4 +304,4 @@
 
 
 if __name__ == "__main__":
-  unittest.main()
+  unittest.main(verbosity=2)
diff --git a/api/merge_annotation_zips.py b/api/merge_annotation_zips.py
new file mode 100755
index 0000000..9c67d7b
--- /dev/null
+++ b/api/merge_annotation_zips.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Script to merge annotation XML files (created by e.g. metalava)."""
+
+from pathlib import Path
+import sys
+import xml.etree.ElementTree as ET
+import zipfile
+
+
+def validate_xml_assumptions(root):
+  """Verify the format of the annotations XML matches expectations"""
+  prevName = ""
+  assert root.tag == 'root'
+  for child in root:
+    assert child.tag == 'item', 'unexpected tag: %s' % child.tag
+    assert list(child.attrib.keys()) == ['name'], 'unexpected attribs: %s' % child.attrib.keys()
+    assert prevName < child.get('name'), 'items unexpectedly not strictly sorted (possibly duplicate entries)'
+    prevName = child.get('name')
+
+
+def merge_xml(a, b):
+  """Merge two annotation xml files"""
+  for xml in [a, b]:
+    validate_xml_assumptions(xml)
+  a.extend(b[:])
+  a[:] = sorted(a[:], key=lambda x: x.get('name'))
+  validate_xml_assumptions(a)
+
+
+def merge_zip_file(out_dir, zip_file):
+  """Merge the content of the zip_file into out_dir"""
+  for filename in zip_file.namelist():
+    path = Path(out_dir, filename)
+    if path.exists():
+      existing_xml = ET.parse(path)
+      with zip_file.open(filename) as other_file:
+        other_xml = ET.parse(other_file)
+      merge_xml(existing_xml.getroot(), other_xml.getroot())
+      existing_xml.write(path, encoding='UTF-8', xml_declaration=True)
+    else:
+      zip_file.extract(filename, out_dir)
+
+
+def main():
+  out_dir = Path(sys.argv[1])
+  zip_filenames = sys.argv[2:]
+
+  assert not out_dir.exists()
+  out_dir.mkdir()
+  for zip_filename in zip_filenames:
+    with zipfile.ZipFile(zip_filename) as zip_file:
+      merge_zip_file(out_dir, zip_file)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/api/merge_annotation_zips_test.py b/api/merge_annotation_zips_test.py
new file mode 100644
index 0000000..26795c47
--- /dev/null
+++ b/api/merge_annotation_zips_test.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+from pathlib import Path
+import tempfile
+import unittest
+import zipfile
+
+import merge_annotation_zips
+
+
+zip_a = {
+  'android/provider/annotations.xml':
+  """<?xml version="1.0" encoding="UTF-8"?>
+<root>
+  <item name="android.provider.BlockedNumberContract boolean isBlocked(android.content.Context, java.lang.String)">
+    <annotation name="androidx.annotation.WorkerThread"/>
+  </item>
+  <item name="android.provider.SimPhonebookContract.SimRecords android.net.Uri getItemUri(int, int, int) 2">
+    <annotation name="androidx.annotation.IntRange">
+      <val name="from" val="1" />
+    </annotation>
+  </item>
+</root>""",
+  'android/os/annotations.xml':
+  """<?xml version="1.0" encoding="UTF-8"?>
+<root>
+  <item name="android.app.ActionBar void setCustomView(int) 0">
+    <annotation name="androidx.annotation.LayoutRes"/>
+  </item>
+</root>
+"""
+}
+
+zip_b = {
+  'android/provider/annotations.xml':
+  """<?xml version="1.0" encoding="UTF-8"?>
+<root>
+  <item name="android.provider.MediaStore QUERY_ARG_MATCH_FAVORITE">
+    <annotation name="androidx.annotation.IntDef">
+      <val name="value" val="{android.provider.MediaStore.MATCH_DEFAULT, android.provider.MediaStore.MATCH_INCLUDE, android.provider.MediaStore.MATCH_EXCLUDE, android.provider.MediaStore.MATCH_ONLY}" />
+      <val name="flag" val="true" />
+    </annotation>
+  </item>
+  <item name="android.provider.MediaStore QUERY_ARG_MATCH_PENDING">
+    <annotation name="androidx.annotation.IntDef">
+      <val name="value" val="{android.provider.MediaStore.MATCH_DEFAULT, android.provider.MediaStore.MATCH_INCLUDE, android.provider.MediaStore.MATCH_EXCLUDE, android.provider.MediaStore.MATCH_ONLY}" />
+      <val name="flag" val="true" />
+    </annotation>
+  </item>
+</root>"""
+}
+
+zip_c = {
+  'android/app/annotations.xml':
+  """<?xml version="1.0" encoding="UTF-8"?>
+<root>
+  <item name="android.app.ActionBar void setCustomView(int) 0">
+    <annotation name="androidx.annotation.LayoutRes"/>
+  </item>
+</root>"""
+}
+
+merged_provider = """<?xml version='1.0' encoding='UTF-8'?>
+<root>
+  <item name="android.provider.BlockedNumberContract boolean isBlocked(android.content.Context, java.lang.String)">
+    <annotation name="androidx.annotation.WorkerThread" />
+  </item>
+  <item name="android.provider.MediaStore QUERY_ARG_MATCH_FAVORITE">
+    <annotation name="androidx.annotation.IntDef">
+      <val name="value" val="{android.provider.MediaStore.MATCH_DEFAULT, android.provider.MediaStore.MATCH_INCLUDE, android.provider.MediaStore.MATCH_EXCLUDE, android.provider.MediaStore.MATCH_ONLY}" />
+      <val name="flag" val="true" />
+    </annotation>
+  </item>
+  <item name="android.provider.MediaStore QUERY_ARG_MATCH_PENDING">
+    <annotation name="androidx.annotation.IntDef">
+      <val name="value" val="{android.provider.MediaStore.MATCH_DEFAULT, android.provider.MediaStore.MATCH_INCLUDE, android.provider.MediaStore.MATCH_EXCLUDE, android.provider.MediaStore.MATCH_ONLY}" />
+      <val name="flag" val="true" />
+    </annotation>
+  </item>
+<item name="android.provider.SimPhonebookContract.SimRecords android.net.Uri getItemUri(int, int, int) 2">
+    <annotation name="androidx.annotation.IntRange">
+      <val name="from" val="1" />
+    </annotation>
+  </item>
+</root>"""
+
+
+
+class MergeAnnotationZipsTest(unittest.TestCase):
+
+  def test_merge_zips(self):
+    with tempfile.TemporaryDirectory() as out_dir:
+      for zip_content in [zip_a, zip_b, zip_c]:
+        f = io.BytesIO()
+        with zipfile.ZipFile(f, "w") as zip_file:
+          for filename, content in zip_content.items():
+            zip_file.writestr(filename, content)
+          merge_annotation_zips.merge_zip_file(out_dir, zip_file)
+
+      # Unchanged
+      self.assertEqual(zip_a['android/os/annotations.xml'], Path(out_dir, 'android/os/annotations.xml').read_text())
+      self.assertEqual(zip_c['android/app/annotations.xml'], Path(out_dir, 'android/app/annotations.xml').read_text())
+
+      # Merged
+      self.assertEqual(merged_provider, Path(out_dir, 'android/provider/annotations.xml').read_text())
+
+
+if __name__ == "__main__":
+  unittest.main(verbosity=2)
diff --git a/cmds/bootanimation/OWNERS b/cmds/bootanimation/OWNERS
new file mode 100644
index 0000000..b6fb007
--- /dev/null
+++ b/cmds/bootanimation/OWNERS
@@ -0,0 +1,3 @@
+dupin@google.com
+shanh@google.com
+jreck@google.com
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index aad5d23..5370dc3 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -56,9 +56,6 @@
         "-readability-redundant-access-specifiers",
         "-readability-uppercase-literal-suffix",
     ],
-    tidy_flags: [
-        "-system-headers",
-    ],
 }
 
 cc_library {
diff --git a/cmds/idmap2/include/idmap2/FileUtils.h b/cmds/idmap2/include/idmap2/FileUtils.h
index c4e0e1f..8fcaeb1 100644
--- a/cmds/idmap2/include/idmap2/FileUtils.h
+++ b/cmds/idmap2/include/idmap2/FileUtils.h
@@ -17,6 +17,8 @@
 #ifndef IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
 #define IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
 
+#include <sys/types.h>
+
 #include <string>
 
 namespace android::idmap2::utils {
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index e7e9e4c..a1206f9 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -93,7 +93,7 @@
                                "--idmap-path", GetIdmapPath()});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
 
   struct stat st;
   ASSERT_EQ(stat(GetIdmapPath().c_str(), &st), 0);
@@ -119,7 +119,7 @@
                                "--idmap-path", GetIdmapPath()});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -127,14 +127,14 @@
                           "--idmap-path", GetIdmapPath()});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
-  ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000"),
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
+  ASSERT_NE(result->stdout_str.find(R::target::integer::literal::int1 + " -> 0x7f010000"),
             std::string::npos);
-  ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000"),
+  ASSERT_NE(result->stdout_str.find(R::target::string::literal::str1 + " -> 0x7f020000"),
             std::string::npos);
-  ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001"),
+  ASSERT_NE(result->stdout_str.find(R::target::string::literal::str3 + " -> 0x7f020001"),
             std::string::npos);
-  ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002"),
+  ASSERT_NE(result->stdout_str.find(R::target::string::literal::str4 + " -> 0x7f020002"),
             std::string::npos);
 
   // clang-format off
@@ -144,8 +144,8 @@
                           "--idmap-path", GetIdmapPath()});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
-  ASSERT_NE(result->stdout.find("00000000: 504d4449  magic"), std::string::npos);
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
+  ASSERT_NE(result->stdout_str.find("00000000: 504d4449  magic"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -170,7 +170,7 @@
                                "--idmap-path", GetIdmapPath()});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -180,9 +180,9 @@
                           "--resid", R::target::string::literal::str1});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
-  ASSERT_NE(result->stdout.find("overlay-1"), std::string::npos);
-  ASSERT_EQ(result->stdout.find("overlay-1-sv"), std::string::npos);
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
+  ASSERT_NE(result->stdout_str.find("overlay-1"), std::string::npos);
+  ASSERT_EQ(result->stdout_str.find("overlay-1-sv"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -192,9 +192,9 @@
                           "--resid", "test.target:string/str1"});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
-  ASSERT_NE(result->stdout.find("overlay-1"), std::string::npos);
-  ASSERT_EQ(result->stdout.find("overlay-1-sv"), std::string::npos);
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
+  ASSERT_NE(result->stdout_str.find("overlay-1"), std::string::npos);
+  ASSERT_EQ(result->stdout_str.find("overlay-1-sv"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -204,8 +204,8 @@
                           "--resid", "test.target:string/str1"});
   // clang-format on
   ASSERT_THAT(result, NotNull());
-  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
-  ASSERT_NE(result->stdout.find("overlay-1-sv"), std::string::npos);
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr_str;
+  ASSERT_NE(result->stdout_str.find("overlay-1-sv"), std::string::npos);
 
   unlink(GetIdmapPath().c_str());
 }
diff --git a/core/api/current.txt b/core/api/current.txt
index fb7d986..e4e7d4e 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -954,7 +954,7 @@
     field public static final int measureWithLargestChild = 16843476; // 0x10102d4
     field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
     field public static final int mediaRouteTypes = 16843694; // 0x10103ae
-    field public static final int memtagMode = 16844313; // 0x1010619
+    field public static final int memtagMode = 16844324; // 0x1010624
     field public static final int menuCategory = 16843230; // 0x10101de
     field public static final int mimeGroup = 16844309; // 0x1010615
     field public static final int mimeType = 16842790; // 0x1010026
@@ -978,7 +978,7 @@
     field public static final int multiArch = 16843918; // 0x101048e
     field public static final int multiprocess = 16842771; // 0x1010013
     field public static final int name = 16842755; // 0x1010003
-    field public static final int nativeHeapZeroInitialized = 16844314; // 0x101061a
+    field public static final int nativeHeapZeroInitialized = 16844325; // 0x1010625
     field public static final int navigationBarColor = 16843858; // 0x1010452
     field public static final int navigationBarDividerColor = 16844141; // 0x101056d
     field public static final int navigationContentDescription = 16843969; // 0x10104c1
@@ -8657,6 +8657,15 @@
     field public static final int TELEPHONY = 4194304; // 0x400000
   }
 
+  public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+    method public void close();
+    method protected void finalize();
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
+    field @RequiresPermission(android.Manifest.permission.BLUETOOTH) public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED = "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
+  }
+
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
@@ -8703,6 +8712,7 @@
     field public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
     field public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
     field public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
+    field public static final String EXTRA_IS_COORDINATED_SET_MEMBER = "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER";
     field public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
     field public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
     field public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT";
@@ -8756,6 +8766,7 @@
     field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f
     field public static final int GATT_FAILURE = 257; // 0x101
     field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
+    field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8
     field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
     field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd
     field public static final int GATT_INVALID_OFFSET = 7; // 0x7
@@ -9082,6 +9093,7 @@
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionState(android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
     field public static final int A2DP = 2; // 0x2
+    field public static final int CSIP_SET_COORDINATOR = 25; // 0x19
     field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE";
     field public static final String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
     field public static final int GATT = 7; // 0x7
@@ -29934,6 +29946,11 @@
     ctor public OperationCanceledException(String);
   }
 
+  public interface OutcomeReceiver<R, E extends java.lang.Throwable> {
+    method public default void onError(@NonNull E);
+    method public void onResult(@NonNull R);
+  }
+
   public final class Parcel {
     method public void appendFrom(android.os.Parcel, int, int);
     method @Nullable public android.os.IBinder[] createBinderArray();
@@ -30328,6 +30345,7 @@
     method public void close();
     method @NonNull public static android.os.SharedMemory create(@Nullable String, int) throws android.system.ErrnoException;
     method public int describeContents();
+    method @NonNull public static android.os.SharedMemory fromFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
     method public int getSize();
     method @NonNull public java.nio.ByteBuffer map(int, int, int) throws android.system.ErrnoException;
     method @NonNull public java.nio.ByteBuffer mapReadOnly() throws android.system.ErrnoException;
@@ -38093,6 +38111,7 @@
     method public final void cancelCall();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onPlaceCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
+    method public void onRedirectionTimeout();
     method public final boolean onUnbind(@NonNull android.content.Intent);
     method public final void placeCallUnmodified();
     method public final void redirectCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
@@ -40287,12 +40306,6 @@
     field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1
   }
 
-  public final class PhoneCapability 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.telephony.PhoneCapability> CREATOR;
-  }
-
   public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
     ctor public PhoneNumberFormattingTextWatcher();
     ctor public PhoneNumberFormattingTextWatcher(String);
@@ -41033,6 +41046,7 @@
     method public String getNetworkOperator();
     method public String getNetworkOperatorName();
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getNetworkSelectionMode();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getNetworkSlicingConfiguration(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.data.SlicingConfig,android.telephony.TelephonyManager.SlicingException>);
     method public String getNetworkSpecifier();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType();
     method @Deprecated public int getPhoneCount();
@@ -41266,6 +41280,13 @@
     field public static final int ERROR_TIMEOUT = 1; // 0x1
   }
 
+  public static class TelephonyManager.SlicingException extends java.lang.Exception {
+    ctor public TelephonyManager.SlicingException(int);
+    method public int getErrorCode();
+    field public static final int ERROR_MODEM_ERROR = 2; // 0x2
+    field public static final int ERROR_TIMEOUT = 1; // 0x1
+  }
+
   public abstract static class TelephonyManager.UssdResponseCallback {
     ctor public TelephonyManager.UssdResponseCallback();
     method public void onReceiveUssdResponse(android.telephony.TelephonyManager, String, CharSequence);
@@ -41441,6 +41462,88 @@
     method @NonNull public android.telephony.data.ApnSetting.Builder setUser(@Nullable String);
   }
 
+  public final class NetworkSliceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0xffffffff, to=0xfffffe) public int getMappedHplmnSliceDifferentiator();
+    method public int getMappedHplmnSliceServiceType();
+    method @IntRange(from=0xffffffff, to=0xfffffe) public int getSliceDifferentiator();
+    method public int getSliceServiceType();
+    method public int getStatus();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.NetworkSliceInfo> CREATOR;
+    field public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; // 0xffffffff
+    field public static final int SLICE_SERVICE_TYPE_EMBB = 1; // 0x1
+    field public static final int SLICE_SERVICE_TYPE_MIOT = 3; // 0x3
+    field public static final int SLICE_SERVICE_TYPE_NONE = 0; // 0x0
+    field public static final int SLICE_SERVICE_TYPE_URLLC = 2; // 0x2
+    field public static final int SLICE_STATUS_ALLOWED = 2; // 0x2
+    field public static final int SLICE_STATUS_CONFIGURED = 1; // 0x1
+    field public static final int SLICE_STATUS_DEFAULT_CONFIGURED = 5; // 0x5
+    field public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3; // 0x3
+    field public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA = 4; // 0x4
+    field public static final int SLICE_STATUS_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class NetworkSliceInfo.Builder {
+    ctor public NetworkSliceInfo.Builder();
+    method @NonNull public android.telephony.data.NetworkSliceInfo build();
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=0xffffffff, to=0xfffffe) int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceServiceType(int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceDifferentiator(@IntRange(from=0xffffffff, to=0xfffffe) int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceServiceType(int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setStatus(int);
+  }
+
+  public final class RouteSelectionDescriptor implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getDataNetworkName();
+    method @IntRange(from=0x0, to=0xff) public int getPrecedence();
+    method public int getSessionType();
+    method @NonNull public java.util.List<android.telephony.data.NetworkSliceInfo> getSliceInfo();
+    method public int getSscMode();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.RouteSelectionDescriptor> CREATOR;
+    field public static final int ROUTE_SSC_MODE_1 = 1; // 0x1
+    field public static final int ROUTE_SSC_MODE_2 = 2; // 0x2
+    field public static final int ROUTE_SSC_MODE_3 = 3; // 0x3
+    field public static final int SESSION_TYPE_IPV4 = 0; // 0x0
+    field public static final int SESSION_TYPE_IPV4V6 = 2; // 0x2
+    field public static final int SESSION_TYPE_IPV6 = 1; // 0x1
+  }
+
+  public final class SlicingConfig implements android.os.Parcelable {
+    ctor public SlicingConfig();
+    method public int describeContents();
+    method @NonNull public java.util.List<android.telephony.data.NetworkSliceInfo> getSliceInfo();
+    method @NonNull public java.util.List<android.telephony.data.UrspRule> getUrspRules();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.SlicingConfig> CREATOR;
+  }
+
+  public final class TrafficDescriptor implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public String getDataNetworkName();
+    method @Nullable public String getOsAppId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.TrafficDescriptor> CREATOR;
+  }
+
+  public static final class TrafficDescriptor.Builder {
+    ctor public TrafficDescriptor.Builder();
+    method @NonNull public android.telephony.data.TrafficDescriptor build();
+    method @NonNull public android.telephony.data.TrafficDescriptor.Builder setDataNetworkName(@NonNull String);
+    method @NonNull public android.telephony.data.TrafficDescriptor.Builder setOsAppId(@NonNull String);
+  }
+
+  public final class UrspRule implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0x0, to=0xff) public int getPrecedence();
+    method @NonNull public java.util.List<android.telephony.data.RouteSelectionDescriptor> getRouteSelectionDescriptor();
+    method @NonNull public java.util.List<android.telephony.data.TrafficDescriptor> getTrafficDescriptors();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.UrspRule> CREATOR;
+  }
+
 }
 
 package android.telephony.emergency {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 5d23eb2..66d6124 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -121,7 +121,7 @@
   }
 
   public static class Build.VERSION {
-    field public static final int FIRST_SDK_INT;
+    field public static final int DEVICE_INITIAL_SDK_INT;
   }
 
   public interface Parcelable {
@@ -132,6 +132,11 @@
     field public static final int VPN_UID = 1016; // 0x3f8
   }
 
+  public final class ServiceManager {
+    method public static boolean isDeclared(@NonNull String);
+    method @Nullable public static android.os.IBinder waitForDeclaredService(@NonNull String);
+  }
+
   public class StatsServiceManager {
     method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer();
     method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer();
@@ -155,6 +160,11 @@
     method public static int getNumSignalStrengthLevels();
   }
 
+  public class SubscriptionManager {
+    method public void addSubscriptionInfoRecord(@NonNull String, @Nullable String, int, int);
+    method public void removeSubscriptionInfoRecord(@NonNull String, int);
+  }
+
   public class TelephonyManager {
     method @NonNull public static int[] getAllNetworkTypes();
   }
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 9a8591d..e601583 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1507,9 +1507,26 @@
     method public void onOobData(int, @NonNull android.bluetooth.OobData);
   }
 
+  public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
+    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.Map getGroupUuidMapByDevice(@Nullable android.bluetooth.BluetoothDevice);
+    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.UUID groupLock(int, @Nullable java.util.concurrent.Executor, @Nullable android.bluetooth.BluetoothCsipSetCoordinator.ClientLockCallback);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean groupUnlock(@NonNull java.util.UUID);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
+    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_DEVICE_AVAILABLE = "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
+    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE = "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
+  }
+
+  public static interface BluetoothCsipSetCoordinator.ClientLockCallback {
+    method public void onGroupLockSet(int, int, boolean);
+  }
+
   public final class BluetoothDevice implements android.os.Parcelable {
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean cancelBondProcess();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond(int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean fetchUuidsWithSdp(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getSimAccessPermission();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isConnected();
@@ -1559,7 +1576,10 @@
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connect(android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnect(android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean startScoUsingVirtualVoiceCall();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean stopScoUsingVirtualVoiceCall();
   }
 
   public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
@@ -1643,7 +1663,9 @@
     field @NonNull public static final android.os.ParcelUuid AVRCP_TARGET;
     field @NonNull public static final android.os.ParcelUuid BASE_UUID;
     field @NonNull public static final android.os.ParcelUuid BNEP;
+    field @NonNull public static final android.os.ParcelUuid COORDINATED_SET;
     field @NonNull public static final android.os.ParcelUuid DIP;
+    field @NonNull public static final android.os.ParcelUuid GENERIC_MEDIA_CONTROL;
     field @NonNull public static final android.os.ParcelUuid HEARING_AID;
     field @NonNull public static final android.os.ParcelUuid HFP;
     field @NonNull public static final android.os.ParcelUuid HFP_AG;
@@ -1654,6 +1676,7 @@
     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 MEDIA_CONTROL;
     field @NonNull public static final android.os.ParcelUuid MNS;
     field @NonNull public static final android.os.ParcelUuid NAP;
     field @NonNull public static final android.os.ParcelUuid OBEX_OBJECT_PUSH;
@@ -6823,6 +6846,10 @@
   public final class BatteryStatsManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanReset();
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanResults(@NonNull android.os.WorkSource, int);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStarted(@NonNull android.os.WorkSource, boolean);
+    method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStopped(@NonNull android.os.WorkSource, boolean);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int);
@@ -7233,6 +7260,7 @@
   public class SystemConfigManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
+    method @NonNull public java.util.List<java.lang.String> getEnabledComponentOverrides(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public int[] getSystemPermissionUids(@NonNull String);
   }
 
@@ -7269,8 +7297,10 @@
     method public boolean bind(android.os.UpdateEngineCallback);
     method public void cancel();
     method @WorkerThread public int cleanupAppliedPayload();
+    method public void resetShouldSwitchSlotOnReboot();
     method public void resetStatus();
     method public void resume();
+    method public void setShouldSwitchSlotOnReboot(@NonNull String);
     method public void suspend();
     method public boolean unbind();
     method public boolean verifyPayloadMetadata(String);
@@ -7760,6 +7790,7 @@
     field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
     field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
     field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
+    field public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native";
     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";
@@ -9660,6 +9691,25 @@
     field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
+    method public long getIdleTimeMillis();
+    method public static int getNumTxPowerLevels();
+    method public long getReceiveTimeMillis();
+    method public long getSleepTimeMillis();
+    method public long getTimestampMillis();
+    method public long getTransmitDurationMillisAtPowerLevel(int);
+    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+  }
+
   public final class NetworkRegistrationInfo implements android.os.Parcelable {
     method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
     method public int getRegistrationState();
@@ -9749,6 +9799,17 @@
     field public static final int REASON_UNSPECIFIED = 0; // 0x0
   }
 
+  public final class PhoneCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public int[] getDeviceNrCapabilities();
+    method @IntRange(from=1) public int getMaxActiveDataSubscriptions();
+    method @IntRange(from=1) public int getMaxActiveVoiceSubscriptions();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
+    field public static final int DEVICE_NR_CAPABILITY_NSA = 1; // 0x1
+    field public static final int DEVICE_NR_CAPABILITY_SA = 2; // 0x2
+  }
+
   public final class PhoneNumberRange implements android.os.Parcelable {
     ctor public PhoneNumberRange(@NonNull String, @NonNull String, @NonNull String, @NonNull String);
     method public int describeContents();
@@ -10268,6 +10329,7 @@
     method public int getMaxNumberOfSimultaneouslyActiveSims();
     method public static long getMaxNumberVerificationTimeoutMillis();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.PhoneCapability getPhoneCapability();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
@@ -10314,6 +10376,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
@@ -10486,6 +10549,14 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
+  public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
+    method public int getErrorCode();
+    field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2
+    field public static final int ERROR_MODEM_RESPONSE_ERROR = 3; // 0x3
+    field public static final int ERROR_PHONE_NOT_AVAILABLE = 1; // 0x1
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+  }
+
   public final class ThermalMitigationRequest implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.telephony.DataThrottlingRequest getDataThrottlingRequest();
@@ -10610,7 +10681,7 @@
     method public int getPduSessionId();
     method public int getProtocolType();
     method public long getRetryDurationMillis();
-    method @Nullable public android.telephony.data.SliceInfo getSliceInfo();
+    method @Nullable public android.telephony.data.NetworkSliceInfo getSliceInfo();
     method @Deprecated public int getSuggestedRetryTime();
     method @NonNull public java.util.List<android.telephony.data.TrafficDescriptor> getTrafficDescriptors();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10646,7 +10717,7 @@
     method @NonNull public android.telephony.data.DataCallResponse.Builder setPduSessionId(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
-    method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
+    method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.NetworkSliceInfo);
     method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setTrafficDescriptors(@NonNull java.util.List<android.telephony.data.TrafficDescriptor>);
   }
@@ -10719,7 +10790,7 @@
     method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
-    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @Nullable android.telephony.data.TrafficDescriptor, boolean, @NonNull android.telephony.data.DataServiceCallback);
+    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.NetworkSliceInfo, @Nullable android.telephony.data.TrafficDescriptor, boolean, @NonNull android.telephony.data.DataServiceCallback);
   }
 
   public class DataServiceCallback {
@@ -10777,32 +10848,6 @@
     method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
   }
 
-  public final class SliceInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator();
-    method public int getMappedHplmnSliceServiceType();
-    method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getSliceDifferentiator();
-    method public int getSliceServiceType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.SliceInfo> CREATOR;
-    field public static final int MAX_SLICE_DIFFERENTIATOR = 16777214; // 0xfffffe
-    field public static final int MIN_SLICE_DIFFERENTIATOR = -1; // 0xffffffff
-    field public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; // 0xffffffff
-    field public static final int SLICE_SERVICE_TYPE_EMBB = 1; // 0x1
-    field public static final int SLICE_SERVICE_TYPE_MIOT = 3; // 0x3
-    field public static final int SLICE_SERVICE_TYPE_NONE = 0; // 0x0
-    field public static final int SLICE_SERVICE_TYPE_URLLC = 2; // 0x2
-  }
-
-  public static final class SliceInfo.Builder {
-    ctor public SliceInfo.Builder();
-    method @NonNull public android.telephony.data.SliceInfo build();
-    method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
-    method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceServiceType(int);
-    method @NonNull public android.telephony.data.SliceInfo.Builder setSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
-    method @NonNull public android.telephony.data.SliceInfo.Builder setSliceServiceType(int);
-  }
-
   public final class ThrottleStatus implements android.os.Parcelable {
     method public int describeContents();
     method public int getApnType();
@@ -10831,15 +10876,6 @@
     method @NonNull public android.telephony.data.ThrottleStatus.Builder setTransportType(int);
   }
 
-  public final class TrafficDescriptor implements android.os.Parcelable {
-    ctor public TrafficDescriptor(@Nullable String, @Nullable String);
-    method public int describeContents();
-    method @Nullable public String getDnn();
-    method @Nullable public String getOsAppId();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.TrafficDescriptor> CREATOR;
-  }
-
 }
 
 package android.telephony.euicc {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 3b759a2..d905bbe 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1037,7 +1037,7 @@
 
   public static class Build.VERSION {
     field public static final String[] ACTIVE_CODENAMES;
-    field public static final int FIRST_SDK_INT;
+    field public static final int DEVICE_INITIAL_SDK_INT;
     field public static final int RESOURCES_SDK_INT;
   }
 
@@ -1649,6 +1649,28 @@
     field public static final String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
+    method public int describeContents();
+    method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
+    method public long getIdleTimeMillis();
+    method public static int getNumTxPowerLevels();
+    method public long getReceiveTimeMillis();
+    method public long getSleepTimeMillis();
+    method public long getTimestampMillis();
+    method public long getTransmitDurationMillisAtPowerLevel(int);
+    method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
+    method public boolean isEmpty();
+    method public boolean isValid();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+    field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+    field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+    field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+    field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+  }
+
   public class PhoneNumberUtils {
     method public static int getMinMatchForTest();
     method public static void setMinMatchForTest(int);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 7ad5e05..949ba6a 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -285,6 +285,23 @@
     },
 }
 
+aidl_interface {
+    name: "android.debug_aidl",
+    unstable: true,
+    srcs: [
+        "android/debug/AdbTransportType.aidl",
+        "android/debug/FingerprintAndPairDevice.aidl",
+        "android/debug/IAdbCallback.aidl",
+        "android/debug/IAdbManager.aidl",
+        "android/debug/PairDevice.aidl",
+    ],
+    backend: {
+        cpp: {
+            enabled: true,
+        },
+    },
+}
+
 // Avoid including Parcelable classes as we don't want to have two copies of
 // Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
 // and TeleService app (packages/services/Telephony).
@@ -324,6 +341,27 @@
     ],
 }
 
+java_library {
+    name: "modules-utils-statemachine",
+    srcs: [
+        "com/android/internal/util/IState.java",
+        "com/android/internal/util/State.java",
+        "com/android/internal/util/StateMachine.java",
+    ],
+    libs: [
+        "framework-annotations-lib",
+        "unsupportedappusage",
+    ],
+    sdk_version: "module_current",
+    min_sdk_version: "29",
+
+    visibility: ["//visibility:public"],
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
+}
+
 filegroup {
     name: "framework-ims-common-shared-srcs",
     srcs: [
@@ -348,10 +386,7 @@
         "android/util/Rational.java",
         "com/android/internal/util/FastXmlSerializer.java",
         "com/android/internal/util/HexDump.java",
-        "com/android/internal/util/IState.java",
         "com/android/internal/util/MessageUtils.java",
-        "com/android/internal/util/State.java",
-        "com/android/internal/util/StateMachine.java",
         "com/android/internal/util/WakeupMessage.java",
     ],
     visibility: [
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index ce68e08..fb9ef53 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -105,12 +105,15 @@
         String statusToken);
 
     /* Returns Map<String, Integer> from package name to visibility with all values stored for given account */
+    @SuppressWarnings(value = {"untyped-collection"})
     Map getPackagesAndVisibilityForAccount(in Account account);
+    @SuppressWarnings(value = {"untyped-collection"})
     boolean addAccountExplicitlyWithVisibility(in Account account, String password, in Bundle extras,
             in Map visibility);
     boolean setAccountVisibility(in Account a, in String packageName, int newVisibility);
     int getAccountVisibility(in Account a, in String packageName);
     /* Type may be null returns Map <Account, Integer>*/
+    @SuppressWarnings(value = {"untyped-collection"})
     Map getAccountsAndVisibilityForPackage(in String packageName, in String accountType);
 
     void registerAccountListener(in String[] accountTypes, String opPackageName);
diff --git a/core/java/android/annotation/SuppressLint.java b/core/java/android/annotation/SuppressLint.java
new file mode 100644
index 0000000..2d3456b
--- /dev/null
+++ b/core/java/android/annotation/SuppressLint.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Indicates that Lint should ignore the specified warnings for the annotated element. */
+@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
+@Retention(RetentionPolicy.CLASS)
+public @interface SuppressLint {
+    /**
+     * The set of warnings (identified by the lint issue id) that should be
+     * ignored by lint. It is not an error to specify an unrecognized name.
+     */
+    String[] value();
+}
diff --git a/core/java/android/annotation/TargetApi.java b/core/java/android/annotation/TargetApi.java
new file mode 100644
index 0000000..975318e
--- /dev/null
+++ b/core/java/android/annotation/TargetApi.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Indicates that Lint should treat this type as targeting a given API level, no matter what the
+    project target is. */
+@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
+@Retention(RetentionPolicy.CLASS)
+public @interface TargetApi {
+    /**
+     * This sets the target api level for the type..
+     */
+    int value();
+}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 193f775..749e8f5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -352,11 +352,12 @@
     @UnsupportedAppUsage
     Configuration mConfiguration;
     Configuration mCompatConfiguration;
+    @GuardedBy("this")
+    private boolean mUpdateHttpProxyOnBind = false;
     @UnsupportedAppUsage
     Application mInitialApplication;
     @UnsupportedAppUsage
-    final ArrayList<Application> mAllApplications
-            = new ArrayList<Application>();
+    final ArrayList<Application> mAllApplications = new ArrayList<>();
     /**
      * Bookkeeping of instantiated backup agents indexed first by user id, then by package name.
      * Indexing by user id supports parallel backups across users on system packages as they run in
@@ -1127,8 +1128,18 @@
         }
 
         public void updateHttpProxy() {
-            ActivityThread.updateHttpProxy(
-                    getApplication() != null ? getApplication() : getSystemContext());
+            final Application app;
+            synchronized (ActivityThread.this) {
+                app = getApplication();
+                if (null == app) {
+                    // The app is not bound yet. Make a note to update the HTTP proxy when the
+                    // app is bound.
+                    mUpdateHttpProxyOnBind = true;
+                    return;
+                }
+            }
+            // App is present, update the proxy inline.
+            ActivityThread.updateHttpProxy(app);
         }
 
         public void processInBackground() {
@@ -6288,7 +6299,13 @@
             final File cacheDir = context.getCacheDir();
             if (cacheDir != null) {
                 // Provide a usable directory for temporary files
-                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+                String tmpdir = cacheDir.getAbsolutePath();
+                System.setProperty("java.io.tmpdir", tmpdir);
+                try {
+                    android.system.Os.setenv("TMPDIR", tmpdir, true);
+                } catch (ErrnoException ex) {
+                    Log.w(TAG, "Unable to initialize $TMPDIR", ex);
+                }
             } else {
                 Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
                         + "due to missing cache directory");
@@ -6697,6 +6714,15 @@
             app.setContentCaptureOptions(data.contentCaptureOptions);
 
             mInitialApplication = app;
+            final boolean updateHttpProxy;
+            synchronized (this) {
+                updateHttpProxy = mUpdateHttpProxyOnBind;
+                // This synchronized block ensures that any subsequent call to updateHttpProxy()
+                // will see a non-null mInitialApplication.
+            }
+            if (updateHttpProxy) {
+                ActivityThread.updateHttpProxy(app);
+            }
 
             // don't bring up providers in restricted mode; they may depend on the
             // app's custom Application class
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 71b28fb..6c435b9 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -54,7 +54,7 @@
  * @see android.support.v4.app.JobIntentService
  *
  * @deprecated IntentService is subject to all the
- *   <a href="/preview/features/background.html">background execution limits</a>
+ *   <a href="{@docRoot}about/versions/oreo/background.html">background execution limits</a>
  *   imposed with Android 8.0 (API level 26). Consider using {@link androidx.work.WorkManager}
  *   or {@link androidx.core.app.JobIntentService}, which uses jobs
  *   instead of services when running on Android 8.0 or higher.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3ad8b4b..d28e489 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -223,14 +223,14 @@
     void addCrossProfileIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
     void clearCrossProfileIntentFilters(in ComponentName admin);
 
-    boolean setPermittedAccessibilityServices(in ComponentName admin,in List packageList);
-    List getPermittedAccessibilityServices(in ComponentName admin);
-    List getPermittedAccessibilityServicesForUser(int userId);
+    boolean setPermittedAccessibilityServices(in ComponentName admin,in List<String> packageList);
+    List<String> getPermittedAccessibilityServices(in ComponentName admin);
+    List<String> getPermittedAccessibilityServicesForUser(int userId);
     boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
-    boolean setPermittedInputMethods(in ComponentName admin,in List packageList);
-    List getPermittedInputMethods(in ComponentName admin);
-    List getPermittedInputMethodsForCurrentUser();
+    boolean setPermittedInputMethods(in ComponentName admin,in List<String> packageList);
+    List<String> getPermittedInputMethods(in ComponentName admin);
+    List<String> getPermittedInputMethodsForCurrentUser();
     boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
     boolean setPermittedCrossProfileNotificationListeners(in ComponentName admin, in List<String> packageList);
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 4d73a61..6d777cf 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -171,9 +171,9 @@
         mLaunchCount = stats.mLaunchCount;
         mAppLaunchCount = stats.mAppLaunchCount;
         mLastEvent = stats.mLastEvent;
-        mActivities = stats.mActivities;
-        mForegroundServices = stats.mForegroundServices;
-        mChooserCounts = stats.mChooserCounts;
+        mActivities = stats.mActivities.clone();
+        mForegroundServices = new ArrayMap<>(stats.mForegroundServices);
+        mChooserCounts = new ArrayMap<>(stats.mChooserCounts);
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 16413e1..4dcb3dc 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -946,6 +946,10 @@
     public boolean setBufferLengthMillis(@BluetoothCodecConfig.SourceCodecType int codec,
             int value) {
         if (VDBG) log("setBufferLengthMillis(" + codec + ", " + value + ")");
+        if (value < 0) {
+            Log.e(TAG, "Trying to set audio buffer length to a negative value: " + value);
+            return false;
+        }
         try {
             final IBluetoothA2dp service = getService();
             if (service != null && isEnabled()) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ce38486..313dd3e 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2819,6 +2819,10 @@
         } else if (profile == BluetoothProfile.VOLUME_CONTROL) {
             BluetoothVolumeControl vcs = new BluetoothVolumeControl(context, listener, this);
             return true;
+        } else if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) {
+            BluetoothCsipSetCoordinator csipSetCoordinator =
+                    new BluetoothCsipSetCoordinator(context, listener);
+            return true;
         } else {
             return false;
         }
@@ -2908,6 +2912,11 @@
                 BluetoothVolumeControl vcs = (BluetoothVolumeControl) proxy;
                 vcs.close();
                 break;
+            case BluetoothProfile.CSIP_SET_COORDINATOR:
+                BluetoothCsipSetCoordinator csipSetCoordinator =
+                        (BluetoothCsipSetCoordinator) proxy;
+                csipSetCoordinator.close();
+                break;
         }
     }
 
@@ -3289,22 +3298,22 @@
     }
 
     /**
-     * Determines whether a String Bluetooth address, such as "00:43:A8:23:10:F0"
+     * Determines whether a String Bluetooth address, such as "F0:43:A8:23:10:00"
      * is a RANDOM STATIC address.
      *
-     * RANDOM STATIC: (addr & 0b11) == 0b11
-     * RANDOM RESOLVABLE: (addr & 0b11) == 0b10
-     * RANDOM non-RESOLVABLE: (addr & 0b11) == 0b00
+     * RANDOM STATIC: (addr & 0xC0) == 0xC0
+     * RANDOM RESOLVABLE: (addr &  0xC0) == 0x40
+     * RANDOM non-RESOLVABLE: (addr &  0xC0) == 0x00
      *
      * @param address Bluetooth address as string
-     * @return true if the 2 Least Significant Bits of the address equals 0b11.
+     * @return true if the 2 Most Significant Bits of the address equals 0xC0.
      *
      * @hide
      */
     public static boolean isAddressRandomStatic(@NonNull String address) {
         requireNonNull(address);
         return checkBluetoothAddress(address)
-                && (Integer.parseInt(address.split(":")[5], 16) & 0b11) == 0b11;
+                && (Integer.parseInt(address.split(":")[0], 16) & 0xC0) == 0xC0;
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
new file mode 100644
index 0000000..cb542e5
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
@@ -0,0 +1,550 @@
+/*
+ * Copyright 2021 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.CloseGuard;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides the public APIs to control the Bluetooth CSIP set coordinator.
+ *
+ * <p>BluetoothCsipSetCoordinator is a proxy object for controlling the Bluetooth VC
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothCsipSetCoordinator proxy object.
+ *
+ */
+public final class BluetoothCsipSetCoordinator implements BluetoothProfile, AutoCloseable {
+    private static final String TAG = "BluetoothCsipSetCoordinator";
+    private static final boolean DBG = false;
+    private static final boolean VDBG = false;
+
+    private CloseGuard mCloseGuard;
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public interface ClientLockCallback {
+        /**
+         * @hide
+         */
+        @SystemApi void onGroupLockSet(int groupId, int opStatus, boolean isLocked);
+    }
+
+    private static class BluetoothCsipSetCoordinatorLockCallbackDelegate
+            extends IBluetoothCsipSetCoordinatorLockCallback.Stub {
+        private final ClientLockCallback mCallback;
+        private final Executor mExecutor;
+
+        BluetoothCsipSetCoordinatorLockCallbackDelegate(
+                Executor executor, ClientLockCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void onGroupLockSet(int groupId, int opStatus, boolean isLocked) {
+            mExecutor.execute(() -> mCallback.onGroupLockSet(groupId, opStatus, isLocked));
+        }
+    };
+
+    /**
+     * Intent used to broadcast the change in connection state of the CSIS
+     * Client.
+     *
+     * <p>This intent will have 3 extras:
+     * <ul>
+     * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+     * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+     * </ul>
+     *
+     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+     */
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED =
+            "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
+
+    /**
+     * Intent used to expose broadcast receiving device.
+     *
+     * <p>This intent will have 2 extras:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Broadcast receiver device. </li>
+     * <li> {@link #EXTRA_CSIS_GROUP_ID} - Group identifier. </li>
+     * <li> {@link #EXTRA_CSIS_GROUP_SIZE} - Group size. </li>
+     * <li> {@link #EXTRA_CSIS_GROUP_TYPE_UUID} - Group type UUID. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CSIS_DEVICE_AVAILABLE =
+            "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
+
+    /**
+     * Used as an extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
+     * Contains the group id.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CSIS_GROUP_ID = "android.bluetooth.extra.CSIS_GROUP_ID";
+
+    /**
+     * Group size as int extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CSIS_GROUP_SIZE = "android.bluetooth.extra.CSIS_GROUP_SIZE";
+
+    /**
+     * Group type uuid extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
+     *
+     * @hide
+     */
+    public static final String EXTRA_CSIS_GROUP_TYPE_UUID =
+            "android.bluetooth.extra.CSIS_GROUP_TYPE_UUID";
+
+    /**
+     * Intent used to broadcast information about identified set member
+     * ready to connect.
+     *
+     * <p>This intent will have one extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li>  {@link #EXTRA_CSIS_GROUP_ID} - Group identifier. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE =
+            "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
+
+    /**
+     * This represents an invalid group ID.
+     *
+     * @hide
+     */
+    public static final int GROUP_ID_INVALID = IBluetoothCsipSetCoordinator.CSIS_GROUP_ID_INVALID;
+
+    /**
+     * Indicating that group was locked with success.
+     *
+     * @hide
+     */
+    public static final int GROUP_LOCK_SUCCESS = 0;
+
+    /**
+     * Indicating that group locked failed due to invalid group ID.
+     *
+     * @hide
+     */
+    public static final int GROUP_LOCK_FAILED_INVALID_GROUP = 1;
+
+    /**
+     * Indicating that group locked failed due to empty group.
+     *
+     * @hide
+     */
+    public static final int GROUP_LOCK_FAILED_GROUP_EMPTY = 2;
+
+    /**
+     * Indicating that group locked failed due to group members being disconnected.
+     *
+     * @hide
+     */
+    public static final int GROUP_LOCK_FAILED_GROUP_NOT_CONNECTED = 3;
+
+    /**
+     * Indicating that group locked failed due to group member being already locked.
+     *
+     * @hide
+     */
+    public static final int GROUP_LOCK_FAILED_LOCKED_BY_OTHER = 4;
+
+    /**
+     * Indicating that group locked failed due to other reason.
+     *
+     * @hide
+     */
+    public static final int GROUP_LOCK_FAILED_OTHER_REASON = 5;
+
+    /**
+     * Indicating that group member in locked state was lost.
+     *
+     * @hide
+     */
+    public static final int LOCKED_GROUP_MEMBER_LOST = 6;
+
+    private BluetoothAdapter mAdapter;
+    private final BluetoothProfileConnector<IBluetoothCsipSetCoordinator> mProfileConnector =
+            new BluetoothProfileConnector(this, BluetoothProfile.CSIP_SET_COORDINATOR, TAG,
+                    IBluetoothCsipSetCoordinator.class.getName()) {
+                @Override
+                public IBluetoothCsipSetCoordinator getServiceInterface(IBinder service) {
+                    return IBluetoothCsipSetCoordinator.Stub.asInterface(
+                            Binder.allowBlocking(service));
+                }
+            };
+
+    /**
+     * Create a BluetoothCsipSetCoordinator proxy object for interacting with the local
+     * Bluetooth CSIS service.
+     */
+    /*package*/ BluetoothCsipSetCoordinator(Context context, ServiceListener listener) {
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        mProfileConnector.connect(context, listener);
+        mCloseGuard = new CloseGuard();
+        mCloseGuard.open("close");
+    }
+
+    /**
+     * @hide
+     */
+    protected void finalize() {
+        if (mCloseGuard != null) {
+            mCloseGuard.warnIfOpen();
+        }
+        close();
+    }
+
+    /**
+     * @hide
+     */
+    public void close() {
+        mProfileConnector.disconnect();
+    }
+
+    private IBluetoothCsipSetCoordinator getService() {
+        return mProfileConnector.getService();
+    }
+
+    /**
+     * Lock the set.
+     * @param groupId group ID to lock,
+     * @param executor callback executor,
+     * @param cb callback to report lock and unlock events - stays valid until the app unlocks
+     *           using the returned lock identifier or the lock timeouts on the remote side,
+     *           as per CSIS specification,
+     * @return unique lock identifier used for unlocking or null if lock has failed.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public
+    @Nullable UUID groupLock(int groupId, @Nullable @CallbackExecutor Executor executor,
+            @Nullable ClientLockCallback cb) {
+        if (VDBG) {
+            log("groupLockSet()");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        try {
+            if (service != null && isEnabled()) {
+                IBluetoothCsipSetCoordinatorLockCallback delegate = null;
+                if ((executor != null) && (cb != null)) {
+                    delegate = new BluetoothCsipSetCoordinatorLockCallbackDelegate(executor, cb);
+                }
+                return service.groupLock(groupId, delegate).getUuid();
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return null;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return null;
+        }
+    }
+
+    /**
+     * Unlock the set.
+     * @param lockUuid unique lock identifier
+     * @return true if unlocked, false on error
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean groupUnlock(@NonNull UUID lockUuid) {
+        if (VDBG) {
+            log("groupLockSet()");
+        }
+        if (lockUuid == null) {
+            return false;
+        }
+
+        final IBluetoothCsipSetCoordinator service = getService();
+        try {
+            if (service != null && isEnabled()) {
+                service.groupUnlock(new ParcelUuid(lockUuid));
+                return true;
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+    }
+
+    /**
+     * Get device's groups.
+     * @param device the active device
+     * @return Map of groups ids and related UUIDs
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public @NonNull Map getGroupUuidMapByDevice(@Nullable BluetoothDevice device) {
+        if (VDBG) {
+            log("getGroupUuidMapByDevice()");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        try {
+            if (service != null && isEnabled()) {
+                return service.getGroupUuidMapByDevice(device);
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return new HashMap<>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new HashMap<>();
+        }
+    }
+
+    /**
+     * Get group id for the given UUID
+     * @param uuid
+     * @return list of group IDs
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public @NonNull List<Integer> getAllGroupIds(@Nullable ParcelUuid uuid) {
+        if (VDBG) {
+            log("getAllGroupIds()");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        try {
+            if (service != null && isEnabled()) {
+                return service.getAllGroupIds(uuid);
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return new ArrayList<Integer>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new ArrayList<Integer>();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public @NonNull List<BluetoothDevice> getConnectedDevices() {
+        if (VDBG) {
+            log("getConnectedDevices()");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        if (service != null && isEnabled()) {
+            try {
+                return service.getConnectedDevices();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return new ArrayList<BluetoothDevice>();
+            }
+        }
+        if (service == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return new ArrayList<BluetoothDevice>();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+    @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+            @NonNull int[] states) {
+        if (VDBG) {
+            log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        if (service != null && isEnabled()) {
+            try {
+                return service.getDevicesMatchingConnectionStates(states);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return new ArrayList<BluetoothDevice>();
+            }
+        }
+        if (service == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return new ArrayList<BluetoothDevice>();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+    @BluetoothProfile.BtProfileState int getConnectionState(
+            @Nullable BluetoothDevice device) {
+        if (VDBG) {
+            log("getState(" + device + ")");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return service.getConnectionState(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return BluetoothProfile.STATE_DISCONNECTED;
+            }
+        }
+        if (service == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return BluetoothProfile.STATE_DISCONNECTED;
+    }
+
+    /**
+     * Set connection policy of the profile
+     *
+     * <p> The device should already be paired.
+     * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+     * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+     *
+     * @param device Paired bluetooth device
+     * @param connectionPolicy is the connection policy to set to for this profile
+     * @return true if connectionPolicy is set, false on error
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean setConnectionPolicy(
+            @Nullable BluetoothDevice device, @ConnectionPolicy int connectionPolicy) {
+        if (DBG) {
+            log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        try {
+            if (service != null && isEnabled() && isValidDevice(device)) {
+                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                        && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                    return false;
+                }
+                return service.setConnectionPolicy(device, connectionPolicy);
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+    }
+
+    /**
+     * Get the connection policy of the profile.
+     *
+     * <p> The connection policy can be any of:
+     * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+     * {@link #CONNECTION_POLICY_UNKNOWN}
+     *
+     * @param device Bluetooth device
+     * @return connection policy of the device
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
+        if (VDBG) {
+            log("getConnectionPolicy(" + device + ")");
+        }
+        final IBluetoothCsipSetCoordinator service = getService();
+        try {
+            if (service != null && isEnabled() && isValidDevice(device)) {
+                return service.getConnectionPolicy(device);
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        }
+    }
+
+    private boolean isEnabled() {
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
+    }
+
+    private static boolean isValidDevice(@Nullable BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 07dbe52..1054b4c 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -106,7 +106,7 @@
      * <p>Sent when a remote device is found during discovery.
      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
      * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or
-     * {@link #EXTRA_RSSI} if they are available.
+     * {@link #EXTRA_RSSI} and/or {@link #EXTRA_IS_COORDINATED_SET_MEMBER} if they are available.
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} and
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to receive.
      */
@@ -257,6 +257,15 @@
     public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
 
     /**
+    * Used as an bool extra field in {@link #ACTION_FOUND} intents.
+    * It contains the information if device is discovered as member of a coordinated set or not.
+    * Pairing with device that belongs to a set would trigger pairing with the rest of set members.
+    * See Bluetooth CSIP specification for more details.
+    */
+    public static final String EXTRA_IS_COORDINATED_SET_MEMBER =
+            "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER";
+
+    /**
      * Used as a Parcelable {@link BluetoothClass} extra field in {@link
      * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents.
      */
@@ -1035,6 +1044,8 @@
     /** Address is either resolvable, non-resolvable or static. */
     public static final int ADDRESS_TYPE_RANDOM = 1;
 
+    private static final String NULL_MAC_ADDRESS = "00:00:00:00:00:00";
+
     /**
      * Lazy initialization. Guaranteed final after first object constructed, or
      * getService() called.
@@ -1324,7 +1335,7 @@
      * @throws IllegalArgumentException if an invalid transport was specified
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean createBond(int transport) {
         return createBondInternal(transport, null, null);
@@ -1371,6 +1382,10 @@
             Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
             return false;
         }
+        if (NULL_MAC_ADDRESS.equals(mAddress)) {
+            Log.e(TAG, "Unable to create bond, invalid address " + mAddress);
+            return false;
+        }
         try {
             return service.createBond(this, transport, remoteP192Data, remoteP256Data);
         } catch (RemoteException e) {
@@ -1616,13 +1631,38 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public boolean fetchUuidsWithSdp() {
+        return fetchUuidsWithSdp(TRANSPORT_AUTO);
+    }
+
+    /**
+     * Perform a service discovery on the remote device to get the UUIDs supported with the
+     * specific transport.
+     *
+     * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
+     * with the UUIDs supported by the remote end. If there is an error
+     * in getting the SDP or GATT records or if the process takes a long time, or the device
+     * is bonding and we have its UUIDs cached, {@link #ACTION_UUID} intent is sent with the
+     * UUIDs that is currently present in the cache. Clients should use the {@link #getUuids}
+     * to get UUIDs if service discovery is not to be performed. If there is an ongoing bonding
+     * process, service discovery or device inquiry, the request will be queued.
+     *
+     * @param transport - provide type of transport (e.g. LE or Classic).
+     * @return False if the check fails, True if the process of initiating an ACL connection
+     * to the remote device was started or cached UUIDs will be broadcast with the specific
+     * transport.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean fetchUuidsWithSdp(@Transport int transport) {
         final IBluetooth service = sService;
         if (service == null || !isBluetoothEnabled()) {
             Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp");
             return false;
         }
         try {
-            return service.fetchRemoteUuids(this);
+            return service.fetchRemoteUuids(this, transport);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index b3a7c88..b3ccdd0 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -101,6 +101,9 @@
     /** A read or write operation was requested with an invalid offset */
     public static final int GATT_INVALID_OFFSET = 0x7;
 
+    /** Insufficient authorization for a given operation */
+    public static final int GATT_INSUFFICIENT_AUTHORIZATION = 0x8;
+
     /** A write operation exceeds the maximum length of the attribute */
     public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
 
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 632572d..18aa23a 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -1018,8 +1018,8 @@
      *  - binder is dead or Bluetooth is disabled or other error
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    @UnsupportedAppUsage
     public boolean startScoUsingVirtualVoiceCall() {
         if (DBG) log("startScoUsingVirtualVoiceCall()");
         final IBluetoothHeadset service = mService;
@@ -1048,8 +1048,8 @@
      *  - binder is dead or Bluetooth is disabled or other error
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    @UnsupportedAppUsage
     public boolean stopScoUsingVirtualVoiceCall() {
         if (DBG) log("stopScoUsingVirtualVoiceCall()");
         final IBluetoothHeadset service = mService;
@@ -1227,7 +1227,8 @@
      * @return true if in-band ringing is enabled, false if in-band ringing is disabled
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
     public boolean isInbandRingingEnabled() {
         if (DBG) {
             log("isInbandRingingEnabled()");
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
index 75fcab9..6bbe95e 100644
--- a/core/java/android/bluetooth/BluetoothLeAudio.java
+++ b/core/java/android/bluetooth/BluetoothLeAudio.java
@@ -65,9 +65,6 @@
      * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
      * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED =
@@ -82,9 +79,6 @@
      * be null if no device is active. </li>
      * </ul>
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
-     *
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -92,12 +86,148 @@
             "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
 
     /**
+     * Intent used to broadcast group node status information.
+     *
+     * <p>This intent will have 3 extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_NODE_STATUS} - Group node status. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED";
+
+
+    /**
+     * Intent used to broadcast group status information.
+     *
+     * <p>This intent will have 4 extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_STATUS} - Group status. </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_GROUP_STATUS_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED";
+
+    /**
+     * Intent used to broadcast group audio configuration changed information.
+     *
+     * <p>This intent will have 5 extra:
+     * <ul>
+     * <li> {@link #EXTRA_LE_AUDIO_GROUP_ID} - Group id. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_DIRECTION} - Direction as bit mask. </li>
+     * <li> {@link #EXTRA_LE_AUDIO_SINK_LOCATION} - Sink location as per Bluetooth Assigned
+     * Numbers </li>
+     * <li> {@link #EXTRA_LE_AUDIO_SOURCE_LOCATION} - Source location as per Bluetooth Assigned
+     * Numbers </li>
+     * <li> {@link #EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS} - Available contexts for group as per
+     * Bluetooth Assigned Numbers </li>
+     * </ul>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_CONF_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_CONF_CHANGED";
+
+    /**
+     * Indicates conversation between humans as, for example, in telephony or video calls.
+     * @hide
+     */
+    public static final int CONTEXT_TYPE_COMMUNICATION = 0x0002;
+
+    /**
+     * Indicates media as, for example, in music, public radio, podcast or video soundtrack.
+     * @hide
+     */
+    public static final int CONTEXT_TYPE_MEDIA = 0x0004;
+
+    /**
      * This represents an invalid group ID.
      *
      * @hide
      */
     public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
 
+    /**
+     * Contains group id.
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_ID =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_ID";
+
+    /**
+     * Contains group node status, can be any of
+     * <p>
+     * <ul>
+     * <li> {@link #GROUP_NODE_ADDED} </li>
+     * <li> {@link #GROUP_NODE_REMOVED} </li>
+     * </ul>
+     * <p>
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_NODE_STATUS =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_NODE_STATUS";
+
+    /**
+     * Contains group status, can be any of
+     *
+     * <p>
+     * <ul>
+     * <li> {@link #GROUP_STATUS_IDLE} </li>
+     * <li> {@link #GROUP_STATUS_STREAMING} </li>
+     * <li> {@link #GROUP_STATUS_SUSPENDED} </li>
+     * <li> {@link #GROUP_STATUS_RECONFIGURED} </li>
+     * <li> {@link #GROUP_STATUS_DESTROYED} </li>
+     * </ul>
+     * <p>
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_GROUP_STATUS =
+            "android.bluetooth.extra.LE_AUDIO_GROUP_STATUS";
+
+    /**
+     * Contains bit mask for direction, bit 0 set when Sink, bit 1 set when Source.
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_DIRECTION =
+            "android.bluetooth.extra.LE_AUDIO_DIRECTION";
+
+    /**
+     * Contains source location as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_SOURCE_LOCATION =
+            "android.bluetooth.extra.LE_AUDIO_SOURCE_LOCATION";
+
+    /**
+     * Contains sink location as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_SINK_LOCATION =
+            "android.bluetooth.extra.LE_AUDIO_SINK_LOCATION";
+
+    /**
+     * Contains available context types for group as per Bluetooth Assigned Numbers
+     * @hide
+     */
+    public static final String EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS =
+            "android.bluetooth.extra.LE_AUDIO_AVAILABLE_CONTEXTS";
+
     private BluetoothAdapter mAdapter;
     private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
             new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio",
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index b76d6b8..c4649b4 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -222,12 +222,25 @@
     int VOLUME_CONTROL = 23;
 
     /**
+     * @hide
+     * Media Control Profile server
+     *
+     */
+    int MCP_SERVER = 24;
+
+    /**
+     * Coordinated Set Identification Profile set coordinator
+     *
+     */
+    int CSIP_SET_COORDINATOR = 25;
+
+    /**
      * Max profile ID. This value should be updated whenever a new profile is added to match
      * the largest value assigned to a profile.
      *
      * @hide
      */
-    int MAX_PROFILE_ID = 23;
+    int MAX_PROFILE_ID = 25;
 
     /**
      * Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index d82cf19..7e4ee9e8 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -172,6 +172,21 @@
     /** @hide */
     @NonNull
     @SystemApi
+    public static final ParcelUuid GENERIC_MEDIA_CONTROL =
+            ParcelUuid.fromString("00001849-0000-1000-8000-00805F9B34FB");
+    /** @hide */
+    @NonNull
+    @SystemApi
+    public static final ParcelUuid MEDIA_CONTROL =
+            ParcelUuid.fromString("00001848-0000-1000-8000-00805F9B34FB");
+    /** @hide */
+    @NonNull
+    @SystemApi
+    public static final ParcelUuid COORDINATED_SET =
+            ParcelUuid.fromString("00001846-0000-1000-8000-00805F9B34FB");
+    /** @hide */
+    @NonNull
+    @SystemApi
     public static final ParcelUuid BASE_UUID =
             ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
 
diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS
index 2239100..fbee577 100644
--- a/core/java/android/bluetooth/OWNERS
+++ b/core/java/android/bluetooth/OWNERS
@@ -1,5 +1,6 @@
 # Bug component: 27441
 
-zachoverflow@google.com
-siyuanh@google.com
 rahulsabnis@google.com
+sattiraju@google.com
+siyuanh@google.com
+zachoverflow@google.com
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index ddc93327..9da6ff3 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -168,6 +168,15 @@
                 dest.writeByteArray(mManufacturerDataMask);
             }
         }
+
+        // IRK
+        if (mDeviceAddress != null) {
+            dest.writeInt(mAddressType);
+            dest.writeInt(mIrk == null ? 0 : 1);
+            if (mIrk != null) {
+                dest.writeByteArray(mIrk);
+            }
+        }
     }
 
     /**
@@ -187,8 +196,10 @@
             if (in.readInt() == 1) {
                 builder.setDeviceName(in.readString());
             }
+            String address = null;
+            // If we have a non-null address
             if (in.readInt() == 1) {
-                builder.setDeviceAddress(in.readString());
+                address = in.readString();
             }
             if (in.readInt() == 1) {
                 ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader());
@@ -245,6 +256,17 @@
                 }
             }
 
+            // IRK
+            if (address != null) {
+                final int addressType = in.readInt();
+                if (in.readInt() == 1) {
+                    final byte[] irk = new byte[16];
+                    in.readByteArray(irk);
+                    builder.setDeviceAddress(address, addressType, irk);
+                } else {
+                    builder.setDeviceAddress(address, addressType);
+                }
+            }
             return builder.build();
         }
     };
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index 8ad1349..c7f92c9 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -1,12 +1,14 @@
 # Remain no owner because multiple modules may touch this file.
 per-file Context.java = *
 per-file ContextWrapper.java = *
-per-file Content* = varunshah@google.com, omakoto@google.com, jsharkey@google.com
+per-file Content* = file:/services/core/java/com/android/server/am/OWNERS
 per-file IntentFilter.java = toddke@google.com
 per-file IntentFilter.java = patb@google.com
+per-file IntentFilter.java = file:/services/core/java/com/android/server/am/OWNERS
 per-file Intent.java = toddke@google.com
 per-file Intent.java = patb@google.com
 per-file Intent.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Intent.java = file:/services/core/java/com/android/server/am/OWNERS
 per-file AutofillOptions* = file:/core/java/android/service/autofill/OWNERS
 per-file ContentCaptureOptions* = file:/core/java/android/service/contentcapture/OWNERS
 per-file LocusId* = file:/core/java/android/service/contentcapture/OWNERS
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 0b950b4..11ea16f 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -39,7 +39,7 @@
      *         requested user, an empty map is returned.
      */
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    Map getAllOverlays(in int userId);
+    Map<String, List<OverlayInfo>> getAllOverlays(in int userId);
 
     /**
      * Returns information about all overlays for the given target package for
@@ -51,7 +51,7 @@
      * @return A list of OverlayInfo objects; if no overlays exist for the
      *         requested package, an empty list is returned.
      */
-    List getOverlayInfosForTarget(in String targetPackageName, in int userId);
+    List<OverlayInfo> getOverlayInfosForTarget(in String targetPackageName, in int userId);
 
     /**
      * Returns information about the overlay with the given package name for the
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
index 0ba92cc..504a7bd 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.content.IntentFilter;
 import android.os.Parcel;
-import android.os.Parcelable;
 import android.util.Pair;
 
 import com.android.internal.util.DataClass;
@@ -168,19 +167,6 @@
                 + '}';
     }
 
-    public static final Parcelable.Creator<ParsedIntentInfo> CREATOR =
-            new Parcelable.Creator<ParsedIntentInfo>() {
-                @Override
-                public ParsedIntentInfo createFromParcel(Parcel source) {
-                    return new ParsedIntentInfo(source);
-                }
-
-                @Override
-                public ParsedIntentInfo[] newArray(int size) {
-                    return new ParsedIntentInfo[size];
-                }
-            };
-
     public boolean isHasDefault() {
         return hasDefault;
     }
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/core/java/android/debug/FingerprintAndPairDevice.aidl
similarity index 66%
copy from telephony/java/android/telephony/data/SliceInfo.aidl
copy to core/java/android/debug/FingerprintAndPairDevice.aidl
index 286ea5e..b439e14 100644
--- a/telephony/java/android/telephony/data/SliceInfo.aidl
+++ b/core/java/android/debug/FingerprintAndPairDevice.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,15 @@
  * limitations under the License.
  */
 
-/** @hide */
-package android.telephony.data;
+package android.debug;
 
-parcelable SliceInfo;
+import android.debug.PairDevice;
+
+/**
+ * @see {@link android.debug.IAdbManager#getPairedDevices()}
+ * @hide
+ */
+parcelable FingerprintAndPairDevice {
+    String keyFingerprint;
+    PairDevice device;
+}
\ No newline at end of file
diff --git a/core/java/android/debug/IAdbCallback.aidl b/core/java/android/debug/IAdbCallback.aidl
new file mode 100644
index 0000000..9c8f1cf
--- /dev/null
+++ b/core/java/android/debug/IAdbCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.debug;
+
+import android.debug.AdbTransportType;
+
+/**
+ * Callback interface of {@link android.debug.IAdbCallbackManager}.
+ *
+ * @hide
+ */
+oneway interface IAdbCallback {
+    /**
+     * On debugging enabled, service providing IAdbManager calls this function.
+     */
+    void onDebuggingChanged(boolean enabled, AdbTransportType type);
+}
diff --git a/core/java/android/debug/IAdbManager.aidl b/core/java/android/debug/IAdbManager.aidl
index aea7633..314c405 100644
--- a/core/java/android/debug/IAdbManager.aidl
+++ b/core/java/android/debug/IAdbManager.aidl
@@ -16,6 +16,9 @@
 
 package android.debug;
 
+import android.debug.FingerprintAndPairDevice;
+import android.debug.IAdbCallback;
+
 /**
  * Interface to communicate remotely with the {@code AdbService} in the system server.
  *
@@ -58,9 +61,10 @@
     void denyWirelessDebugging();
 
     /**
-     * Returns a Map<String, PairDevice> with the key fingerprint mapped to the device information.
+     * Returns an array of NamedPairDevice with the key fingerprint mapped to the device
+     * information.
      */
-    Map getPairedDevices();
+    FingerprintAndPairDevice[] getPairedDevices();
 
     /**
      * Unpair the device identified by the key fingerprint it uses.
@@ -108,4 +112,14 @@
      * QR code.
      */
     boolean isAdbWifiQrSupported();
+
+    /**
+     * Register callback for ADB debugging changed notification.
+     */
+    void registerCallback(IAdbCallback callback);
+
+    /**
+     * Unregister callback for ADB debugging changed notification.
+     */
+    void unregisterCallback(IAdbCallback callback);
 }
diff --git a/core/java/android/debug/PairDevice.aidl b/core/java/android/debug/PairDevice.aidl
new file mode 100644
index 0000000..c72a5ed
--- /dev/null
+++ b/core/java/android/debug/PairDevice.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.debug;
+
+/**
+ * Contains information about the client in an ADB connection.
+ * @see {@link android.debug.IAdbManager#getPairedDevices()}
+ * @hide
+ */
+parcelable PairDevice {
+    /**
+     * The human-readable name of the device.
+     */
+    String name;
+
+    /**
+     * The device's guid.
+     */
+    String guid;
+
+    /**
+     * Indicates whether the device is currently connected to adbd.
+     */
+    boolean connected;
+}
\ No newline at end of file
diff --git a/core/java/android/debug/PairDevice.java b/core/java/android/debug/PairDevice.java
deleted file mode 100644
index 2d5b446..0000000
--- a/core/java/android/debug/PairDevice.java
+++ /dev/null
@@ -1,112 +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.debug;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.Immutable;
-import com.android.internal.util.Preconditions;
-
-/**
- * Contains information about the client in an ADB connection.
- * @hide
- */
-@Immutable
-public class PairDevice implements Parcelable {
-    /**
-     * The human-readable name of the device.
-     */
-    @NonNull private final String mName;
-
-    /**
-     * The device's guid.
-     */
-    @NonNull private final String mGuid;
-
-    /**
-     * Indicates whether the device is currently connected to adbd.
-     */
-    private final boolean mConnected;
-
-    public PairDevice(@NonNull String name, @NonNull String guid, boolean connected) {
-        Preconditions.checkStringNotEmpty(name);
-        Preconditions.checkStringNotEmpty(guid);
-        mName = name;
-        mGuid = guid;
-        mConnected = connected;
-    }
-
-    /**
-     * @return the device name.
-     */
-    @NonNull
-    public String getDeviceName() {
-        return mName;
-    }
-
-    /**
-     * @return the device GUID.
-     */
-    @NonNull
-    public String getGuid() {
-        return mGuid;
-    }
-
-    /**
-     * @return the adb connection state of the device.
-     */
-    public boolean isConnected() {
-        return mConnected;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(mName);
-        dest.writeString(mGuid);
-        dest.writeBoolean(mConnected);
-    }
-
-    /**
-     * @return Human-readable info about the object.
-     */
-    @Override
-    public String toString() {
-        return "\n" + mName + "\n" + mGuid + "\n" + mConnected;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<PairDevice> CREATOR =
-            new Creator<PairDevice>() {
-                @Override
-                public PairDevice createFromParcel(Parcel source) {
-                    return new PairDevice(source.readString(), source.readString(),
-                            source.readBoolean());
-                }
-
-                @Override
-                public PairDevice[] newArray(int size) {
-                    return new PairDevice[size];
-                }
-            };
-}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 0a76a9c..9e78a6b 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1440,14 +1440,14 @@
      *                Assuming that the bottom edge of the device faces the
      *                user and that the screen is face-up, tilting the top edge
      *                of the device toward the ground creates a positive pitch
-     *                angle. The range of values is -&pi; to &pi;.</li>
+     *                angle. The range of values is -&pi;/2 to &pi;/2.</li>
      * <li>values[2]: <i>Roll</i>, angle of rotation about the y axis. This
      *                value represents the angle between a plane perpendicular
      *                to the device's screen and a plane perpendicular to the
      *                ground. Assuming that the bottom edge of the device faces
      *                the user and that the screen is face-up, tilting the left
      *                edge of the device toward the ground creates a positive
-     *                roll angle. The range of values is -&pi;/2 to &pi;/2.</li>
+     *                roll angle. The range of values is -&pi; to &pi;.</li>
      * </ul>
      * <p>
      * Applying these three rotations in the azimuth, pitch, roll order
diff --git a/core/java/android/hardware/biometrics/OWNERS b/core/java/android/hardware/biometrics/OWNERS
index 2065ffa..0b4d9d9 100644
--- a/core/java/android/hardware/biometrics/OWNERS
+++ b/core/java/android/hardware/biometrics/OWNERS
@@ -1,8 +1,3 @@
 # Bug component: 879035
 
-curtislb@google.com
-ilyamaty@google.com
-jaggies@google.com
-joshmccloskey@google.com
-kchyn@google.com
-
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/java/android/hardware/radio/ITuner.aidl b/core/java/android/hardware/radio/ITuner.aidl
index 429f1f3..7bf234b 100644
--- a/core/java/android/hardware/radio/ITuner.aidl
+++ b/core/java/android/hardware/radio/ITuner.aidl
@@ -80,14 +80,14 @@
     void setConfigFlag(int flag, boolean value);
 
     /**
-     * @param parameters Vendor-specific key-value pairs, must be Map<String, String>
-     * @return Vendor-specific key-value pairs, must be Map<String, String>
+     * @param parameters Vendor-specific key-value pairs
+     * @return Vendor-specific key-value pairs
      */
-    Map setParameters(in Map parameters);
+    Map<String, String> setParameters(in Map<String, String> parameters);
 
     /**
      * @param keys Parameter keys to fetch
-     * @return Vendor-specific key-value pairs, must be Map<String, String>
+     * @return Vendor-specific key-value pairs
      */
-    Map getParameters(in List<String> keys);
+    Map<String, String> getParameters(in List<String> keys);
 }
diff --git a/core/java/android/hardware/radio/ITunerCallback.aidl b/core/java/android/hardware/radio/ITunerCallback.aidl
index b32daa5..f98947b 100644
--- a/core/java/android/hardware/radio/ITunerCallback.aidl
+++ b/core/java/android/hardware/radio/ITunerCallback.aidl
@@ -36,7 +36,7 @@
     void onProgramListUpdated(in ProgramList.Chunk chunk);
 
     /**
-     * @param parameters Vendor-specific key-value pairs, must be Map<String, String>
+     * @param parameters Vendor-specific key-value pairs
      */
-    void onParametersUpdated(in Map parameters);
+    void onParametersUpdated(in Map<String, String> parameters);
 }
diff --git a/core/java/android/hardware/radio/TunerCallbackAdapter.java b/core/java/android/hardware/radio/TunerCallbackAdapter.java
index beff0f7..e3f7001 100644
--- a/core/java/android/hardware/radio/TunerCallbackAdapter.java
+++ b/core/java/android/hardware/radio/TunerCallbackAdapter.java
@@ -220,7 +220,7 @@
     }
 
     @Override
-    public void onParametersUpdated(Map parameters) {
+    public void onParametersUpdated(Map<String, String> parameters) {
         mHandler.post(() -> mCallback.onParametersUpdated(parameters));
     }
 }
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 8f1e2de..7ef5bac 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -354,7 +354,7 @@
         }
 
         for (Entry<String, Integer> entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) {
-            if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) {
+            if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= entry.getValue()) {
                 enabledAlgos.add(entry.getKey());
             }
         }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 288b06e..46c83df 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1581,32 +1583,37 @@
                 // processes this every time device has transmitted/received amount equivalent to
                 // global threshold alert (~ 2MB) across all interfaces.
                 final long rxBytesAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+                        multiplySafeByRational(underlyingIfacesTotal.rxBytes,
+                                rxBytes[i], tunIfaceTotal.rxBytes);
                 // app must not be blamed for more than it consumed on tunIface
                 totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
             }
             long totalRxPackets = 0;
             if (tunIfaceTotal.rxPackets > 0) {
                 final long rxPacketsAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+                        multiplySafeByRational(underlyingIfacesTotal.rxPackets,
+                                rxPackets[i], tunIfaceTotal.rxPackets);
                 totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
             }
             long totalTxBytes = 0;
             if (tunIfaceTotal.txBytes > 0) {
                 final long txBytesAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+                        multiplySafeByRational(underlyingIfacesTotal.txBytes,
+                                txBytes[i], tunIfaceTotal.txBytes);
                 totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
             }
             long totalTxPackets = 0;
             if (tunIfaceTotal.txPackets > 0) {
                 final long txPacketsAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+                        multiplySafeByRational(underlyingIfacesTotal.txPackets,
+                                txPackets[i], tunIfaceTotal.txPackets);
                 totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
             }
             long totalOperations = 0;
             if (tunIfaceTotal.operations > 0) {
                 final long operationsAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
+                        multiplySafeByRational(underlyingIfacesTotal.operations,
+                                operations[i], tunIfaceTotal.operations);
                 totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
             }
             // In a second pass, distribute these values across interfaces in the proportion that
@@ -1618,37 +1625,37 @@
                 tmpEntry.set = set[i];
                 if (underlyingIfacesTotal.rxBytes > 0) {
                     tmpEntry.rxBytes =
-                            totalRxBytes
-                                    * perInterfaceTotal[j].rxBytes
-                                    / underlyingIfacesTotal.rxBytes;
+                            multiplySafeByRational(totalRxBytes,
+                                    perInterfaceTotal[j].rxBytes,
+                                    underlyingIfacesTotal.rxBytes);
                 }
                 tmpEntry.rxPackets = 0;
                 if (underlyingIfacesTotal.rxPackets > 0) {
                     tmpEntry.rxPackets =
-                            totalRxPackets
-                                    * perInterfaceTotal[j].rxPackets
-                                    / underlyingIfacesTotal.rxPackets;
+                            multiplySafeByRational(totalRxPackets,
+                                    perInterfaceTotal[j].rxPackets,
+                                    underlyingIfacesTotal.rxPackets);
                 }
                 tmpEntry.txBytes = 0;
                 if (underlyingIfacesTotal.txBytes > 0) {
                     tmpEntry.txBytes =
-                            totalTxBytes
-                                    * perInterfaceTotal[j].txBytes
-                                    / underlyingIfacesTotal.txBytes;
+                            multiplySafeByRational(totalTxBytes,
+                                    perInterfaceTotal[j].txBytes,
+                                    underlyingIfacesTotal.txBytes);
                 }
                 tmpEntry.txPackets = 0;
                 if (underlyingIfacesTotal.txPackets > 0) {
                     tmpEntry.txPackets =
-                            totalTxPackets
-                                    * perInterfaceTotal[j].txPackets
-                                    / underlyingIfacesTotal.txPackets;
+                            multiplySafeByRational(totalTxPackets,
+                                    perInterfaceTotal[j].txPackets,
+                                    underlyingIfacesTotal.txPackets);
                 }
                 tmpEntry.operations = 0;
                 if (underlyingIfacesTotal.operations > 0) {
                     tmpEntry.operations =
-                            totalOperations
-                                    * perInterfaceTotal[j].operations
-                                    / underlyingIfacesTotal.operations;
+                            multiplySafeByRational(totalOperations,
+                                    perInterfaceTotal[j].operations,
+                                    underlyingIfacesTotal.operations);
                 }
                 // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
                 // interface. Add that data usage to this object.
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 68917a8..08f75df 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -47,7 +47,6 @@
 import android.util.BackupUtils;
 import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.net.module.util.NetworkIdentityUtils;
 
@@ -151,24 +150,6 @@
         }
     }
 
-    private static boolean sForceAllNetworkTypes = false;
-
-    /**
-     * Results in matching against all mobile network types.
-     *
-     * <p>See {@link #matchesMobile} and {@link matchesMobileWildcard}.
-     */
-    @VisibleForTesting
-    public static void forceAllNetworkTypes() {
-        sForceAllNetworkTypes = true;
-    }
-
-    /** Resets the affect of {@link #forceAllNetworkTypes}. */
-    @VisibleForTesting
-    public static void resetForceAllNetworkTypes() {
-        sForceAllNetworkTypes = false;
-    }
-
     /**
      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
      * the given IMSI.
@@ -611,7 +592,7 @@
             // Only metered mobile network would be matched regardless of metered filter.
             // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
             // TODO: Respect metered filter and remove mMetered condition.
-            return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
+            return (ident.mType == TYPE_MOBILE && ident.mMetered)
                     && !ArrayUtils.isEmpty(mMatchSubscriberIds)
                     && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
                     && matchesCollapsedRatType(ident);
@@ -726,7 +707,7 @@
         if (ident.mType == TYPE_WIMAX) {
             return true;
         } else {
-            return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
+            return (ident.mType == TYPE_MOBILE && ident.mMetered)
                     && matchesCollapsedRatType(ident);
         }
     }
diff --git a/core/java/android/net/PacProxyManager.java b/core/java/android/net/PacProxyManager.java
index 8f7ad8c..da79634 100644
--- a/core/java/android/net/PacProxyManager.java
+++ b/core/java/android/net/PacProxyManager.java
@@ -94,7 +94,7 @@
     }
 
     /**
-     * Updates the PAC Proxy Installer with current Proxy information.
+     * Updates the PAC Proxy Service with current Proxy information.
      */
     @RequiresPermission(anyOf = {
             android.Manifest.permission.NETWORK_STACK,
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index 662ebb3..5c28553 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -389,6 +389,10 @@
 
     /**
      * Starts a legacy VPN.
+     *
+     * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the
+     * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be
+     * thrown.
      * @hide
      */
     public void startLegacyVpn(VpnProfile profile) {
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 1692921f..fb21ce3 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -31,6 +31,7 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Set;
+import java.util.function.Supplier;
 
 /**
  * A mapping from String keys to values of various types. In most cases, you
@@ -38,7 +39,8 @@
  * {@link PersistableBundle} subclass.
  */
 public class BaseBundle {
-    private static final String TAG = "Bundle";
+    /** @hide */
+    protected static final String TAG = "Bundle";
     static final boolean DEBUG = false;
 
     // Keep them in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
@@ -95,7 +97,7 @@
     Parcel mParcelledData = null;
 
     /**
-     * Whether {@link #mParcelledData} was generated by native coed or not.
+     * Whether {@link #mParcelledData} was generated by native code or not.
      */
     private boolean mParcelledByNative;
 
@@ -198,7 +200,7 @@
         if (size == 0) {
             return null;
         }
-        Object o = mMap.valueAt(0);
+        Object o = getValueAt(0);
         try {
             return (String) o;
         } catch (ClassCastException e) {
@@ -229,7 +231,12 @@
      * using the currently assigned class loader.
      */
     @UnsupportedAppUsage
-    /* package */ void unparcel() {
+    final void unparcel() {
+        unparcel(/* itemwise */ false);
+    }
+
+    /** Deserializes the underlying data and each item if {@code itemwise} is true. */
+    final void unparcel(boolean itemwise) {
         synchronized (this) {
             final Parcel source = mParcelledData;
             if (source != null) {
@@ -241,9 +248,45 @@
                             + ": no parcelled data");
                 }
             }
+            if (itemwise) {
+                for (int i = 0, n = mMap.size(); i < n; i++) {
+                    // Triggers deserialization of i-th item, if needed
+                    getValueAt(i);
+                }
+            }
         }
     }
 
+    /**
+     * Returns the value for key {@code key}.
+     *
+     * This call should always be made after {@link #unparcel()} or inside a lock after making sure
+     * {@code mMap} is not null.
+     *
+     * @hide
+     */
+    final Object getValue(String key) {
+        int i = mMap.indexOfKey(key);
+        return (i >= 0) ? getValueAt(i) : null;
+    }
+
+    /**
+     * Returns the value for a certain position in the array map.
+     *
+     * This call should always be made after {@link #unparcel()} or inside a lock after making sure
+     * {@code mMap} is not null.
+     *
+     * @hide
+     */
+    final Object getValueAt(int i) {
+        Object object = mMap.valueAt(i);
+        if (object instanceof Supplier<?>) {
+            object = ((Supplier<?>) object).get();
+            mMap.setValueAt(i, object);
+        }
+        return object;
+    }
+
     private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel,
             boolean parcelledByNative) {
         if (LOG_DEFUSABLE && sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
@@ -282,15 +325,8 @@
             map.ensureCapacity(count);
         }
         try {
-            if (parcelledByNative) {
-                // If it was parcelled by native code, then the array map keys aren't sorted
-                // by their hash codes, so use the safe (slow) one.
-                parcelledData.readArrayMapSafelyInternal(map, count, mClassLoader);
-            } else {
-                // If parcelled by Java, we know the contents are sorted properly,
-                // so we can use ArrayMap.append().
-                parcelledData.readArrayMapInternal(map, count, mClassLoader);
-            }
+            recycleParcel &= parcelledData.readArrayMap(map, count, !parcelledByNative,
+                    /* lazy */ true, mClassLoader);
         } catch (BadParcelableException e) {
             if (sShouldDefuse) {
                 Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -342,7 +378,7 @@
 
     /** @hide */
     ArrayMap<String, Object> getMap() {
-        unparcel();
+        unparcel(/* itemwise */ true);
         return mMap;
     }
 
@@ -400,7 +436,12 @@
     }
 
     /**
-     * @hide This kind-of does an equality comparison.  Kind-of.
+     * Performs a loose equality check, which means there can be false negatives but if the method
+     * returns true than both objects are guaranteed to be equal.
+     *
+     * The point is that this method is a light-weight check in performance terms.
+     *
+     * @hide
      */
     public boolean kindofEquals(BaseBundle other) {
         if (other == null) {
@@ -415,6 +456,12 @@
         } else if (isParcelled()) {
             return mParcelledData.compareData(other.mParcelledData) == 0;
         } else {
+            // Following semantic above of failing in case we get a serialized value vs a
+            // deserialized one, we'll compare the map. If a certain element hasn't been
+            // deserialized yet, it's a Supplier (or more specifically a LazyValue, but let's
+            // pretend we don't know that here :P), we'll use that element's equality comparison as
+            // map naturally does. That will takes care of comparing the payload if needed (see
+            // Parcel.readLazyValue() for details).
             return mMap.equals(other.mMap);
         }
     }
@@ -453,7 +500,7 @@
                     final int N = fromMap.size();
                     mMap = new ArrayMap<>(N);
                     for (int i = 0; i < N; i++) {
-                        mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
+                        mMap.append(fromMap.keyAt(i), deepCopyValue(from.getValueAt(i)));
                     }
                 }
             } else {
@@ -526,7 +573,7 @@
     @Nullable
     public Object get(String key) {
         unparcel();
-        return mMap.get(key);
+        return getValue(key);
     }
 
     /**
@@ -1001,7 +1048,7 @@
      */
     char getChar(String key, char defaultValue) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return defaultValue;
         }
@@ -1266,7 +1313,7 @@
     @Nullable
     Serializable getSerializable(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1289,7 +1336,7 @@
     @Nullable
     ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1312,7 +1359,7 @@
     @Nullable
     ArrayList<String> getStringArrayList(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1335,7 +1382,7 @@
     @Nullable
     ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1404,7 +1451,7 @@
     @Nullable
     short[] getShortArray(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1427,7 +1474,7 @@
     @Nullable
     char[] getCharArray(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1496,7 +1543,7 @@
     @Nullable
     float[] getFloatArray(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1585,7 +1632,7 @@
     void writeToParcelInner(Parcel parcel, int flags) {
         // If the parcel has a read-write helper, we can't just copy the blob, so unparcel it first.
         if (parcel.hasReadWriteHelper()) {
-            unparcel();
+            unparcel(/* itemwise */ true);
         }
         // Keep implementation in sync with writeToParcel() in
         // frameworks/native/libs/binder/PersistableBundle.cpp.
@@ -1660,10 +1707,13 @@
         }
 
         if (parcel.hasReadWriteHelper()) {
-            // If the parcel has a read-write helper, then we can't lazily-unparcel it, so just
-            // unparcel right away.
+            // If the parcel has a read-write helper, it's better to deserialize immediately
+            // otherwise the helper would have to either maintain valid state long after the bundle
+            // had been constructed with parcel or to make sure they trigger deserialization of the
+            // bundle immediately; neither of which is obvious.
             synchronized (this) {
                 initializeFromParcelLocked(parcel, /*recycleParcel=*/ false, isNativeBundle);
+                unparcel(/* itemwise */ true);
             }
             return;
         }
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index f5172cf..16034df 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -219,7 +219,7 @@
     /**
      * Indicates that a new wifi scan has started.
      *
-     * @param ws Worksource (to be used for battery blaming).
+     * @param ws worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void reportWifiScanStartedFromSource(@NonNull WorkSource ws) {
@@ -233,7 +233,7 @@
     /**
      * Indicates that an ongoing wifi scan has stopped.
      *
-     * @param ws Worksource (to be used for battery blaming).
+     * @param ws worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void reportWifiScanStoppedFromSource(@NonNull WorkSource ws) {
@@ -247,7 +247,7 @@
     /**
      * Indicates that a new wifi batched scan has started.
      *
-     * @param ws Worksource (to be used for battery blaming).
+     * @param ws worksource (to be used for battery blaming).
      * @param csph Channels scanned per hour.
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
@@ -263,7 +263,7 @@
     /**
      * Indicates that an ongoing wifi batched scan has stopped.
      *
-     * @param ws Worksource (to be used for battery blaming).
+     * @param ws worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void reportWifiBatchedScanStoppedFromSource(@NonNull WorkSource ws) {
@@ -307,7 +307,7 @@
     /**
      * Indicates an app acquiring full wifi lock.
      *
-     * @param ws Worksource (to be used for battery blaming).
+     * @param ws worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void reportFullWifiLockAcquiredFromSource(@NonNull WorkSource ws) {
@@ -321,7 +321,7 @@
     /**
      * Indicates an app releasing full wifi lock.
      *
-     * @param ws Worksource (to be used for battery blaming).
+     * @param ws worksource (to be used for battery blaming).
      */
     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void reportFullWifiLockReleasedFromSource(@NonNull WorkSource ws) {
@@ -436,6 +436,63 @@
         }
     }
 
+    /**
+     * Indicates that a new Bluetooth LE scan has started.
+     *
+     * @param ws worksource (to be used for battery blaming).
+     * @param isUnoptimized whether or not the scan has a filter.
+     */
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+    public void reportBleScanStarted(@NonNull WorkSource ws, boolean isUnoptimized) {
+        try {
+            mBatteryStats.noteBleScanStarted(ws, isUnoptimized);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Indicates that an ongoing Bluetooth LE scan has stopped.
+     *
+     * @param ws worksource (to be used for battery blaming).
+     * @param isUnoptimized whether or not the scan has a filter.
+     */
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+    public void reportBleScanStopped(@NonNull WorkSource ws, boolean isUnoptimized) {
+        try {
+            mBatteryStats.noteBleScanStopped(ws, isUnoptimized);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Indicates that Bluetooth LE has been reset.
+     */
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+    public void reportBleScanReset() {
+        try {
+            mBatteryStats.noteBleScanReset();
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Indicates that Bluetooth LE scan has received new results.
+     *
+     * @param ws worksource (to be used for battery blaming).
+     * @param numNewResults number of results received since last update.
+     */
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+    public void reportBleScanResults(@NonNull WorkSource ws, int numNewResults) {
+        try {
+            mBatteryStats.noteBleScanResults(ws, numNewResults);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
     private static int getDataConnectionPowerState(boolean isActive) {
         // TODO: DataConnectionRealTimeInfo is under telephony package but the constants are used
         // for both Wifi and mobile. It would make more sense to separate the constants to a
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 5017d9e..de13044 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -333,7 +333,7 @@
          */
         @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
         @TestApi
-        public static final int FIRST_SDK_INT = SystemProperties
+        public static final int DEVICE_INITIAL_SDK_INT = SystemProperties
                 .getInt("ro.product.first_api_level", 0);
 
         /**
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 1c1f5c0..5626bde 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -330,47 +330,9 @@
                 // It's been unparcelled, so we need to walk the map
                 for (int i=mMap.size()-1; i>=0; i--) {
                     Object obj = mMap.valueAt(i);
-                    if (obj instanceof Parcelable) {
-                        if ((((Parcelable)obj).describeContents()
-                                & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
-                            fdFound = true;
-                            break;
-                        }
-                    } else if (obj instanceof Parcelable[]) {
-                        Parcelable[] array = (Parcelable[]) obj;
-                        for (int n = array.length - 1; n >= 0; n--) {
-                            Parcelable p = array[n];
-                            if (p != null && ((p.describeContents()
-                                    & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
-                                fdFound = true;
-                                break;
-                            }
-                        }
-                    } else if (obj instanceof SparseArray) {
-                        SparseArray<? extends Parcelable> array =
-                                (SparseArray<? extends Parcelable>) obj;
-                        for (int n = array.size() - 1; n >= 0; n--) {
-                            Parcelable p = array.valueAt(n);
-                            if (p != null && (p.describeContents()
-                                    & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
-                                fdFound = true;
-                                break;
-                            }
-                        }
-                    } else if (obj instanceof ArrayList) {
-                        ArrayList array = (ArrayList) obj;
-                        // an ArrayList here might contain either Strings or
-                        // Parcelables; only look inside for Parcelables
-                        if (!array.isEmpty() && (array.get(0) instanceof Parcelable)) {
-                            for (int n = array.size() - 1; n >= 0; n--) {
-                                Parcelable p = (Parcelable) array.get(n);
-                                if (p != null && ((p.describeContents()
-                                        & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
-                                    fdFound = true;
-                                    break;
-                                }
-                            }
-                        }
+                    if (Parcel.hasFileDescriptors(obj)) {
+                        fdFound = true;
+                        break;
                     }
                 }
             }
@@ -391,7 +353,7 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public Bundle filterValues() {
-        unparcel();
+        unparcel(/* itemwise */ true);
         Bundle bundle = this;
         if (mMap != null) {
             ArrayMap<String, Object> map = mMap;
@@ -972,7 +934,7 @@
     @Nullable
     public Bundle getBundle(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -999,7 +961,7 @@
     @Nullable
     public <T extends Parcelable> T getParcelable(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1026,7 +988,7 @@
     @Nullable
     public Parcelable[] getParcelableArray(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1053,7 +1015,7 @@
     @Nullable
     public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1077,7 +1039,7 @@
     @Nullable
     public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) {
         unparcel();
-        Object o = mMap.get(key);
+        Object o = getValue(key);
         if (o == null) {
             return null;
         }
@@ -1300,7 +1262,7 @@
     public void writeToParcel(Parcel parcel, int flags) {
         final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0);
         try {
-            super.writeToParcelInner(parcel, flags);
+            writeToParcelInner(parcel, flags);
         } finally {
             parcel.restoreAllowFds(oldAllowFds);
         }
@@ -1312,7 +1274,7 @@
      * @param parcel The parcel to overwrite this bundle from.
      */
     public void readFromParcel(Parcel parcel) {
-        super.readFromParcelInner(parcel);
+        readFromParcelInner(parcel);
         mFlags = FLAG_ALLOW_FDS;
         maybePrefillHasFds();
     }
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index fd576c9..d701676 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -30,6 +30,7 @@
 
 import com.android.internal.os.IDropBoxManagerService;
 
+import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.File;
@@ -234,7 +235,8 @@
             } else {
                 return null;
             }
-            return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
+            return (mFlags & IS_GZIPPED) != 0
+                ? new GZIPInputStream(new BufferedInputStream(is)) : is;
         }
 
         public static final @android.annotation.NonNull Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator() {
diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl
index 4d160da..d83d94a 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -40,4 +40,9 @@
      * @see SystemConfigManager#getSystemPermissionUids
      */
     int[] getSystemPermissionUids(String permissionName);
+
+    /**
+     * @see SystemConfigManager#getEnabledComponentOverrides
+     */
+    List<String> getEnabledComponentOverrides(String packageName);
 }
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index cd02d29..c575c80e 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -66,3 +66,9 @@
 
 # Bugreporting
 per-file Bugreport* = file:/platform/frameworks/native:/cmds/dumpstate/OWNERS
+
+# UpdateEngine
+per-file *UpdateEngine* = file:/platform/system/update_engine:/OWNERS
+
+# VINTF
+per-file Vintf* = file:/platform/system/libvintf:/OWNERS
diff --git a/core/java/android/os/OutcomeReceiver.java b/core/java/android/os/OutcomeReceiver.java
new file mode 100644
index 0000000..01b2764
--- /dev/null
+++ b/core/java/android/os/OutcomeReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+
+/**
+ * Callback interface intended for use when an asynchronous operation may result in a failure.
+ *
+ * This interface may be used in cases where an asynchronous API may complete either with a value
+ * or with a {@link Throwable} that indicates an error.
+ * @param <R> The type of the result that's being sent.
+ * @param <E> The type of the {@link Throwable} that contains more information about the error.
+ */
+public interface OutcomeReceiver<R, E extends Throwable> {
+    /**
+     * Called when the asynchronous operation succeeds and delivers a result value.
+     * @param result The value delivered by the asynchronous operation.
+     */
+    void onResult(@NonNull R result);
+
+    /**
+     * Called when the asynchronous operation fails. The mode of failure is indicated by the
+     * {@link Throwable} passed as an argument to this method.
+     * @param error A subclass of {@link Throwable} with more details about the error that occurred.
+     */
+    default void onError(@NonNull E error) {}
+}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 6acdcc4..7f2e2b1 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -26,6 +28,7 @@
 import android.util.ArraySet;
 import android.util.ExceptionUtils;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.Size;
 import android.util.SizeF;
 import android.util.Slog;
@@ -56,7 +59,9 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.function.Supplier;
 
 /**
  * Container for a message (data and object references) that can
@@ -279,6 +284,8 @@
 
     @CriticalNative
     private static native void nativeMarkSensitive(long nativePtr);
+    @FastNative
+    private static native void nativeMarkForBinder(long nativePtr, IBinder binder);
     @CriticalNative
     private static native int nativeDataSize(long nativePtr);
     @CriticalNative
@@ -495,6 +502,16 @@
 
     /**
      * Parcel data should be zero'd before realloc'd or deleted.
+     *
+     * Note: currently this feature requires multiple things to work in concert:
+     * - markSensitive must be called on every relative Parcel
+     * - FLAG_CLEAR_BUF must be passed into the kernel
+     * This requires having code which does the right thing in every method and in every backend
+     * of AIDL. Rather than exposing this API, it should be replaced with a single API on
+     * IBinder objects which can be called once, and the information should be fed into the
+     * Parcel using markForBinder APIs. In terms of code size and number of API calls, this is
+     * much more extensible.
+     *
      * @hide
      */
     public final void markSensitive() {
@@ -502,9 +519,23 @@
     }
 
     /**
+     * Associate this parcel with a binder object. This marks the parcel as being prepared for a
+     * transaction on this specific binder object. Based on this, the format of the wire binder
+     * protocol may change. This should be called before any data is written to the parcel. If this
+     * is called multiple times, this will only be marked for the last binder. For future
+     * compatibility, it is recommended to call this on all parcels which are being sent over
+     * binder.
+     *
+     * @hide
+     */
+    public void markForBinder(@NonNull IBinder binder) {
+        nativeMarkForBinder(mNativePtr, binder);
+    }
+
+    /**
      * Returns the total amount of data contained in the parcel.
      */
-    public final int dataSize() {
+    public int dataSize() {
         return nativeDataSize(mNativePtr);
     }
 
@@ -649,6 +680,66 @@
     }
 
     /**
+     * Check if the object used in {@link #readValue(ClassLoader)} / {@link #writeValue(Object)}
+     * has file descriptors.
+     *
+     * <p>For most cases, it will use the self-reported {@link Parcelable#describeContents()} method
+     * for that.
+     *
+     * @throws IllegalArgumentException if you provide any object not supported by above methods.
+     *         Most notably, if you pass {@link Parcel}, this method will throw, for that check
+     *         {@link Parcel#hasFileDescriptors()}
+     *
+     * @hide
+     */
+    public static boolean hasFileDescriptors(Object value) {
+        if (value instanceof LazyValue) {
+            return ((LazyValue) value).hasFileDescriptors();
+        } else if (value instanceof Parcelable) {
+            if ((((Parcelable) value).describeContents()
+                    & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+                return true;
+            }
+        } else if (value instanceof Parcelable[]) {
+            Parcelable[] array = (Parcelable[]) value;
+            for (int n = array.length - 1; n >= 0; n--) {
+                Parcelable p = array[n];
+                if (p != null && ((p.describeContents()
+                        & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
+                    return true;
+                }
+            }
+        } else if (value instanceof SparseArray<?>) {
+            SparseArray<?> array = (SparseArray<?>) value;
+            for (int n = array.size() - 1; n >= 0; n--) {
+                Object object = array.valueAt(n);
+                if (object instanceof Parcelable) {
+                    Parcelable p = (Parcelable) object;
+                    if (p != null && (p.describeContents()
+                            & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+                        return true;
+                    }
+                }
+            }
+        } else if (value instanceof ArrayList<?>) {
+            ArrayList<?> array = (ArrayList<?>) value;
+            for (int n = array.size() - 1; n >= 0; n--) {
+                Object object = array.get(n);
+                if (object instanceof Parcelable) {
+                    Parcelable p = (Parcelable) object;
+                    if (p != null && ((p.describeContents()
+                            & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
+                        return true;
+                    }
+                }
+            }
+        } else {
+            getValueType(value); // Will throw if value is not supported
+        }
+        return false;
+    }
+
+    /**
      * Store or read an IBinder interface token in the parcel at the current
      * {@link #dataPosition}.  This is used to validate that the marshalled
      * transaction is intended for the target interface.
@@ -1795,108 +1886,206 @@
      * should be used).</p>
      */
     public final void writeValue(@Nullable Object v) {
+        if (v instanceof LazyValue) {
+            LazyValue value = (LazyValue) v;
+            value.writeToParcel(this);
+            return;
+        }
+        int type = getValueType(v);
+        writeInt(type);
+        if (isLengthPrefixed(type)) {
+            // Length
+            int length = dataPosition();
+            writeInt(-1); // Placeholder
+            // Object
+            int start = dataPosition();
+            writeValue(type, v);
+            int end = dataPosition();
+            // Backpatch length
+            setDataPosition(length);
+            writeInt(end - start);
+            setDataPosition(end);
+        } else {
+            writeValue(type, v);
+        }
+    }
+
+    /** @hide */
+    public static int getValueType(@Nullable Object v) {
         if (v == null) {
-            writeInt(VAL_NULL);
+            return VAL_NULL;
         } else if (v instanceof String) {
-            writeInt(VAL_STRING);
-            writeString((String) v);
+            return VAL_STRING;
         } else if (v instanceof Integer) {
-            writeInt(VAL_INTEGER);
-            writeInt((Integer) v);
+            return VAL_INTEGER;
         } else if (v instanceof Map) {
-            writeInt(VAL_MAP);
-            writeMap((Map) v);
+            return VAL_MAP;
         } else if (v instanceof Bundle) {
             // Must be before Parcelable
-            writeInt(VAL_BUNDLE);
-            writeBundle((Bundle) v);
+            return VAL_BUNDLE;
         } else if (v instanceof PersistableBundle) {
-            writeInt(VAL_PERSISTABLEBUNDLE);
-            writePersistableBundle((PersistableBundle) v);
+            // Must be before Parcelable
+            return VAL_PERSISTABLEBUNDLE;
+        } else if (v instanceof SizeF) {
+            // Must be before Parcelable
+            return VAL_SIZEF;
         } else if (v instanceof Parcelable) {
             // IMPOTANT: cases for classes that implement Parcelable must
-            // come before the Parcelable case, so that their specific VAL_*
+            // come before the Parcelable case, so that their speci fic VAL_*
             // types will be written.
-            writeInt(VAL_PARCELABLE);
-            writeParcelable((Parcelable) v, 0);
+            return VAL_PARCELABLE;
         } else if (v instanceof Short) {
-            writeInt(VAL_SHORT);
-            writeInt(((Short) v).intValue());
+            return VAL_SHORT;
         } else if (v instanceof Long) {
-            writeInt(VAL_LONG);
-            writeLong((Long) v);
+            return VAL_LONG;
         } else if (v instanceof Float) {
-            writeInt(VAL_FLOAT);
-            writeFloat((Float) v);
+            return VAL_FLOAT;
         } else if (v instanceof Double) {
-            writeInt(VAL_DOUBLE);
-            writeDouble((Double) v);
+            return VAL_DOUBLE;
         } else if (v instanceof Boolean) {
-            writeInt(VAL_BOOLEAN);
-            writeInt((Boolean) v ? 1 : 0);
+            return VAL_BOOLEAN;
         } else if (v instanceof CharSequence) {
             // Must be after String
-            writeInt(VAL_CHARSEQUENCE);
-            writeCharSequence((CharSequence) v);
+            return VAL_CHARSEQUENCE;
         } else if (v instanceof List) {
-            writeInt(VAL_LIST);
-            writeList((List) v);
+            return VAL_LIST;
         } else if (v instanceof SparseArray) {
-            writeInt(VAL_SPARSEARRAY);
-            writeSparseArray((SparseArray) v);
+            return VAL_SPARSEARRAY;
         } else if (v instanceof boolean[]) {
-            writeInt(VAL_BOOLEANARRAY);
-            writeBooleanArray((boolean[]) v);
+            return VAL_BOOLEANARRAY;
         } else if (v instanceof byte[]) {
-            writeInt(VAL_BYTEARRAY);
-            writeByteArray((byte[]) v);
+            return VAL_BYTEARRAY;
         } else if (v instanceof String[]) {
-            writeInt(VAL_STRINGARRAY);
-            writeStringArray((String[]) v);
+            return VAL_STRINGARRAY;
         } else if (v instanceof CharSequence[]) {
             // Must be after String[] and before Object[]
-            writeInt(VAL_CHARSEQUENCEARRAY);
-            writeCharSequenceArray((CharSequence[]) v);
+            return VAL_CHARSEQUENCEARRAY;
         } else if (v instanceof IBinder) {
-            writeInt(VAL_IBINDER);
-            writeStrongBinder((IBinder) v);
+            return VAL_IBINDER;
         } else if (v instanceof Parcelable[]) {
-            writeInt(VAL_PARCELABLEARRAY);
-            writeParcelableArray((Parcelable[]) v, 0);
+            return VAL_PARCELABLEARRAY;
         } else if (v instanceof int[]) {
-            writeInt(VAL_INTARRAY);
-            writeIntArray((int[]) v);
+            return VAL_INTARRAY;
         } else if (v instanceof long[]) {
-            writeInt(VAL_LONGARRAY);
-            writeLongArray((long[]) v);
+            return VAL_LONGARRAY;
         } else if (v instanceof Byte) {
-            writeInt(VAL_BYTE);
-            writeInt((Byte) v);
+            return VAL_BYTE;
         } else if (v instanceof Size) {
-            writeInt(VAL_SIZE);
-            writeSize((Size) v);
-        } else if (v instanceof SizeF) {
-            writeInt(VAL_SIZEF);
-            writeSizeF((SizeF) v);
+            return VAL_SIZE;
         } else if (v instanceof double[]) {
-            writeInt(VAL_DOUBLEARRAY);
-            writeDoubleArray((double[]) v);
+            return VAL_DOUBLEARRAY;
         } else {
             Class<?> clazz = v.getClass();
             if (clazz.isArray() && clazz.getComponentType() == Object.class) {
                 // Only pure Object[] are written here, Other arrays of non-primitive types are
                 // handled by serialization as this does not record the component type.
-                writeInt(VAL_OBJECTARRAY);
-                writeArray((Object[]) v);
+                return VAL_OBJECTARRAY;
             } else if (v instanceof Serializable) {
                 // Must be last
-                writeInt(VAL_SERIALIZABLE);
-                writeSerializable((Serializable) v);
+                return VAL_SERIALIZABLE;
             } else {
-                throw new RuntimeException("Parcel: unable to marshal value " + v);
+                throw new IllegalArgumentException("Parcel: unknown type for value " + v);
             }
         }
     }
+    /**
+     * Writes value {@code v} in the parcel. This does NOT write the int representing the type
+     * first.
+     *
+     * @hide
+     */
+    public void writeValue(int type, @Nullable Object v) {
+        switch (type) {
+            case VAL_NULL:
+                break;
+            case VAL_STRING:
+                writeString((String) v);
+                break;
+            case VAL_INTEGER:
+                writeInt((Integer) v);
+                break;
+            case VAL_MAP:
+                writeMap((Map) v);
+                break;
+            case VAL_BUNDLE:
+                writeBundle((Bundle) v);
+                break;
+            case VAL_PERSISTABLEBUNDLE:
+                writePersistableBundle((PersistableBundle) v);
+                break;
+            case VAL_PARCELABLE:
+                writeParcelable((Parcelable) v, 0);
+                break;
+            case VAL_SHORT:
+                writeInt(((Short) v).intValue());
+                break;
+            case VAL_LONG:
+                writeLong((Long) v);
+                break;
+            case VAL_FLOAT:
+                writeFloat((Float) v);
+                break;
+            case VAL_DOUBLE:
+                writeDouble((Double) v);
+                break;
+            case VAL_BOOLEAN:
+                writeInt((Boolean) v ? 1 : 0);
+                break;
+            case VAL_CHARSEQUENCE:
+                writeCharSequence((CharSequence) v);
+                break;
+            case VAL_LIST:
+                writeList((List) v);
+                break;
+            case VAL_SPARSEARRAY:
+                writeSparseArray((SparseArray) v);
+                break;
+            case VAL_BOOLEANARRAY:
+                writeBooleanArray((boolean[]) v);
+                break;
+            case VAL_BYTEARRAY:
+                writeByteArray((byte[]) v);
+                break;
+            case VAL_STRINGARRAY:
+                writeStringArray((String[]) v);
+                break;
+            case VAL_CHARSEQUENCEARRAY:
+                writeCharSequenceArray((CharSequence[]) v);
+                break;
+            case VAL_IBINDER:
+                writeStrongBinder((IBinder) v);
+                break;
+            case VAL_PARCELABLEARRAY:
+                writeParcelableArray((Parcelable[]) v, 0);
+                break;
+            case VAL_INTARRAY:
+                writeIntArray((int[]) v);
+                break;
+            case VAL_LONGARRAY:
+                writeLongArray((long[]) v);
+                break;
+            case VAL_BYTE:
+                writeInt((Byte) v);
+                break;
+            case VAL_SIZE:
+                writeSize((Size) v);
+                break;
+            case VAL_SIZEF:
+                writeSizeF((SizeF) v);
+                break;
+            case VAL_DOUBLEARRAY:
+                writeDoubleArray((double[]) v);
+                break;
+            case VAL_OBJECTARRAY:
+                writeArray((Object[]) v);
+                break;
+            case VAL_SERIALIZABLE:
+                writeSerializable((Serializable) v);
+                break;
+            default:
+                throw new RuntimeException("Parcel: unable to marshal value " + v);
+        }
+    }
 
     /**
      * Flatten the name of the class of the Parcelable and its contents
@@ -3167,7 +3356,190 @@
     @Nullable
     public final Object readValue(@Nullable ClassLoader loader) {
         int type = readInt();
+        final Object object;
+        if (isLengthPrefixed(type)) {
+            int length = readInt();
+            int start = dataPosition();
+            object = readValue(type, loader);
+            int actual = dataPosition() - start;
+            if (actual != length) {
+                Log.w(TAG,
+                        "Unparcelling of " + object + " of type " + Parcel.valueTypeToString(type)
+                                + "  consumed " + actual + " bytes, but " + length + " expected.");
+            }
+        } else {
+            object = readValue(type, loader);
+        }
+        return object;
+    }
 
+    /**
+     * This will return a {@link Supplier} for length-prefixed types that deserializes the object
+     * when {@link Supplier#get()} is called, for other types it will return the object itself.
+     *
+     * <p>After calling {@link Supplier#get()} the parcel cursor will not change. Note that you
+     * shouldn't recycle the parcel, not at least until all objects have been retrieved. No
+     * synchronization attempts are made.
+     *
+     * </p>The supplier returned implements {@link #equals(Object)} and {@link #hashCode()}. Two
+     * suppliers are equal if either of the following is true:
+     * <ul>
+     *   <li>{@link Supplier#get()} has been called on both and both objects returned are equal.
+     *   <li>{@link Supplier#get()} hasn't been called on either one and everything below is true:
+     *   <ul>
+     *       <li>The {@code loader} parameters used to retrieve each are equal.
+     *       <li>They both have the same type.
+     *       <li>They have the same payload length.
+     *       <li>Their binary content is the same.
+     *   </ul>
+     * </ul>
+     *
+     * @hide
+     */
+    @Nullable
+    public Object readLazyValue(@Nullable ClassLoader loader) {
+        int start = dataPosition();
+        int type = readInt();
+        if (isLengthPrefixed(type)) {
+            int length = readInt();
+            setDataPosition(MathUtils.addOrThrow(dataPosition(), length));
+            return new LazyValue(this, start, length, type, loader);
+        } else {
+            return readValue(type, loader);
+        }
+    }
+
+    private static final class LazyValue implements Supplier<Object> {
+        private final int mPosition;
+        private final int mLength;
+        private final int mType;
+        @Nullable private final ClassLoader mLoader;
+        @Nullable private Object mObject;
+        @Nullable private volatile Parcel mValueParcel;
+
+        /**
+         * This goes from non-null to null once. Always check the nullability of this object before
+         * performing any operations, either involving itself or mObject since the happens-before
+         * established by this volatile will guarantee visibility of either. We can assume this
+         * parcel won't change anymore.
+         */
+        @Nullable private volatile Parcel mSource;
+
+        LazyValue(Parcel source, int position, int length, int type, @Nullable ClassLoader loader) {
+            mSource = requireNonNull(source);
+            mPosition = position;
+            mLength = length;
+            mType = type;
+            mLoader = loader;
+        }
+
+        @Override
+        public Object get() {
+            Parcel source = mSource;
+            if (source != null) {
+                synchronized (source) {
+                    int restore = source.dataPosition();
+                    try {
+                        source.setDataPosition(mPosition);
+                        mObject = source.readValue(mLoader);
+                    } finally {
+                        source.setDataPosition(restore);
+                    }
+                    mSource = null;
+                }
+            }
+            return mObject;
+        }
+
+        public void writeToParcel(Parcel out) {
+            Parcel source = mSource;
+            if (source != null) {
+                out.appendFrom(source, mPosition, mLength + 8);
+            } else {
+                out.writeValue(mObject);
+            }
+        }
+
+        public boolean hasFileDescriptors() {
+            Parcel source = mSource;
+            return (source != null)
+                    ? getValueParcel(source).hasFileDescriptors()
+                    : Parcel.hasFileDescriptors(mObject);
+        }
+
+        @Override
+        public String toString() {
+            return (mSource != null)
+                    ? "Supplier{" + valueTypeToString(mType) + "@" + mPosition + "+" + mLength + '}'
+                    : "Supplier{" + mObject + "}";
+        }
+
+        /**
+         * We're checking if the *lazy value* is equal to another one, not if the *object*
+         * represented by the lazy value is equal to the other one. So, if there are two lazy values
+         * and one of them has been deserialized but the other hasn't this will always return false.
+         */
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (!(other instanceof LazyValue)) {
+                return false;
+            }
+            LazyValue value = (LazyValue) other;
+            // Check if they are either both serialized or both deserialized.
+            Parcel source = mSource;
+            Parcel otherSource = value.mSource;
+            if ((source == null) != (otherSource == null)) {
+                return false;
+            }
+            // If both are deserialized, compare the live objects.
+            if (source == null) {
+                // Note that here it's guaranteed that both mObject references contain valid values
+                // (possibly null) since mSource will have provided the memory barrier for those and
+                // once deserialized we never go back to serialized state.
+                return Objects.equals(mObject, value.mObject);
+            }
+            // Better safely fail here since this could mean we get different objects.
+            if (!Objects.equals(mLoader, value.mLoader)) {
+                return false;
+            }
+            // Otherwise compare metadata prior to comparing payload.
+            if (mType != value.mType || mLength != value.mLength) {
+                return false;
+            }
+            // Finally we compare the payload.
+            return getValueParcel(source).compareData(value.getValueParcel(otherSource)) == 0;
+        }
+
+        @Override
+        public int hashCode() {
+            // Accessing mSource first to provide memory barrier for mObject
+            return Objects.hash(mSource == null, mObject, mLoader, mType, mLength);
+        }
+
+        /** This extracts the parcel section responsible for the object and returns it. */
+        private Parcel getValueParcel(Parcel source) {
+            Parcel parcel = mValueParcel;
+            if (parcel == null) {
+                parcel = Parcel.obtain();
+                // mLength is the length of object representation, excluding the type and length.
+                // mPosition is the position of the entire value container, right before the type.
+                // So, we add 4 bytes for the type + 4 bytes for the length written.
+                parcel.appendFrom(source, mPosition, mLength + 8);
+                mValueParcel = parcel;
+            }
+            return parcel;
+        }
+    }
+
+    /**
+     * Reads a value from the parcel of type {@code type}. Does NOT read the int representing the
+     * type first.
+     */
+    @Nullable
+    private Object readValue(int type, @Nullable ClassLoader loader) {
         switch (type) {
         case VAL_NULL:
             return null;
@@ -3266,6 +3638,20 @@
         }
     }
 
+    private boolean isLengthPrefixed(int type) {
+        switch (type) {
+            case VAL_PARCELABLE:
+            case VAL_PARCELABLEARRAY:
+            case VAL_LIST:
+            case VAL_SPARSEARRAY:
+            case VAL_BUNDLE:
+            case VAL_SERIALIZABLE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     /**
      * Read and return a new Parcelable from the parcel.  The given class loader
      * will be used to load any enclosed Parcelables.  If it is null, the default
@@ -3564,49 +3950,49 @@
         }
     }
 
-    /* package */ void readArrayMapInternal(@NonNull ArrayMap outVal, int N,
-            @Nullable ClassLoader loader) {
-        if (DEBUG_ARRAY_MAP) {
-            RuntimeException here =  new RuntimeException("here");
-            here.fillInStackTrace();
-            Log.d(TAG, "Reading " + N + " ArrayMap entries", here);
-        }
-        int startPos;
-        while (N > 0) {
-            if (DEBUG_ARRAY_MAP) startPos = dataPosition();
-            String key = readString();
-            Object value = readValue(loader);
-            if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Read #" + (N-1) + " "
-                    + (dataPosition()-startPos) + " bytes: key=0x"
-                    + Integer.toHexString((key != null ? key.hashCode() : 0)) + " " + key);
-            outVal.append(key, value);
-            N--;
-        }
-        outVal.validate();
+    /* package */ void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
+            int size, @Nullable ClassLoader loader) {
+        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader);
     }
 
-    /* package */ void readArrayMapSafelyInternal(@NonNull ArrayMap outVal, int N,
-            @Nullable ClassLoader loader) {
-        if (DEBUG_ARRAY_MAP) {
-            RuntimeException here =  new RuntimeException("here");
-            here.fillInStackTrace();
-            Log.d(TAG, "Reading safely " + N + " ArrayMap entries", here);
-        }
-        while (N > 0) {
+    /**
+     * Reads a map into {@code map}.
+     *
+     * @param sorted Whether the keys are sorted by their hashes, if so we use an optimized path.
+     * @param lazy   Whether to populate the map with lazy {@link Supplier} objects for
+     *               length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
+     *               details.
+     * @return whether the parcel can be recycled or not.
+     * @hide
+     */
+    boolean readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
+            boolean lazy, @Nullable ClassLoader loader) {
+        boolean recycle = true;
+        while (size > 0) {
             String key = readString();
-            if (DEBUG_ARRAY_MAP) Log.d(TAG, "  Read safe #" + (N-1) + ": key=0x"
-                    + (key != null ? key.hashCode() : 0) + " " + key);
-            Object value = readValue(loader);
-            outVal.put(key, value);
-            N--;
+            Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
+            if (value instanceof LazyValue) {
+                recycle = false;
+            }
+            if (sorted) {
+                map.append(key, value);
+            } else {
+                map.put(key, value);
+            }
+            size--;
         }
+        if (sorted) {
+            map.validate();
+        }
+        return recycle;
     }
 
     /**
      * @hide For testing only.
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void readArrayMap(@NonNull ArrayMap outVal, @Nullable ClassLoader loader) {
+    public void readArrayMap(@NonNull ArrayMap<? super String, Object> outVal,
+            @Nullable ClassLoader loader) {
         final int N = readInt();
         if (N < 0) {
             return;
@@ -3691,4 +4077,38 @@
     public long getBlobAshmemSize() {
         return nativeGetBlobAshmemSize(mNativePtr);
     }
+
+    private static String valueTypeToString(int type) {
+        switch (type) {
+            case VAL_NULL: return "VAL_NULL";
+            case VAL_INTEGER: return "VAL_INTEGER";
+            case VAL_MAP: return "VAL_MAP";
+            case VAL_BUNDLE: return "VAL_BUNDLE";
+            case VAL_PERSISTABLEBUNDLE: return "VAL_PERSISTABLEBUNDLE";
+            case VAL_PARCELABLE: return "VAL_PARCELABLE";
+            case VAL_SHORT: return "VAL_SHORT";
+            case VAL_LONG: return "VAL_LONG";
+            case VAL_FLOAT: return "VAL_FLOAT";
+            case VAL_DOUBLE: return "VAL_DOUBLE";
+            case VAL_BOOLEAN: return "VAL_BOOLEAN";
+            case VAL_CHARSEQUENCE: return "VAL_CHARSEQUENCE";
+            case VAL_LIST: return "VAL_LIST";
+            case VAL_SPARSEARRAY: return "VAL_SPARSEARRAY";
+            case VAL_BOOLEANARRAY: return "VAL_BOOLEANARRAY";
+            case VAL_BYTEARRAY: return "VAL_BYTEARRAY";
+            case VAL_STRINGARRAY: return "VAL_STRINGARRAY";
+            case VAL_CHARSEQUENCEARRAY: return "VAL_CHARSEQUENCEARRAY";
+            case VAL_IBINDER: return "VAL_IBINDER";
+            case VAL_PARCELABLEARRAY: return "VAL_PARCELABLEARRAY";
+            case VAL_INTARRAY: return "VAL_INTARRAY";
+            case VAL_LONGARRAY: return "VAL_LONGARRAY";
+            case VAL_BYTE: return "VAL_BYTE";
+            case VAL_SIZE: return "VAL_SIZE";
+            case VAL_SIZEF: return "VAL_SIZEF";
+            case VAL_DOUBLEARRAY: return "VAL_DOUBLEARRAY";
+            case VAL_OBJECTARRAY: return "VAL_OBJECTARRAY";
+            case VAL_SERIALIZABLE: return "VAL_SERIALIZABLE";
+            default: return "UNKNOWN(" + type + ")";
+        }
+    }
 }
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index f853e67..4e8418b 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -17,6 +17,8 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -27,7 +29,15 @@
 
 import java.util.Map;
 
-/** @hide */
+/**
+ * Manage binder services as registered with the binder context manager. These services must be
+ * declared statically on an Android device (SELinux access_vector service_manager, w/ service
+ * names in service_contexts files), and they do not follow the activity lifecycle. When
+ * building applications, android.app.Service should be preferred.
+ *
+ * @hide
+ **/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
 public final class ServiceManager {
     private static final String TAG = "ServiceManager";
     private static final Object sLock = new Object();
@@ -98,10 +108,12 @@
         int COUNT = GET_SERVICE + 1;
     }
 
+    /** @hide */
     public static final StatLogger sStatLogger = new StatLogger(new String[] {
             "getService()",
     });
 
+    /** @hide */
     @UnsupportedAppUsage
     public ServiceManager() {
     }
@@ -123,6 +135,7 @@
      *
      * @param name the name of the service to get
      * @return a reference to the service, or <code>null</code> if the service doesn't exist
+     * @hide
      */
     @UnsupportedAppUsage
     public static IBinder getService(String name) {
@@ -160,6 +173,7 @@
      *
      * @param name the name of the new service
      * @param service the service object
+     * @hide
      */
     @UnsupportedAppUsage
     public static void addService(String name, IBinder service) {
@@ -174,6 +188,7 @@
      * @param service the service object
      * @param allowIsolated set to true to allow isolated sandboxed processes
      * to access this service
+     * @hide
      */
     @UnsupportedAppUsage
     public static void addService(String name, IBinder service, boolean allowIsolated) {
@@ -189,6 +204,7 @@
      * @param allowIsolated set to true to allow isolated sandboxed processes
      * @param dumpPriority supported dump priority levels as a bitmask
      * to access this service
+     * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static void addService(String name, IBinder service, boolean allowIsolated,
@@ -203,6 +219,7 @@
     /**
      * Retrieve an existing service called @a name from the
      * service manager.  Non-blocking.
+     * @hide
      */
     @UnsupportedAppUsage
     public static IBinder checkService(String name) {
@@ -239,6 +256,7 @@
      *
      * @return true if the service is declared somewhere (eg. VINTF manifest) and
      * waitForService should always be able to return the service.
+     * @hide
      */
     public static String[] getDeclaredInstances(@NonNull String iface) {
         try {
@@ -256,8 +274,13 @@
      * will wait for it to be ready.
      *
      * @return {@code null} only if there are permission problems or fatal errors.
+     * @hide
      */
-    public static native IBinder waitForService(@NonNull String name);
+    public static IBinder waitForService(@NonNull String name) {
+        return Binder.allowBlocking(waitForServiceNative(name));
+    }
+
+    private static native IBinder waitForServiceNative(@NonNull String name);
 
     /**
      * Returns the specified service from the service manager, if declared.
@@ -267,8 +290,10 @@
      *
      * @return {@code null} if the service is not declared in the manifest, or if there are
      * permission problems, or if there are fatal errors.
+     * @hide
      */
-    public static IBinder waitForDeclaredService(@NonNull String name) {
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @Nullable public static IBinder waitForDeclaredService(@NonNull String name) {
         return isDeclared(name) ? waitForService(name) : null;
     }
 
@@ -276,6 +301,7 @@
      * Return a list of all currently running services.
      * @return an array of all currently running services, or <code>null</code> in
      * case of an exception
+     * @hide
      */
     @UnsupportedAppUsage
     public static String[] listServices() {
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 755c35f..3739040 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -98,6 +98,10 @@
         return mServiceManager.updatableViaApex(name);
     }
 
+    public ConnectionInfo getConnectionInfo(String name) throws RemoteException {
+        return mServiceManager.getConnectionInfo(name);
+    }
+
     public void registerClientCallback(String name, IBinder service, IClientCallback cb)
             throws RemoteException {
         throw new RemoteException();
diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java
index 136e3de..46eb2ec 100644
--- a/core/java/android/os/SharedMemory.java
+++ b/core/java/android/os/SharedMemory.java
@@ -93,6 +93,26 @@
         }
     }
 
+    /**
+     * Creates an instance from existing shared memory passed as {@link ParcelFileDescriptor}.
+     *
+     * <p> The {@code fd} should be a shared memory created from
+       {@code SharedMemory or ASharedMemory}. This can be useful when shared memory is passed as
+       file descriptor through JNI or binder service implemented in cpp.
+     * <p> Note that newly created {@code SharedMemory} takes ownership of passed {@code fd} and
+     * the original {@code fd} becomes detached (Check {@link ParcelFileDescriptor#detachFd()}).
+     * If the caller wants to use the file descriptor after the call, the caller should duplicate
+     * the file descriptor (Check {@link ParcelFileDescriptor#dup()}) and pass the duped version
+     * instead.
+     *
+     * @param fd File descriptor of shared memory passed as {@link ParcelFileDescriptor}.
+     */
+    public static @NonNull SharedMemory fromFileDescriptor(@NonNull ParcelFileDescriptor fd) {
+        FileDescriptor f = new FileDescriptor();
+        f.setInt$(fd.detachFd());
+        return new SharedMemory(f);
+    }
+
     private static final int PROT_MASK = OsConstants.PROT_READ | OsConstants.PROT_WRITE
             | OsConstants.PROT_EXEC | OsConstants.PROT_NONE;
 
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index 9bfa8ad..a6316df 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -17,6 +17,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -129,4 +130,21 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Get enabled component for a specific package
+     *
+     * @param packageName The target package.
+     * @return The enabled component
+     * {@hide}
+     */
+    @SystemApi
+    @NonNull
+    public List<String> getEnabledComponentOverrides(@NonNull String packageName) {
+        try {
+            return mInterface.getEnabledComponentOverrides(packageName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index c8cbc51..ddb6533 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -102,8 +102,6 @@
     /** @hide */
     public static final long TRACE_TAG_RRO = 1L << 26;
     /** @hide */
-    public static final long TRACE_TAG_SYSPROP = 1L << 27;
-    /** @hide */
     public static final long TRACE_TAG_APEX_MANAGER = 1L << 18;
 
     private static final long TRACE_TAG_NOT_READY = 1L << 63;
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 5a48242..3e01c53 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -409,10 +409,11 @@
 
     /**
      * Resets the bootable flag on the non-current partition and all internal
-     * update_engine state. This can be used after an unwanted payload has been
-     * successfully applied and the device has not yet been rebooted to signal
-     * that we no longer want to boot into that updated system. After this call
-     * completes, update_engine will no longer report
+     * update_engine state. Note this call will clear the entire update
+     * progress. So a subsequent {@link #applyPayload} will apply the update
+     * from scratch.
+     *
+     * <p>After this call completes, update_engine will no longer report
      * {@code UPDATED_NEED_REBOOT}, so your callback can remove any outstanding
      * notification that rebooting into the new system is possible.
      */
@@ -425,6 +426,39 @@
     }
 
     /**
+     * Sets the A/B slot switch for the next boot after applying an ota update. If
+     * {@link #applyPayload} hasn't switched the slot, the updater APP can call
+     * this API to switch the slot and apply the update on next boot.
+     *
+     * @param payloadMetadataFilename the location of the metadata without the
+     * {@code file://} prefix.
+     */
+    public void setShouldSwitchSlotOnReboot(@NonNull String payloadMetadataFilename) {
+        try {
+            mUpdateEngine.setShouldSwitchSlotOnReboot(payloadMetadataFilename);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+   /**
+    * Resets the boot slot to the source/current slot, without cancelling the
+    * update progress. This can be called after the update is installed, and to
+    * prevent the device from accidentally taking the update when it reboots.
+    *
+    * This is useful when users don't want to take the update immediately; or
+    * the updater determines some condition hasn't met, e.g. insufficient space
+    * for boot.
+    */
+    public void resetShouldSwitchSlotOnReboot() {
+        try {
+            mUpdateEngine.resetShouldSwitchSlotOnReboot();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Unbinds the last bound callback function.
      */
     public boolean unbind() {
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index bf0b655..1f11197 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -97,8 +97,11 @@
      * ["android.hidl.manager@1.0", "android.hardware.camera.device@1.0",
      *  "android.hardware.camera.device@3.2"]. There are no duplicates.
      *
-     * For AIDL HALs, the version is stripped away
-     * (e.g. "android.hardware.light").
+     * For AIDL HALs, the version is a single number
+     * (e.g. "android.hardware.light@1"). Historically, this API strips the
+     * version number for AIDL HALs (e.g. "android.hardware.light"). Users
+     * of this API must be able to handle both for backwards compatibility.
+     *
      * @hide
      */
     @TestApi
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
index 121fd33..fc17002 100644
--- a/core/java/android/os/connectivity/CellularBatteryStats.java
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -109,7 +109,7 @@
                         CellSignalStrength.getNumSignalStrengthLevels()));
         mTxTimeMs = Arrays.copyOfRange(
                 txTimeMs, 0,
-                Math.min(txTimeMs.length, ModemActivityInfo.TX_POWER_LEVELS));
+                Math.min(txTimeMs.length, ModemActivityInfo.getNumTxPowerLevels()));
         mMonitoredRailChargeConsumedMaMs = monitoredRailChargeConsumedMaMs;
     }
 
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
index 19a3a8b..b5466b6 100644
--- a/core/java/android/permission/OWNERS
+++ b/core/java/android/permission/OWNERS
@@ -1,11 +1,12 @@
 # Bug component: 137825
 
-eugenesusla@google.com
 evanseverson@google.com
 evanxinchen@google.com
 ewol@google.com
 guojing@google.com
 jaysullivan@google.com
+olekarg@google.com
+pyuli@google.com
 ntmyren@google.com
 svetoslavganov@android.com
 svetoslavganov@google.com
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index bd84c84..c89f4f5 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -201,6 +201,14 @@
             "intelligence_content_suggestions";
 
     /**
+     * Namespace for all lmkd related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native";
+
+    /**
      * Namespace for all media native related features.
      *
      * @hide
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index f0f0867..505f400 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -2351,7 +2351,10 @@
         final int ellipsisStringLen = ellipsisString.length();
         // Use the ellipsis string only if there are that at least as many characters to replace.
         final boolean useEllipsisString = ellipsisCount >= ellipsisStringLen;
-        for (int i = 0; i < ellipsisCount; i++) {
+        final int min = Math.max(0, start - ellipsisStart - lineStart);
+        final int max = Math.min(ellipsisCount, end - ellipsisStart - lineStart);
+
+        for (int i = min; i < max; i++) {
             final char c;
             if (useEllipsisString && i < ellipsisStringLen) {
                 c = ellipsisString.charAt(i);
@@ -2360,9 +2363,7 @@
             }
 
             final int a = i + ellipsisStart + lineStart;
-            if (start <= a && a < end) {
-                dest[destoff + a - start] = c;
-            }
+            dest[destoff + a - start] = c;
         }
     }
 
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 346fe29..0771157 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -210,7 +210,7 @@
         if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
             byte[] verityDigest = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
             verityRootHash = ApkSigningBlockUtils.parseVerityDigestAndVerifySourceLength(
-                    verityDigest, apk.length(), signatureInfo);
+                    verityDigest, apk.getChannel().size(), signatureInfo);
         }
 
         byte[] digest = pickBestDigestForV4(contentDigests);
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index 4ab541b..44f01a4 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -209,7 +209,7 @@
         if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
             byte[] verityDigest = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
             result.verityRootHash = ApkSigningBlockUtils.parseVerityDigestAndVerifySourceLength(
-                    verityDigest, apk.length(), signatureInfo);
+                    verityDigest, apk.getChannel().size(), signatureInfo);
         }
 
         result.digest = pickBestDigestForV4(contentDigests);
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 6efe95c..f79b5b9 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -349,7 +349,7 @@
             SignatureInfo signatureInfo) throws SecurityException {
         try {
             byte[] expectedRootHash = parseVerityDigestAndVerifySourceLength(expectedDigest,
-                    apk.length(), signatureInfo);
+                    apk.getChannel().size(), signatureInfo);
             VerityBuilder.VerityResult verity = VerityBuilder.generateApkVerityTree(apk,
                     signatureInfo, new ByteBufferFactory() {
                         @Override
diff --git a/core/java/android/util/apk/OWNERS b/core/java/android/util/apk/OWNERS
index 52c9550..0f4e869 100644
--- a/core/java/android/util/apk/OWNERS
+++ b/core/java/android/util/apk/OWNERS
@@ -1 +1,3 @@
 include /core/java/android/content/pm/OWNERS
+cbrubaker@google.com
+mpgroover@google.com
diff --git a/core/java/android/util/apk/VerityBuilder.java b/core/java/android/util/apk/VerityBuilder.java
index e81e3f7..3dfa4cd 100644
--- a/core/java/android/util/apk/VerityBuilder.java
+++ b/core/java/android/util/apk/VerityBuilder.java
@@ -90,7 +90,7 @@
             throws IOException, SecurityException, NoSuchAlgorithmException, DigestException {
         long signingBlockSize =
                 signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset;
-        long dataSize = apk.length() - signingBlockSize;
+        long dataSize = apk.getChannel().size() - signingBlockSize;
         int[] levelOffset = calculateVerityLevelOffset(dataSize);
         int merkleTreeSize = levelOffset[levelOffset.length - 1];
 
@@ -108,7 +108,7 @@
             @NonNull SignatureInfo signatureInfo, @NonNull ByteBuffer footerOutput)
             throws IOException {
         footerOutput.order(ByteOrder.LITTLE_ENDIAN);
-        generateApkVerityHeader(footerOutput, apk.length(), DEFAULT_SALT);
+        generateApkVerityHeader(footerOutput, apk.getChannel().size(), DEFAULT_SALT);
         long signingBlockSize =
                 signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset;
         generateApkVerityExtensions(footerOutput, signatureInfo.apkSigningBlockOffset,
@@ -310,11 +310,11 @@
                 eocdCdOffsetFieldPosition + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE;
         consumeByChunk(digester,
                 new MemoryMappedFileDataSource(apk.getFD(), offsetAfterEocdCdOffsetField,
-                    apk.length() - offsetAfterEocdCdOffsetField),
+                    apk.getChannel().size() - offsetAfterEocdCdOffsetField),
                 MMAP_REGION_SIZE_BYTES);
 
         // 5. Pad 0s up to the nearest 4096-byte block before hashing.
-        int lastIncompleteChunkSize = (int) (apk.length() % CHUNK_SIZE_BYTES);
+        int lastIncompleteChunkSize = (int) (apk.getChannel().size() % CHUNK_SIZE_BYTES);
         if (lastIncompleteChunkSize != 0) {
             digester.consume(ByteBuffer.allocate(CHUNK_SIZE_BYTES - lastIncompleteChunkSize));
         }
diff --git a/core/java/android/util/apk/ZipUtils.java b/core/java/android/util/apk/ZipUtils.java
index fa5477e..3ca3fc0 100644
--- a/core/java/android/util/apk/ZipUtils.java
+++ b/core/java/android/util/apk/ZipUtils.java
@@ -63,7 +63,8 @@
         // exactly the remaining bytes in the buffer. The search is bounded because the maximum
         // size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
 
-        long fileSize = zip.length();
+        // TODO(b/193592496) RandomAccessFile#length
+        long fileSize = zip.getChannel().size();
         if (fileSize < ZIP_EOCD_REC_MIN_SIZE) {
             return null;
         }
@@ -110,7 +111,8 @@
             throw new IllegalArgumentException("maxCommentSize: " + maxCommentSize);
         }
 
-        long fileSize = zip.length();
+        // TODO(b/193592496) RandomAccessFile#length
+        long fileSize = zip.getChannel().size();
         if (fileSize < ZIP_EOCD_REC_MIN_SIZE) {
             // No space for EoCD record in the file.
             return null;
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 844b156..c7609a6 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -310,7 +310,7 @@
         String extension = null;
 
         // If we couldn't do anything with the hint, move toward the content disposition
-        if (filename == null && contentDisposition != null) {
+        if (contentDisposition != null) {
             filename = parseContentDisposition(contentDisposition);
             if (filename != null) {
                 int index = filename.lastIndexOf('/') + 1;
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index ea39f6d..fcaeeff 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -396,8 +396,9 @@
                 // Prompt user to add this person to contacts
                 final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, createUri);
                 if (extras != null) {
-                    extras.remove(EXTRA_URI_CONTENT);
-                    intent.putExtras(extras);
+                    Bundle bundle = new Bundle(extras);
+                    bundle.remove(EXTRA_URI_CONTENT);
+                    intent.putExtras(bundle);
                 }
                 getContext().startActivity(intent);
             }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 0b78a2b..fcbcf6c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -140,7 +140,7 @@
 
     void noteBleScanStarted(in WorkSource ws, boolean isUnoptimized);
     void noteBleScanStopped(in WorkSource ws, boolean isUnoptimized);
-    void noteResetBleScan();
+    void noteBleScanReset();
     void noteBleScanResults(in WorkSource ws, int numNewResults);
 
     /** {@hide} */
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 6e1d3ce..5f84b5a 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -377,12 +377,15 @@
     /** Checks if this profile specifies a LegacyVpn type. */
     public static boolean isLegacyType(int type) {
         switch (type) {
-            case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: // fall through
-            case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
-            case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
-                return false;
-            default:
+            case VpnProfile.TYPE_PPTP:
+            case VpnProfile.TYPE_L2TP_IPSEC_PSK:
+            case VpnProfile.TYPE_L2TP_IPSEC_RSA:
+            case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
+            case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
+            case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
                 return true;
+            default:
+                return false;
         }
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index dd2940f..e8db609 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -66,7 +66,6 @@
 import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
-import android.telephony.ModemActivityInfo.TransmitPower;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -7205,7 +7204,7 @@
         public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
             if (mModemControllerActivity == null) {
                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
-                        ModemActivityInfo.TX_POWER_LEVELS);
+                        ModemActivityInfo.getNumTxPowerLevels());
             }
             return mModemControllerActivity;
         }
@@ -8687,7 +8686,7 @@
 
             if (in.readInt() != 0) {
                 mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
-                        ModemActivityInfo.TX_POWER_LEVELS, in);
+                        ModemActivityInfo.getNumTxPowerLevels(), in);
             } else {
                 mModemControllerActivity = null;
             }
@@ -9953,7 +9952,7 @@
         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_BT_TX_LEVELS);
         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
-                ModemActivityInfo.TX_POWER_LEVELS);
+                ModemActivityInfo.getNumTxPowerLevels());
         mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
         mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
                 mOnBatteryTimeBase);
@@ -11131,26 +11130,7 @@
         }
     }
 
-    private ModemActivityInfo mLastModemActivityInfo =
-            new ModemActivityInfo(0, 0, 0, new int[0], 0);
-
-    private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
-        if (activityInfo == null) {
-            return null;
-        }
-        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
-        for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
-            txTimeMs[i] = activityInfo.getTransmitPowerInfo().get(i).getTimeInMillis()
-                    - mLastModemActivityInfo.getTransmitPowerInfo().get(i).getTimeInMillis();
-        }
-        ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
-                activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
-                activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
-                txTimeMs,
-                activityInfo.getReceiveTimeMillis() - mLastModemActivityInfo.getReceiveTimeMillis());
-        mLastModemActivityInfo = activityInfo;
-        return deltaInfo;
-    }
+    private ModemActivityInfo mLastModemActivityInfo = null;
 
     /**
      * Distribute Cell radio energy info and network traffic to apps.
@@ -11159,7 +11139,9 @@
         if (DEBUG_ENERGY) {
             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
         }
-        ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo);
+        ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo
+                : mLastModemActivityInfo.getDelta(activityInfo);
+        mLastModemActivityInfo = activityInfo;
 
         // Add modem tx power to history.
         addModemTxPowerToHistory(deltaInfo);
@@ -11191,10 +11173,9 @@
                 mModemActivity.getSleepTimeCounter().addCountLocked(
                         deltaInfo.getSleepTimeMillis());
                 mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
-                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+                for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) {
                     mModemActivity.getTxTimeCounters()[lvl]
-                        .addCountLocked(deltaInfo.getTransmitPowerInfo()
-                            .get(lvl).getTimeInMillis());
+                        .addCountLocked(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl));
                 }
 
                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -11208,11 +11189,11 @@
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
                             + deltaInfo.getReceiveTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
-                    List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo();
-                    for (int i = 0; i < Math.min(txPowerInfo.size(),
+                    for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(),
                             CellSignalStrength.getNumSignalStrengthLevels()); i++) {
-                        energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile
-                            .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
+                        energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i)
+                                * mPowerProfile.getAveragePower(
+                                        PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
                     }
 
                     // We store the power drain as mAms.
@@ -11307,10 +11288,10 @@
                             }
 
                             if (totalTxPackets > 0 && entry.txPackets > 0) {
-                                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
-                                    long txMs =
-                                            entry.txPackets * deltaInfo.getTransmitPowerInfo()
-                                                .get(lvl).getTimeInMillis();
+                                for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
+                                        lvl++) {
+                                    long txMs = entry.txPackets
+                                            * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
                                     txMs /= totalTxPackets;
                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
                                 }
@@ -11341,20 +11322,16 @@
         if (activityInfo == null) {
             return;
         }
-        List<TransmitPower> txPowerInfo = activityInfo.getTransmitPowerInfo();
-        if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) {
-            return;
-        }
         final long elapsedRealtime = mClocks.elapsedRealtime();
         final long uptime = mClocks.uptimeMillis();
         int levelMaxTimeSpent = 0;
-        for (int i = 1; i < txPowerInfo.size(); i++) {
-            if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent)
-                .getTimeInMillis()) {
+        for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) {
+            if (activityInfo.getTransmitDurationMillisAtPowerLevel(i)
+                    > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) {
                 levelMaxTimeSpent = i;
             }
         }
-        if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
+        if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) {
             mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
             addHistoryRecordLocked(elapsedRealtime, uptime);
         }
@@ -12771,7 +12748,7 @@
            timeInRxSignalStrengthLevelMs[i]
                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
         }
-        long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
+        long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(),
             counter.getTxTimeCounters().length)];
         long totalTxTimeMs = 0;
         for (int i = 0; i < txTimeMs.length; i++) {
@@ -14817,7 +14794,7 @@
         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_BT_TX_LEVELS, in);
         mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
-                ModemActivityInfo.TX_POWER_LEVELS, in);
+                ModemActivityInfo.getNumTxPowerLevels(), in);
         mHasWifiReporting = in.readInt() != 0;
         mHasBluetoothReporting = in.readInt() != 0;
         mHasModemReporting = in.readInt() != 0;
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
index ea3b3a7..7766b77 100644
--- a/core/java/com/android/internal/os/OWNERS
+++ b/core/java/com/android/internal/os/OWNERS
@@ -10,4 +10,6 @@
 per-file *ChargeCalculator* = file:/BATTERY_STATS_OWNERS
 per-file *PowerCalculator* = file:/BATTERY_STATS_OWNERS
 per-file *PowerEstimator* = file:/BATTERY_STATS_OWNERS
+per-file *Kernel* = file:/BATTERY_STATS_OWNERS
+per-file *MultiState* = file:/BATTERY_STATS_OWNERS
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 0e02af2..cd52db4 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -33,13 +33,11 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.ZygoteProcess;
-import android.os.storage.StorageManager;
 import android.provider.DeviceConfig;
 import android.security.keystore2.AndroidKeyStoreProvider;
 import android.system.ErrnoException;
@@ -58,7 +56,6 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.Preconditions;
 
-import dalvik.system.DexFile;
 import dalvik.system.VMRuntime;
 import dalvik.system.ZygoteHooks;
 
@@ -517,7 +514,6 @@
 
         final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
         if (systemServerClasspath != null) {
-            performSystemServerDexOpt(systemServerClasspath);
             // Capturing profiles is only supported for debug or eng builds since selinux normally
             // prevents it.
             if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
@@ -659,95 +655,6 @@
     }
 
     /**
-     * Performs dex-opt on the elements of {@code classPath}, if needed. We choose the instruction
-     * set of the current runtime.
-     */
-    private static void performSystemServerDexOpt(String classPath) {
-        final String[] classPathElements = classPath.split(":");
-        final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
-
-        String classPathForElement = "";
-        for (String classPathElement : classPathElements) {
-            // We default to the verify filter because the compilation will happen on /data and
-            // system server cannot load executable code outside /system.
-            String systemServerFilter = SystemProperties.get(
-                    "dalvik.vm.systemservercompilerfilter", "verify");
-
-            String classLoaderContext =
-                        getSystemServerClassLoaderContext(classPathForElement);
-            int dexoptNeeded;
-            try {
-                dexoptNeeded = DexFile.getDexOptNeeded(
-                        classPathElement, instructionSet, systemServerFilter,
-                        classLoaderContext, false /* newProfile */, false /* downgrade */);
-            } catch (FileNotFoundException ignored) {
-                // Do not add to the classpath.
-                Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
-                continue;
-            } catch (IOException e) {
-                // Not fully clear what to do here as we don't know the cause of the
-                // IO exception. Add to the classpath to be conservative, but don't
-                // attempt to compile it.
-                Log.w(TAG, "Error checking classpath element for system server: "
-                        + classPathElement, e);
-                dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
-            }
-
-            if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                final String packageName = "*";
-                final String outputPath = null;
-                final int dexFlags = 0;
-                final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
-                final String seInfo = null;
-                final int targetSdkVersion = 0;  // SystemServer targets the system's SDK version
-                // Wait for installd to be made available
-                IInstalld installd = IInstalld.Stub.asInterface(
-                        ServiceManager.waitForService("installd"));
-
-                try {
-                    installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
-                            instructionSet, dexoptNeeded, outputPath, dexFlags, systemServerFilter,
-                            uuid, classLoaderContext, seInfo, false /* downgrade */,
-                            targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null,
-                            "server-dexopt");
-                } catch (RemoteException | ServiceSpecificException e) {
-                    // Ignore (but log), we need this on the classpath for fallback mode.
-                    Log.w(TAG, "Failed compiling classpath element for system server: "
-                            + classPathElement, e);
-                }
-            }
-
-            classPathForElement = encodeSystemServerClassPath(
-                    classPathForElement, classPathElement);
-        }
-    }
-
-    /**
-     * Encodes the system server class loader context in a format that is accepted by dexopt. This
-     * assumes the system server is always loaded with a {@link dalvik.system.PathClassLoader}.
-     *
-     * Note that ideally we would use the {@code DexoptUtils} to compute this. However we have no
-     * dependency here on the server so we hard code the logic again.
-     */
-    private static String getSystemServerClassLoaderContext(String classPath) {
-        return classPath == null ? "PCL[]" : "PCL[" + classPath + "]";
-    }
-
-    /**
-     * Encodes the class path in a format accepted by dexopt.
-     *
-     * @param classPath  The old class path (may be empty).
-     * @param newElement  The new class path elements
-     * @return The class path encoding resulted from appending {@code newElement} to {@code
-     * classPath}.
-     */
-    private static String encodeSystemServerClassPath(String classPath, String newElement) {
-        return (classPath == null || classPath.isEmpty())
-                ? newElement
-                : classPath + ":" + newElement;
-    }
-
-    /**
      * Prepare the arguments and forks for the system server process.
      *
      * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index b90722c..09bb327 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -62,6 +62,7 @@
     void onActiveDataSubIdChanged(in int subId);
     void onRadioPowerStateChanged(in int state);
     void onCallAttributesChanged(in CallAttributes callAttributes);
+    @SuppressWarnings(value={"untyped-collection"})
     void onEmergencyNumberListChanged(in Map emergencyNumberList);
     void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber, int subscriptionId);
     void onOutgoingEmergencySms(in EmergencyNumber sentEmergencyNumber, int subscriptionId);
diff --git a/core/java/com/android/internal/util/IState.java b/core/java/com/android/internal/util/IState.java
index 07837bf..41b3d5e 100644
--- a/core/java/com/android/internal/util/IState.java
+++ b/core/java/com/android/internal/util/IState.java
@@ -27,12 +27,12 @@
 public interface IState {
 
     /**
-     * Returned by processMessage to indicate the the message was processed.
+     * Returned by processMessage to indicate the message was processed.
      */
     static final boolean HANDLED = true;
 
     /**
-     * Returned by processMessage to indicate the the message was NOT processed.
+     * Returned by processMessage to indicate the message was NOT processed.
      */
     static final boolean NOT_HANDLED = false;
 
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 5b68159..100a605d 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -1,6 +1,7 @@
 per-file AsyncChannel* = lorenzo@google.com, satk@google.com, etancohen@google.com
 per-file MessageUtils*, Protocol*, RingBuffer*, TokenBucket* = jchalard@google.com, lorenzo@google.com, satk@google.com
 per-file *Notification* = file:/services/core/java/com/android/server/notification/OWNERS
+per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS
 per-file Protocol* = etancohen@google.com, lorenzo@google.com
 per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
 per-file DataClass* = eugenesusla@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/State.java b/core/java/com/android/internal/util/State.java
index 4613dad8..d5c0f60 100644
--- a/core/java/com/android/internal/util/State.java
+++ b/core/java/com/android/internal/util/State.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.util;
 
+import android.annotation.SuppressLint;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Message;
@@ -25,6 +26,7 @@
  *
  * The class for implementing states in a StateMachine
  */
+@SuppressLint("AndroidFrameworkRequiresPermission")
 public class State implements IState {
 
     /**
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 4cff785..cb8d9d1 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -48,7 +48,7 @@
  * in Object Oriented programming and are used to perform initialization and
  * cleanup of the state respectively. The <code>getName</code> method returns the
  * name of the state; the default implementation returns the class name. It may be
- * desirable to have <code>getName</code> return the the state instance name instead,
+ * desirable to have <code>getName</code> return the state instance name instead,
  * in particular if a particular state class has multiple instances.</p>
  *
  * <p>When a state machine is created, <code>addState</code> is used to build the
@@ -433,14 +433,14 @@
 
     /**
      * Convenience constant that maybe returned by processMessage
-     * to indicate the the message was processed and is not to be
+     * to indicate the message was processed and is not to be
      * processed by parent states
      */
     public static final boolean HANDLED = true;
 
     /**
      * Convenience constant that maybe returned by processMessage
-     * to indicate the the message was NOT processed and is to be
+     * to indicate the message was NOT processed and is to be
      * processed by parent states
      */
     public static final boolean NOT_HANDLED = false;
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index d6e2c2f..1132422 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -484,7 +484,7 @@
         // Vendors are only allowed to customize these
         int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
                 | ALLOW_ASSOCIATIONS;
-        if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
+        if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.O_MR1) {
             // For backward compatibility
             vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
         }
@@ -546,13 +546,14 @@
         if (!isSystemProcess()) {
             return;
         }
-        // Read configuration of libs from apex module.
+        // Read configuration of features and libs from apex module.
+        int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES;
         // TODO: Use a solid way to filter apex module folders?
         for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
             if (f.isFile() || f.getPath().contains("@")) {
                 continue;
             }
-            readPermissions(Environment.buildPath(f, "etc", "permissions"), ALLOW_LIBS);
+            readPermissions(Environment.buildPath(f, "etc", "permissions"), apexPermissionFlag);
         }
     }
 
@@ -1252,7 +1253,7 @@
             addFeature(PackageManager.FEATURE_APP_ENUMERATION, 0);
         }
 
-        if (Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.Q) {
+        if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.Q) {
             addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0);
         }
 
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 701960e..6fb2904 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -75,3 +75,7 @@
 # VINTF
 per-file android_os_VintfObject* = file:platform/system/libvintf:/OWNERS
 per-file android_os_VintfRuntimeInfo* = file:platform/system/libvintf:/OWNERS
+
+# Battery
+per-file com_android_internal_os_Kernel* = file:/BATTERY_STATS_OWNERS
+per-file com_android_internal_os_*MultiStateCounter* = file:/BATTERY_STATS_OWNERS
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 241570a..ac32038 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -98,6 +98,15 @@
     }
 }
 
+static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nativePtr,
+                                            jobject binder)
+{
+    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+    if (parcel) {
+        parcel->markForBinder(ibinderForJavaObject(env, binder));
+    }
+}
+
 static jint android_os_Parcel_dataSize(jlong nativePtr)
 {
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
@@ -766,7 +775,9 @@
 
 static const JNINativeMethod gParcelMethods[] = {
     // @CriticalNative
-    {"nativeMarkSensitive",             "(J)V", (void*)android_os_Parcel_markSensitive},
+    {"nativeMarkSensitive",       "(J)V", (void*)android_os_Parcel_markSensitive},
+    // @FastNative
+    {"nativeMarkForBinder",       "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_markForBinder},
     // @CriticalNative
     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
     // @CriticalNative
diff --git a/core/jni/android_os_ServiceManager.cpp b/core/jni/android_os_ServiceManager.cpp
index c747949..d642d0e 100644
--- a/core/jni/android_os_ServiceManager.cpp
+++ b/core/jni/android_os_ServiceManager.cpp
@@ -29,11 +29,8 @@
 
 // Native because we have a client-side wait in waitForService() and we do not
 // want an unnecessary second copy of it.
-static jobject android_os_ServiceManager_waitForService(
-        JNIEnv *env,
-        jclass /* clazzObj */,
-        jstring serviceNameObj) {
-
+static jobject android_os_ServiceManager_waitForServiceNative(JNIEnv* env, jclass /* clazzObj */,
+                                                              jstring serviceNameObj) {
     const jchar* serviceName = env->GetStringCritical(serviceNameObj, nullptr);
     if (!serviceName) {
         jniThrowNullPointerException(env, nullptr);
@@ -55,12 +52,9 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod method_table[] = {
-     /* name, signature, funcPtr */
-    {
-        "waitForService",
-        "(Ljava/lang/String;)Landroid/os/IBinder;",
-        (void*)android_os_ServiceManager_waitForService
-    },
+        /* name, signature, funcPtr */
+        {"waitForServiceNative", "(Ljava/lang/String;)Landroid/os/IBinder;",
+         (void*)android_os_ServiceManager_waitForServiceNative},
 };
 
 int register_android_os_ServiceManager(JNIEnv* env) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 6374305..ff9e27f 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -263,8 +263,12 @@
         sprintf(proc_path, "/proc/%d/cmdline", pid);
         fd = open(proc_path, O_RDONLY | O_CLOEXEC);
         if (fd >= 0) {
-            int rc = read(fd, cmdline, sizeof(cmdline)-1);
-            cmdline[rc] = 0;
+            ssize_t rc = read(fd, cmdline, sizeof(cmdline) - 1);
+            if (rc < 0) {
+                ALOGE("read /proc/%d/cmdline (%s)", pid, strerror(errno));
+            } else {
+                cmdline[rc] = 0;
+            }
             close(fd);
         }
 
diff --git a/core/jni/com_android_internal_content_om_OverlayConfig.cpp b/core/jni/com_android_internal_content_om_OverlayConfig.cpp
index 6aa7c10..b37269c 100644
--- a/core/jni/com_android_internal_content_om_OverlayConfig.cpp
+++ b/core/jni/com_android_internal_content_om_OverlayConfig.cpp
@@ -73,13 +73,13 @@
   }
 
   if (result->status != 0) {
-    LOG(ERROR) << "idmap2: " << result->stderr;
-    return nullptr;
+      LOG(ERROR) << "idmap2: " << result->stderr_str;
+      return nullptr;
   }
 
   // Return the paths of the idmaps created or updated during the idmap invocation.
   std::vector<std::string> idmap_paths;
-  std::istringstream input(result->stdout);
+  std::istringstream input(result->stdout_str);
   std::string path;
   while (std::getline(input, path)) {
     idmap_paths.push_back(path);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 292ba47..288327e 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -62,7 +62,6 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/un.h>
-#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -837,26 +836,6 @@
   }
 }
 
-static bool NeedsNoRandomizeWorkaround() {
-#if !defined(__arm__)
-    return false;
-#else
-    int major;
-    int minor;
-    struct utsname uts;
-    if (uname(&uts) == -1) {
-        return false;
-    }
-
-    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
-        return false;
-    }
-
-    // Kernels before 3.4.* need the workaround.
-    return (major < 3) || ((major == 3) && (minor < 4));
-#endif
-}
-
 // Utility to close down the Zygote socket file descriptors while
 // the child is still running as root with Zygote's privileges.  Each
 // descriptor (if any) is closed via dup3(), replacing it with a valid
@@ -874,7 +853,7 @@
 
     for (int fd : fds_to_close) {
       ALOGV("Switching descriptor %d to /dev/null", fd);
-      if (dup3(devnull_fd, fd, O_CLOEXEC) == -1) {
+      if (TEMP_FAILURE_RETRY(dup3(devnull_fd, fd, O_CLOEXEC)) == -1) {
         fail_fn(StringPrintf("Failed dup3() on descriptor %d: %s", fd, strerror(errno)));
       }
     }
@@ -1150,14 +1129,14 @@
 }
 
 // Relabel directory
-static void relabelDir(const char* path, security_context_t context, fail_fn_t fail_fn) {
+static void relabelDir(const char* path, const char* context, fail_fn_t fail_fn) {
   if (setfilecon(path, context) != 0) {
     fail_fn(CREATE_ERROR("Failed to setfilecon %s %s", path, strerror(errno)));
   }
 }
 
 // Relabel all directories under a path non-recursively.
-static void relabelAllDirs(const char* path, security_context_t context, fail_fn_t fail_fn) {
+static void relabelAllDirs(const char* path, const char* context, fail_fn_t fail_fn) {
   DIR* dir = opendir(path);
   if (dir == nullptr) {
     fail_fn(CREATE_ERROR("Failed to opendir %s", path));
@@ -1232,7 +1211,7 @@
   snprintf(internalDePath, PATH_MAX, "/data/user_de");
   snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
 
-  security_context_t dataDataContext = nullptr;
+  char* dataDataContext = nullptr;
   if (getfilecon(internalDePath, &dataDataContext) < 0) {
     fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath,
         strerror(errno)));
@@ -1687,15 +1666,6 @@
     // runtime.
     runtime_flags &= ~RuntimeFlags::GWP_ASAN_LEVEL_MASK;
 
-    if (NeedsNoRandomizeWorkaround()) {
-        // Work around ARM kernel ASLR lossage (http://b/5817320).
-        int old_personality = personality(0xffffffff);
-        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
-        if (new_personality == -1) {
-            ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
-        }
-    }
-
     SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
                     fail_fn);
 
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 5fe96ed..248db76 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -426,7 +426,7 @@
       tmp_pid >>= 8;
     }
     pid_buf[4] = 0;  // Process is not wrapped.
-    int res = write(session_socket, pid_buf, 5);
+    int res = TEMP_FAILURE_RETRY(write(session_socket, pid_buf, 5));
     if (res != 5) {
       if (res == -1) {
         (first_time ? fail_fn_1 : fail_fn_n)
@@ -451,18 +451,18 @@
       }
       // We've now seen either a disconnect or connect request.
       close(session_socket);
-      int new_fd = accept(zygote_socket_fd, nullptr, nullptr);
+      int new_fd = TEMP_FAILURE_RETRY(accept(zygote_socket_fd, nullptr, nullptr));
       if (new_fd == -1) {
         fail_fn_z(CREATE_ERROR("Accept(%d) failed: %s", zygote_socket_fd, strerror(errno)));
       }
       if (new_fd != session_socket) {
           // Move new_fd back to the old value, so that we don't have to change Java-level data
           // structures to reflect a change. This implicitly closes the old one.
-          if (dup2(new_fd, session_socket) != session_socket) {
+          if (TEMP_FAILURE_RETRY(dup2(new_fd, session_socket)) != session_socket) {
             fail_fn_z(CREATE_ERROR("Failed to move fd %d to %d: %s",
                                    new_fd, session_socket, strerror(errno)));
           }
-          close(new_fd);
+          close(new_fd);  //  On Linux, fd is closed even if EINTR is returned.
       }
       // If we ever return, we effectively reuse the old Java ZygoteConnection.
       // None of its state needs to change.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a761d02..35a3cde 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -196,6 +196,9 @@
         android:name="android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED" />
+    <protected-broadcast android:name="android.bluetooth.action.CSIS_DEVICE_AVAILABLE" />
+    <protected-broadcast android:name="android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE" />
     <protected-broadcast
         android:name="android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
@@ -3226,6 +3229,13 @@
     <permission android:name="android.permission.TRIGGER_SHELL_BUGREPORT"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to trigger profcollect report upload via shell.
+        <p>Not for use by third-party applications.
+        @hide
+    -->
+    <permission android:name="android.permission.TRIGGER_SHELL_PROFCOLLECT_UPLOAD"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to be the status bar.  Currently used only by SystemUI.apk
     @hide -->
     <permission android:name="android.permission.STATUS_BAR_SERVICE"
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 7a8da36..684202b 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -25,3 +25,6 @@
 toddke@google.com
 tsuji@google.com
 yamasani@google.com
+
+# Multiuser
+per-file res/xml/config_user_types.xml = file:/MULTIUSER_OWNERS
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6f5fbae..14d3147 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4310,6 +4310,15 @@
     <!-- The package name for the default bug report handler app from power menu short press. This app must be allowlisted. -->
     <string name="config_defaultBugReportHandlerApp" translatable="false"></string>
 
+    <!-- When true, enables the allowlisted app to upload profcollect reports. -->
+    <bool name="config_profcollectReportUploaderEnabled">false</bool>
+
+    <!-- The package name for the default profcollect report uploader app. This app must be allowlisted. -->
+    <string name="config_defaultProfcollectReportUploaderApp" translatable="false"></string>
+
+    <!-- The action name for the default profcollect report uploader app. -->
+    <string name="config_defaultProfcollectReportUploaderAction" translatable="false"></string>
+
     <!-- The default value used for RawContacts.ACCOUNT_NAME when contacts are inserted without this
          column set. These contacts are stored locally on the device and will not be removed even
          if no android.account.Account with this name exists. A null string will be used if the
@@ -4426,4 +4435,9 @@
 
     <!-- Whether to allow the caching of the SIM PIN for verification after unattended reboot -->
     <bool name="config_allow_pin_storage_for_unattended_reboot">true</bool>
+
+    <!-- Whether the device enable the standalone (SA) mode of 5G NR.-->
+    <bool name="config_telephony5gStandalone">false</bool>
+    <!-- Whether the device enable the non-standalone (NSA) mode of 5G NR.-->
+    <bool name="config_telephony5gNonStandalone">false</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6a4702b..c1c1858 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3046,6 +3046,9 @@
     <public name="canPauseRecording" />
     <!-- attribute definitions go here -->
     <public name="requireDeviceScreenOn" />
+  </public-group>
+
+  <public-group type="attr" first-id="0x01010624">
     <public name="memtagMode" />
     <public name="nativeHeapZeroInitialized" />
   </public-group>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c50c494..2be5152 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3876,6 +3876,11 @@
   <java-symbol type="bool" name="config_bugReportHandlerEnabled" />
   <java-symbol type="string" name="config_defaultBugReportHandlerApp" />
 
+  <!-- For profcollect report uploader -->
+  <java-symbol type="bool" name="config_profcollectReportUploaderEnabled" />
+  <java-symbol type="string" name="config_defaultProfcollectReportUploaderApp" />
+  <java-symbol type="string" name="config_defaultProfcollectReportUploaderAction" />
+
   <java-symbol type="string" name="usb_device_resolve_prompt_warn" />
 
   <!-- For Accessibility system actions -->
@@ -4075,4 +4080,7 @@
   <java-symbol type="array" name="config_keep_warming_services" />
 
   <java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
+
+  <java-symbol type="bool" name="config_telephony5gStandalone" />
+  <java-symbol type="bool" name="config_telephony5gNonStandalone" />
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 2be5c47..f1c66c5 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -88,9 +88,12 @@
     <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
 
-    <!-- Czechia: 7-8 digits, starting with 9, plus EU:
-         http://www.o2.cz/osobni/en/services-by-alphabet/91670-premium_sms.html -->
-    <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
+    <!-- Czechia: Premium numbers start with 90, and are either 5 or 7 digits (5 digits is a
+         subscription request, you will be charged for the messages received, but it's necessary
+         to warn on the _request_ as that's the last chance to stop), plus EU:
+         https://www.t-mobile.cz/platebni-a-premium-sms
+         https://www.vodafone.cz/pece/vyuctovani-platby-kredit/platby-mobilem/cena-premium-sms/ -->
+    <shortcode country="cz" premium="90\\d{5}|90\\d{3}" free="116\\d{3}" />
 
     <!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
     <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240|72438" />
@@ -262,7 +265,7 @@
 
     <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm),
          visual voicemail code for T-Mobile: 122 -->
-    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245" />
+    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611" />
 
     <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055" />
diff --git a/core/tests/BroadcastRadioTests/OWNERS b/core/tests/BroadcastRadioTests/OWNERS
index ea4421e..3e360e7 100644
--- a/core/tests/BroadcastRadioTests/OWNERS
+++ b/core/tests/BroadcastRadioTests/OWNERS
@@ -1,2 +1,3 @@
+keunyoung@google.com
+oscarazu@google.com
 twasilczyk@google.com
-randolphs@google.com
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 000e870..2d63351 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -88,6 +88,11 @@
                     false /* launchActivity */);
 
     @Test
+    public void testTemporaryDirectory() throws Exception {
+        assertEquals(System.getProperty("java.io.tmpdir"), System.getenv("TMPDIR"));
+    }
+
+    @Test
     public void testDoubleRelaunch() throws Exception {
         final Activity activity = mActivityTestRule.launchActivity(new Intent());
         final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
diff --git a/core/tests/coretests/src/com/android/internal/util/OWNERS b/core/tests/coretests/src/com/android/internal/util/OWNERS
new file mode 100644
index 0000000..d832745
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/OWNERS
@@ -0,0 +1,2 @@
+per-file *Notification* = file:/services/core/java/com/android/server/notification/OWNERS
+per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS
\ No newline at end of file
diff --git a/core/tests/hosttests/Android.mk b/core/tests/hosttests/Android.mk
deleted file mode 100644
index f26d401..0000000
--- a/core/tests/hosttests/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Build the test APKs using their own makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/hosttests/test-apps/Android.mk b/core/tests/hosttests/test-apps/Android.mk
deleted file mode 100644
index e25764f..0000000
--- a/core/tests/hosttests/test-apps/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Build the test APKs using their own makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.bp b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.bp
new file mode 100644
index 0000000..d439124
--- /dev/null
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.bp
@@ -0,0 +1,38 @@
+// 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.
+
+package {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "DownloadManagerTestApp",
+
+    srcs: ["src/**/*.java"],
+
+    static_libs: [
+        "android-common",
+        "mockwebserver",
+        "junit",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+
+    platform_apis: true,
+
+    // Need to run as system app to get access to Settings. This test won't work for user builds.
+    certificate: "platform",
+}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
deleted file mode 100644
index d9e6151..0000000
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-common mockwebserver junit
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-
-LOCAL_PACKAGE_NAME := DownloadManagerTestApp
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-ifneq ($(TARGET_BUILD_VARIANT),user)
-# Need to run as system app to get access to Settings. This test won't work for user builds.
-LOCAL_CERTIFICATE := platform
-endif
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.bp
new file mode 100644
index 0000000..d0645b0
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.bp
@@ -0,0 +1,47 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// The application with a minimal main dex
+android_test_helper_app {
+    name: "MultiDexLegacyAndException",
+
+    static_libs: [
+        "android-support-multidex",
+        "android-support-multidex-instrumentation",
+        "androidx.test.rules",
+    ],
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    javacflags: ["-nowarn"],
+
+    main_dex_rules: [":mainDexClassesRules"],
+    dxflags: [
+        // --debug triggers the old --minimal-main-dex behavior
+        "--debug",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+
+    min_sdk_version: "16",
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
deleted file mode 100644
index 2d8556f..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ /dev/null
@@ -1,51 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-
-## The application with a minimal main dex
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex android-support-multidex-instrumentation androidx.test.rules
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 8
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyAndException
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_JAVACFLAGS := -nowarn
-
-mainDexList:= \
-    $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
-LOCAL_MIN_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-	echo "com/android/multidexlegacyandexception/Test.class" >> $@
-
-$(built_dex_intermediate): $(mainDexList)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.bp
new file mode 100644
index 0000000..c0c8aba
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.bp
@@ -0,0 +1,70 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// The application with a minimal main dex
+android_test_helper_app {
+    name: "MultiDexLegacyTestApp",
+
+    static_libs: ["android-support-multidex"],
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    main_dex_rules: [
+        ":mainDexClassesRules",
+        "mainDexClasses.rules",
+    ],
+    dxflags: [
+        // --debug triggers the old --minimal-main-dex behavior
+        "--debug",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+
+    min_sdk_version: "16",
+}
+
+android_test_helper_app {
+    name: "MultiDexLegacyTestApp2",
+
+    static_libs: ["android-support-multidex"],
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    main_dex_rules: [
+        ":mainDexClassesRules",
+        "mainDexClasses.rules",
+    ],
+    dxflags: [
+        // --release disables the old --minimal-main-dex behavior
+        "--release",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+
+    min_sdk_version: "16",
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
deleted file mode 100644
index d7af2d9..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ /dev/null
@@ -1,87 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-
-## The application with a minimal main dex
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 8
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_EMMA_INSTRUMENT := false
-
-mainDexList:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
-LOCAL_MIN_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-	echo "com/android/multidexlegacytestapp/Test.class" >> $@
-
-$(built_dex_intermediate): $(mainDexList)
-
-## The application with a full main dex
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 8
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_EMMA_INSTRUMENT := false
-
-mainDexList2:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2)
-
-LOCAL_MIN_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList2): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-	echo "com/android/multidexlegacytestapp/Test.class" >> $@
-
-$(built_dex_intermediate): $(mainDexList2)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/mainDexClasses.rules b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/mainDexClasses.rules
new file mode 100644
index 0000000..91e6ddb
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/mainDexClasses.rules
@@ -0,0 +1 @@
+-keep class com.android.multidexlegacytestapp.Test
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.bp
new file mode 100644
index 0000000..fe29416
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.bp
@@ -0,0 +1,34 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// The application with a minimal main dex
+android_test {
+    name: "MultiDexLegacyTestAppTests",
+
+    static_libs: ["android-support-multidex-instrumentation"],
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    javacflags: ["-nowarn"],
+
+    min_sdk_version: "16",
+
+    instrumentation_for: "MultiDexLegacyTestApp",
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.mk
deleted file mode 100644
index 236c740..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.mk
+++ /dev/null
@@ -1,43 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-
-## The application with a minimal main dex
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex-instrumentation
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 8
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestAppTests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_JAVACFLAGS := -nowarn
-
-LOCAL_MIN_SDK_VERSION := 8
-
-LOCAL_INSTRUMENTATION_FOR := MultiDexLegacyTestApp
-
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.bp
new file mode 100644
index 0000000..c558153
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.bp
@@ -0,0 +1,57 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// The tests with only one dex
+android_test {
+    name: "MultiDexLegacyTestAppTests2",
+
+    static_libs: [
+        "android-support-multidex-instrumentation",
+        "androidx.test.rules",
+    ],
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    javacflags: ["-nowarn"],
+
+    min_sdk_version: "16",
+
+    instrumentation_for: "MultiDexLegacyTestApp",
+}
+
+// The tests with a minimal main dex
+android_test {
+    name: "MultiDexLegacyTestAppTests2-multidex",
+
+    static_libs: [
+        "android-support-multidex-instrumentation",
+        "androidx.test.rules",
+    ],
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    javacflags: ["-nowarn"],
+
+    min_sdk_version: "16",
+
+    instrumentation_for: "MultiDexLegacyTestApp",
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.mk
deleted file mode 100644
index 6f6ccfe..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.mk
+++ /dev/null
@@ -1,69 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-
-## The tests with only one dex
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex-instrumentation androidx.test.rules
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestAppTests2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_JAVACFLAGS := -nowarn
-
-LOCAL_MIN_SDK_VERSION := 8
-
-LOCAL_INSTRUMENTATION_FOR := MultiDexLegacyTestApp
-
-include $(BUILD_PACKAGE)
-
-
-## The tests with a minimal main dex
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex-instrumentation androidx.test.rules
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 8
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestAppTests2-multidex
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_JAVACFLAGS := -nowarn
-
-LOCAL_MIN_SDK_VERSION := 8
-
-LOCAL_INSTRUMENTATION_FOR := MultiDexLegacyTestApp
-
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/Android.bp
new file mode 100644
index 0000000..15bc4efb
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/Android.bp
@@ -0,0 +1,48 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "MultiDexLegacyTestApp_without_corrupted",
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    static_libs: ["android-support-multidex"],
+}
+
+java_genrule {
+    name: "MultiDexLegacyTestApp_genrule",
+    srcs: [
+        ":MultiDexLegacyTestApp_without_corrupted",
+    ],
+    tools: [
+        "soong_zip",
+        "merge_zips",
+    ],
+    out: ["MultiDexLegacyTestApp_with_corrupted.apk"],
+    cmd: "touch $(genDir)/classes2.dex &&" +
+        " $(location soong_zip) -o $(genDir)/corrupted.zip -j -f $(genDir)/classes2.dex &&" +
+        " $(location merge_zips) $(out) $(location :MultiDexLegacyTestApp_without_corrupted) $(genDir)/corrupted.zip",
+}
+
+android_test_import {
+    name: "MultiDexLegacyTestApp_corrupted",
+    apk: ":MultiDexLegacyTestApp_genrule",
+    default_dev_cert: true,
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/Android.mk
deleted file mode 100644
index 33a46ea..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppWithCorruptedDex/Android.mk
+++ /dev/null
@@ -1,41 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 18
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp_corrupted
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
-
-corrupted_classes2_dex := $(dir $(built_dex))/classes2.dex
-
-$(corrupted_classes2_dex): $(built_dex)
-	$(hide) touch $@
-
-$(LOCAL_BUILT_MODULE): $(corrupted_classes2_dex)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.bp
new file mode 100644
index 0000000..de0657f
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.bp
@@ -0,0 +1,38 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "MultiDexLegacyTestServices",
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    static_libs: ["android-support-multidex"],
+
+    main_dex_rules: [":mainDexClassesRules"],
+    dxflags: [
+        // --debug triggers the old --minimal-main-dex behavior
+        "--debug",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
deleted file mode 100644
index efc0688..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ /dev/null
@@ -1,47 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 9
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestServices
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-
-mainDexList:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_EMMA_INSTRUMENT := false
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-
-$(built_dex_intermediate): $(mainDexList)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp
index 56f10fe..b62b25c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp
@@ -24,7 +24,7 @@
 android_test {
     name: "MultiDexLegacyTestServicesTests",
     srcs: ["src/**/*.java"],
-    sdk_version: "9",
+    sdk_version: "16",
     dex_preopt: {
         enabled: false,
     },
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.bp
new file mode 100644
index 0000000..75c753c
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.bp
@@ -0,0 +1,28 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "MultiDexLegacyTestServicesTests2",
+
+    srcs: ["src/**/*.java"],
+
+    libs: ["android-support-multidex"],
+    static_libs: ["androidx.test.rules"],
+
+    sdk_version: "16",
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
deleted file mode 100644
index 3920fd6..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
+++ /dev/null
@@ -1,35 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyTestServicesTests2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_JAVA_LIBRARIES := android-support-multidex
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-LOCAL_SDK_VERSION := 9
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.bp
new file mode 100644
index 0000000..23c62dc
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.bp
@@ -0,0 +1,41 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "MultiDexLegacyVersionedTestApp_v1",
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    static_libs: ["android-support-multidex"],
+
+    main_dex_rules: [
+        ":mainDexClassesRules",
+        "mainDexClasses.rules",
+    ],
+    dxflags: [
+        // --debug triggers the old --minimal-main-dex behavior
+        "--debug",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
deleted file mode 100644
index 2323ad9..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ /dev/null
@@ -1,48 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 9
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v1
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_EMMA_INSTRUMENT := false
-
-mainDexList:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
-
-$(built_dex_intermediate): $(mainDexList)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/mainDexClasses.rules b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/mainDexClasses.rules
new file mode 100644
index 0000000..1cdf3af
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/mainDexClasses.rules
@@ -0,0 +1 @@
+-keep class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.bp
new file mode 100644
index 0000000..6cd3df7
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.bp
@@ -0,0 +1,41 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "MultiDexLegacyVersionedTestApp_v2",
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    static_libs: ["android-support-multidex"],
+
+    main_dex_rules: [
+        ":mainDexClassesRules",
+        "mainDexClasses.rules",
+    ],
+    dxflags: [
+        // --debug triggers the old --minimal-main-dex behavior
+        "--debug",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
deleted file mode 100644
index 79a5906..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ /dev/null
@@ -1,48 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 9
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v2
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_EMMA_INSTRUMENT := false
-
-mainDexList:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
-
-$(built_dex_intermediate): $(mainDexList)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/mainDexClasses.rules b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/mainDexClasses.rules
new file mode 100644
index 0000000..1cdf3af
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/mainDexClasses.rules
@@ -0,0 +1 @@
+-keep class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.bp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.bp
new file mode 100644
index 0000000..34dba40
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.bp
@@ -0,0 +1,41 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "MultiDexLegacyVersionedTestApp_v3",
+
+    srcs: ["src/**/*.java"],
+
+    sdk_version: "16",
+
+    static_libs: ["android-support-multidex"],
+
+    main_dex_rules: [
+        ":mainDexClassesRules",
+        "mainDexClasses.rules",
+    ],
+    dxflags: [
+        // --debug triggers the old --minimal-main-dex behavior
+        "--debug",
+    ],
+    optimize: {
+        // disable optimization to force D8 instead of R8, as R8 doesn't support
+        // --main-dex-rules.
+        enabled: false,
+    },
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
deleted file mode 100644
index 521bad0..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ /dev/null
@@ -1,48 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 9
-
-LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v3
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
-
-mainDexList:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_EMMA_INSTRUMENT := false
-
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
-include $(BUILD_PACKAGE)
-
-$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS)
-	$(hide) mkdir -p $(dir $@)
-	PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@
-	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
-
-$(built_dex_intermediate): $(mainDexList)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/mainDexClasses.rules b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/mainDexClasses.rules
new file mode 100644
index 0000000..1cdf3af
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/mainDexClasses.rules
@@ -0,0 +1 @@
+-keep class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
index edf473e..b85cb9c 100644
--- a/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
@@ -542,83 +542,83 @@
     public void testStateMachineEnterExitTransitionToTest() throws Exception {
         //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
 
-        StateMachineEnterExitTransitionToTest smEnterExitTranstionToTest =
-            new StateMachineEnterExitTransitionToTest("smEnterExitTranstionToTest");
-        smEnterExitTranstionToTest.start();
-        if (smEnterExitTranstionToTest.isDbg()) {
+        StateMachineEnterExitTransitionToTest smEnterExitTransitionToTest =
+                new StateMachineEnterExitTransitionToTest("smEnterExitTransitionToTest");
+        smEnterExitTransitionToTest.start();
+        if (smEnterExitTransitionToTest.isDbg()) {
             tlog("testStateMachineEnterExitTransitionToTest E");
         }
 
-        synchronized (smEnterExitTranstionToTest) {
-            smEnterExitTranstionToTest.sendMessage(TEST_CMD_1);
+        synchronized (smEnterExitTransitionToTest) {
+            smEnterExitTransitionToTest.sendMessage(TEST_CMD_1);
 
             try {
                 // wait for the messages to be handled
-                smEnterExitTranstionToTest.wait();
+                smEnterExitTransitionToTest.wait();
             } catch (InterruptedException e) {
                 tloge("testStateMachineEnterExitTransitionToTest: exception while waiting "
                     + e.getMessage());
             }
         }
 
-        dumpLogRecs(smEnterExitTranstionToTest);
+        dumpLogRecs(smEnterExitTransitionToTest);
 
-        assertEquals(9, smEnterExitTranstionToTest.getLogRecCount());
+        assertEquals(9, smEnterExitTransitionToTest.getLogRecCount());
         LogRec lr;
 
-        lr = smEnterExitTranstionToTest.getLogRec(0);
+        lr = smEnterExitTransitionToTest.getLogRec(0);
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS1, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS1, lr.getState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(1);
+        lr = smEnterExitTransitionToTest.getLogRec(1);
         assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS1, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS1, lr.getState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(2);
+        lr = smEnterExitTransitionToTest.getLogRec(2);
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(3);
+        lr = smEnterExitTransitionToTest.getLogRec(3);
         assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(4);
+        lr = smEnterExitTransitionToTest.getLogRec(4);
         assertEquals(TEST_CMD_1, lr.getWhat());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS2, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
         assertEquals(EXIT, lr.getInfo());
 
-        lr = smEnterExitTranstionToTest.getLogRec(5);
+        lr = smEnterExitTransitionToTest.getLogRec(5);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(6);
+        lr = smEnterExitTransitionToTest.getLogRec(6);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS3, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(7);
+        lr = smEnterExitTransitionToTest.getLogRec(7);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(ENTER, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getDestState());
 
-        lr = smEnterExitTranstionToTest.getLogRec(8);
+        lr = smEnterExitTransitionToTest.getLogRec(8);
         assertEquals(TEST_CMD_1, lr.getWhat());
         assertEquals(EXIT, lr.getInfo());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
-        assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getState());
+        assertEquals(smEnterExitTransitionToTest.mS4, lr.getOriginalState());
 
-        if (smEnterExitTranstionToTest.isDbg()) {
+        if (smEnterExitTransitionToTest.isDbg()) {
             tlog("testStateMachineEnterExitTransitionToTest X");
         }
     }
diff --git a/identity/java/android/security/identity/IdentityCredential.java b/identity/java/android/security/identity/IdentityCredential.java
index 8f175bb..1e68585 100644
--- a/identity/java/android/security/identity/IdentityCredential.java
+++ b/identity/java/android/security/identity/IdentityCredential.java
@@ -160,7 +160,7 @@
      * not the case, the {@link SessionTranscriptMismatchException} exception is thrown.
      *
      * <p>If not {@code null} the {@code requestMessage} parameter must contain data for the request
-     * from the verifier. The content can be defined in the way appropriate for the credential, byt
+     * from the verifier. The content can be defined in the way appropriate for the credential, but
      * there are three requirements that must be met to work with this API:
      * <ul>
      * <li>The content must be a CBOR-encoded structure.</li>
@@ -205,9 +205,9 @@
      * must appear somewhere in {@code sessionTranscript} and ditto for the 32 bytes for the Y
      * coordinate.
      *
-     * <p>If {@code readerAuth} is not {@code null} it must be the bytes of a {@code COSE_Sign1}
-     * structure as defined in RFC 8152. For the payload nil shall be used and the
-     * detached payload is the ReaderAuthenticationBytes CBOR described below.
+     * <p>If {@code readerSignature} is not {@code null} it must be the bytes of a
+     * {@code COSE_Sign1} structure as defined in RFC 8152. For the payload nil shall be used and
+     * the detached payload is the ReaderAuthenticationBytes CBOR described below.
      * <pre>
      *     ReaderAuthentication = [
      *       "ReaderAuthentication",
diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java
index 053bec74..2e54e63 100644
--- a/keystore/java/android/security/GenerateRkpKey.java
+++ b/keystore/java/android/security/GenerateRkpKey.java
@@ -25,6 +25,8 @@
 import android.util.Log;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -88,7 +90,8 @@
         }
         intent.setComponent(comp);
         mCountDownLatch = new CountDownLatch(1);
-        if (!mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
+        Executor executor = Executors.newCachedThreadPool();
+        if (!mContext.bindService(intent, Context.BIND_AUTO_CREATE, executor, mConnection)) {
             throw new RemoteException("Failed to bind to GenerateRkpKeyService");
         }
         try {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java
index 5619585..b24a22d 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java
@@ -102,11 +102,9 @@
         final int prime = 31;
         int result = 1;
 
-        result = prime * result + ((mDescriptor == null) ? 0 : mDescriptor.hashCode());
+        result = prime * result + getClass().hashCode();
         result = prime * result + (int) (mKeyId >>> 32);
         result = prime * result + (int) (mKeyId & 0xffffffff);
-        result = prime * result + ((mAuthorizations == null) ? 0 : mAuthorizations.hashCode());
-        result = prime * result + ((mAlgorithm == null) ? 0 : mAlgorithm.hashCode());
         return result;
     }
 
@@ -122,10 +120,6 @@
             return false;
         }
         AndroidKeyStoreKey other = (AndroidKeyStoreKey) obj;
-        if (mKeyId != other.mKeyId) {
-            return false;
-        }
-
-        return true;
+        return mKeyId == other.mKeyId;
     }
 }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java
index db3e567..4842984 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java
@@ -23,6 +23,7 @@
 import android.system.keystore2.KeyMetadata;
 
 import java.security.PublicKey;
+import java.util.Objects;
 
 /**
  * {@link PublicKey} backed by Android Keystore.
@@ -75,9 +76,14 @@
         if (!super.equals(obj)) {
             return false;
         }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        return true;
+
+        /*
+         * getClass().equals(ojb.getClass()) is implied by the call to super.equals() above. This
+         * means we can cast obj to AndroidKeyStorePublicKey here.
+         */
+        final AndroidKeyStorePublicKey other = (AndroidKeyStorePublicKey) obj;
+
+        return Objects.equals(mCertificate, other.mCertificate) && Objects.equals(mCertificateChain,
+                other.mCertificateChain);
     }
 }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index f3cfcf1..67358c4 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -579,7 +579,7 @@
         //
         // Note: mNamespace == KeyProperties.NAMESPACE_APPLICATION implies that the target domain
         // is Domain.APP and Domain.SELINUX is the target domain otherwise.
-        if (alias != descriptor.alias
+        if (!alias.equals(descriptor.alias)
                 || descriptor.domain != targetDomain
                 || (descriptor.domain == Domain.SELINUX && descriptor.nspace != targetNamespace)) {
             throw new KeyStoreException("Can only replace keys with same alias: " + alias
diff --git a/libs/androidfw/LocaleDataTables.cpp b/libs/androidfw/LocaleDataTables.cpp
index 8a10599..2c3567a 100644
--- a/libs/androidfw/LocaleDataTables.cpp
+++ b/libs/androidfw/LocaleDataTables.cpp
@@ -1,37 +1,37 @@
 // Auto-generated by ./tools/localedata/extract_icu_data.py
 
 const char SCRIPT_CODES[][4] = {
-    /* 0  */ {'A', 'h', 'o', 'm'},
-    /* 1  */ {'A', 'r', 'a', 'b'},
-    /* 2  */ {'A', 'r', 'm', 'i'},
-    /* 3  */ {'A', 'r', 'm', 'n'},
-    /* 4  */ {'A', 'v', 's', 't'},
-    /* 5  */ {'B', 'a', 'm', 'u'},
-    /* 6  */ {'B', 'a', 's', 's'},
-    /* 7  */ {'B', 'e', 'n', 'g'},
-    /* 8  */ {'B', 'r', 'a', 'h'},
-    /* 9  */ {'C', 'a', 'k', 'm'},
-    /* 10 */ {'C', 'a', 'n', 's'},
-    /* 11 */ {'C', 'a', 'r', 'i'},
-    /* 12 */ {'C', 'h', 'a', 'm'},
-    /* 13 */ {'C', 'h', 'e', 'r'},
-    /* 14 */ {'C', 'h', 'r', 's'},
-    /* 15 */ {'C', 'o', 'p', 't'},
-    /* 16 */ {'C', 'p', 'r', 't'},
-    /* 17 */ {'C', 'y', 'r', 'l'},
-    /* 18 */ {'D', 'e', 'v', 'a'},
-    /* 19 */ {'E', 'g', 'y', 'p'},
-    /* 20 */ {'E', 't', 'h', 'i'},
-    /* 21 */ {'G', 'e', 'o', 'r'},
-    /* 22 */ {'G', 'o', 'n', 'g'},
-    /* 23 */ {'G', 'o', 'n', 'm'},
-    /* 24 */ {'G', 'o', 't', 'h'},
-    /* 25 */ {'G', 'r', 'e', 'k'},
-    /* 26 */ {'G', 'u', 'j', 'r'},
-    /* 27 */ {'G', 'u', 'r', 'u'},
-    /* 28 */ {'H', 'a', 'n', 's'},
-    /* 29 */ {'H', 'a', 'n', 't'},
-    /* 30 */ {'H', 'a', 't', 'r'},
+    /* 0  */ {'A', 'g', 'h', 'b'},
+    /* 1  */ {'A', 'h', 'o', 'm'},
+    /* 2  */ {'A', 'r', 'a', 'b'},
+    /* 3  */ {'A', 'r', 'm', 'i'},
+    /* 4  */ {'A', 'r', 'm', 'n'},
+    /* 5  */ {'A', 'v', 's', 't'},
+    /* 6  */ {'B', 'a', 'm', 'u'},
+    /* 7  */ {'B', 'a', 's', 's'},
+    /* 8  */ {'B', 'e', 'n', 'g'},
+    /* 9  */ {'B', 'r', 'a', 'h'},
+    /* 10 */ {'C', 'a', 'k', 'm'},
+    /* 11 */ {'C', 'a', 'n', 's'},
+    /* 12 */ {'C', 'a', 'r', 'i'},
+    /* 13 */ {'C', 'h', 'a', 'm'},
+    /* 14 */ {'C', 'h', 'e', 'r'},
+    /* 15 */ {'C', 'h', 'r', 's'},
+    /* 16 */ {'C', 'o', 'p', 't'},
+    /* 17 */ {'C', 'p', 'r', 't'},
+    /* 18 */ {'C', 'y', 'r', 'l'},
+    /* 19 */ {'D', 'e', 'v', 'a'},
+    /* 20 */ {'E', 'g', 'y', 'p'},
+    /* 21 */ {'E', 't', 'h', 'i'},
+    /* 22 */ {'G', 'e', 'o', 'r'},
+    /* 23 */ {'G', 'o', 'n', 'g'},
+    /* 24 */ {'G', 'o', 'n', 'm'},
+    /* 25 */ {'G', 'o', 't', 'h'},
+    /* 26 */ {'G', 'r', 'e', 'k'},
+    /* 27 */ {'G', 'u', 'j', 'r'},
+    /* 28 */ {'G', 'u', 'r', 'u'},
+    /* 29 */ {'H', 'a', 'n', 's'},
+    /* 30 */ {'H', 'a', 'n', 't'},
     /* 31 */ {'H', 'e', 'b', 'r'},
     /* 32 */ {'H', 'l', 'u', 'w'},
     /* 33 */ {'H', 'm', 'n', 'g'},
@@ -55,52 +55,53 @@
     /* 51 */ {'L', 'y', 'd', 'i'},
     /* 52 */ {'M', 'a', 'n', 'd'},
     /* 53 */ {'M', 'a', 'n', 'i'},
-    /* 54 */ {'M', 'e', 'r', 'c'},
-    /* 55 */ {'M', 'l', 'y', 'm'},
-    /* 56 */ {'M', 'o', 'n', 'g'},
-    /* 57 */ {'M', 'r', 'o', 'o'},
-    /* 58 */ {'M', 'y', 'm', 'r'},
-    /* 59 */ {'N', 'a', 'r', 'b'},
-    /* 60 */ {'N', 'k', 'o', 'o'},
-    /* 61 */ {'N', 's', 'h', 'u'},
-    /* 62 */ {'O', 'g', 'a', 'm'},
-    /* 63 */ {'O', 'l', 'c', 'k'},
-    /* 64 */ {'O', 'r', 'k', 'h'},
-    /* 65 */ {'O', 'r', 'y', 'a'},
-    /* 66 */ {'O', 's', 'g', 'e'},
-    /* 67 */ {'P', 'a', 'u', 'c'},
-    /* 68 */ {'P', 'h', 'l', 'i'},
-    /* 69 */ {'P', 'h', 'n', 'x'},
-    /* 70 */ {'P', 'l', 'r', 'd'},
-    /* 71 */ {'P', 'r', 't', 'i'},
-    /* 72 */ {'R', 'u', 'n', 'r'},
-    /* 73 */ {'S', 'a', 'm', 'r'},
-    /* 74 */ {'S', 'a', 'r', 'b'},
-    /* 75 */ {'S', 'a', 'u', 'r'},
-    /* 76 */ {'S', 'g', 'n', 'w'},
-    /* 77 */ {'S', 'i', 'n', 'h'},
-    /* 78 */ {'S', 'o', 'g', 'd'},
-    /* 79 */ {'S', 'o', 'r', 'a'},
-    /* 80 */ {'S', 'o', 'y', 'o'},
-    /* 81 */ {'S', 'y', 'r', 'c'},
-    /* 82 */ {'T', 'a', 'l', 'e'},
-    /* 83 */ {'T', 'a', 'l', 'u'},
-    /* 84 */ {'T', 'a', 'm', 'l'},
-    /* 85 */ {'T', 'a', 'n', 'g'},
-    /* 86 */ {'T', 'a', 'v', 't'},
-    /* 87 */ {'T', 'e', 'l', 'u'},
-    /* 88 */ {'T', 'f', 'n', 'g'},
-    /* 89 */ {'T', 'h', 'a', 'a'},
-    /* 90 */ {'T', 'h', 'a', 'i'},
-    /* 91 */ {'T', 'i', 'b', 't'},
-    /* 92 */ {'U', 'g', 'a', 'r'},
-    /* 93 */ {'V', 'a', 'i', 'i'},
-    /* 94 */ {'W', 'c', 'h', 'o'},
-    /* 95 */ {'X', 'p', 'e', 'o'},
-    /* 96 */ {'X', 's', 'u', 'x'},
-    /* 97 */ {'Y', 'i', 'i', 'i'},
-    /* 98 */ {'~', '~', '~', 'A'},
-    /* 99 */ {'~', '~', '~', 'B'},
+    /* 54 */ {'M', 'e', 'd', 'f'},
+    /* 55 */ {'M', 'e', 'r', 'c'},
+    /* 56 */ {'M', 'l', 'y', 'm'},
+    /* 57 */ {'M', 'o', 'n', 'g'},
+    /* 58 */ {'M', 'r', 'o', 'o'},
+    /* 59 */ {'M', 'y', 'm', 'r'},
+    /* 60 */ {'N', 'a', 'r', 'b'},
+    /* 61 */ {'N', 'k', 'o', 'o'},
+    /* 62 */ {'N', 's', 'h', 'u'},
+    /* 63 */ {'O', 'g', 'a', 'm'},
+    /* 64 */ {'O', 'l', 'c', 'k'},
+    /* 65 */ {'O', 'r', 'k', 'h'},
+    /* 66 */ {'O', 'r', 'y', 'a'},
+    /* 67 */ {'O', 's', 'g', 'e'},
+    /* 68 */ {'P', 'a', 'u', 'c'},
+    /* 69 */ {'P', 'h', 'l', 'i'},
+    /* 70 */ {'P', 'h', 'n', 'x'},
+    /* 71 */ {'P', 'l', 'r', 'd'},
+    /* 72 */ {'P', 'r', 't', 'i'},
+    /* 73 */ {'R', 'u', 'n', 'r'},
+    /* 74 */ {'S', 'a', 'm', 'r'},
+    /* 75 */ {'S', 'a', 'r', 'b'},
+    /* 76 */ {'S', 'a', 'u', 'r'},
+    /* 77 */ {'S', 'g', 'n', 'w'},
+    /* 78 */ {'S', 'i', 'n', 'h'},
+    /* 79 */ {'S', 'o', 'g', 'd'},
+    /* 80 */ {'S', 'o', 'r', 'a'},
+    /* 81 */ {'S', 'o', 'y', 'o'},
+    /* 82 */ {'S', 'y', 'r', 'c'},
+    /* 83 */ {'T', 'a', 'l', 'e'},
+    /* 84 */ {'T', 'a', 'l', 'u'},
+    /* 85 */ {'T', 'a', 'm', 'l'},
+    /* 86 */ {'T', 'a', 'n', 'g'},
+    /* 87 */ {'T', 'a', 'v', 't'},
+    /* 88 */ {'T', 'e', 'l', 'u'},
+    /* 89 */ {'T', 'f', 'n', 'g'},
+    /* 90 */ {'T', 'h', 'a', 'a'},
+    /* 91 */ {'T', 'h', 'a', 'i'},
+    /* 92 */ {'T', 'i', 'b', 't'},
+    /* 93 */ {'U', 'g', 'a', 'r'},
+    /* 94 */ {'V', 'a', 'i', 'i'},
+    /* 95 */ {'W', 'c', 'h', 'o'},
+    /* 96 */ {'X', 'p', 'e', 'o'},
+    /* 97 */ {'X', 's', 'u', 'x'},
+    /* 98 */ {'Y', 'i', 'i', 'i'},
+    /* 99 */ {'~', '~', '~', 'A'},
+    /* 100 */ {'~', '~', '~', 'B'},
 };
 
 
@@ -109,9 +110,9 @@
     {0xA0000000u, 46u}, // aai -> Latn
     {0xA8000000u, 46u}, // aak -> Latn
     {0xD0000000u, 46u}, // aau -> Latn
-    {0x61620000u, 17u}, // ab -> Cyrl
+    {0x61620000u, 18u}, // ab -> Cyrl
     {0xA0200000u, 46u}, // abi -> Latn
-    {0xC0200000u, 17u}, // abq -> Cyrl
+    {0xC0200000u, 18u}, // abq -> Cyrl
     {0xC4200000u, 46u}, // abr -> Latn
     {0xCC200000u, 46u}, // abt -> Latn
     {0xE0200000u, 46u}, // aby -> Latn
@@ -121,11 +122,11 @@
     {0x80600000u, 46u}, // ada -> Latn
     {0x90600000u, 46u}, // ade -> Latn
     {0xA4600000u, 46u}, // adj -> Latn
-    {0xBC600000u, 91u}, // adp -> Tibt
-    {0xE0600000u, 17u}, // ady -> Cyrl
+    {0xBC600000u, 92u}, // adp -> Tibt
+    {0xE0600000u, 18u}, // ady -> Cyrl
     {0xE4600000u, 46u}, // adz -> Latn
-    {0x61650000u,  4u}, // ae -> Avst
-    {0x84800000u,  1u}, // aeb -> Arab
+    {0x61650000u,  5u}, // ae -> Avst
+    {0x84800000u,  2u}, // aeb -> Arab
     {0xE0800000u, 46u}, // aey -> Latn
     {0x61660000u, 46u}, // af -> Latn
     {0x88C00000u, 46u}, // agc -> Latn
@@ -136,15 +137,15 @@
     {0xC0C00000u, 46u}, // agq -> Latn
     {0x80E00000u, 46u}, // aha -> Latn
     {0xACE00000u, 46u}, // ahl -> Latn
-    {0xB8E00000u,  0u}, // aho -> Ahom
+    {0xB8E00000u,  1u}, // aho -> Ahom
     {0x99200000u, 46u}, // ajg -> Latn
     {0x616B0000u, 46u}, // ak -> Latn
-    {0xA9400000u, 96u}, // akk -> Xsux
+    {0xA9400000u, 97u}, // akk -> Xsux
     {0x81600000u, 46u}, // ala -> Latn
     {0xA1600000u, 46u}, // ali -> Latn
     {0xB5600000u, 46u}, // aln -> Latn
-    {0xCD600000u, 17u}, // alt -> Cyrl
-    {0x616D0000u, 20u}, // am -> Ethi
+    {0xCD600000u, 18u}, // alt -> Cyrl
+    {0x616D0000u, 21u}, // am -> Ethi
     {0xB1800000u, 46u}, // amm -> Latn
     {0xB5800000u, 46u}, // amn -> Latn
     {0xB9800000u, 46u}, // amo -> Latn
@@ -157,25 +158,25 @@
     {0xA5C00000u, 46u}, // aoj -> Latn
     {0xB1C00000u, 46u}, // aom -> Latn
     {0xE5C00000u, 46u}, // aoz -> Latn
-    {0x89E00000u,  1u}, // apc -> Arab
-    {0x8DE00000u,  1u}, // apd -> Arab
+    {0x89E00000u,  2u}, // apc -> Arab
+    {0x8DE00000u,  2u}, // apd -> Arab
     {0x91E00000u, 46u}, // ape -> Latn
     {0xC5E00000u, 46u}, // apr -> Latn
     {0xC9E00000u, 46u}, // aps -> Latn
     {0xE5E00000u, 46u}, // apz -> Latn
-    {0x61720000u,  1u}, // ar -> Arab
-    {0x61725842u, 99u}, // ar-XB -> ~~~B
-    {0x8A200000u,  2u}, // arc -> Armi
+    {0x61720000u,  2u}, // ar -> Arab
+    {0x61725842u, 100u}, // ar-XB -> ~~~B
+    {0x8A200000u,  3u}, // arc -> Armi
     {0x9E200000u, 46u}, // arh -> Latn
     {0xB6200000u, 46u}, // arn -> Latn
     {0xBA200000u, 46u}, // aro -> Latn
-    {0xC2200000u,  1u}, // arq -> Arab
-    {0xCA200000u,  1u}, // ars -> Arab
-    {0xE2200000u,  1u}, // ary -> Arab
-    {0xE6200000u,  1u}, // arz -> Arab
-    {0x61730000u,  7u}, // as -> Beng
+    {0xC2200000u,  2u}, // arq -> Arab
+    {0xCA200000u,  2u}, // ars -> Arab
+    {0xE2200000u,  2u}, // ary -> Arab
+    {0xE6200000u,  2u}, // arz -> Arab
+    {0x61730000u,  8u}, // as -> Beng
     {0x82400000u, 46u}, // asa -> Latn
-    {0x92400000u, 76u}, // ase -> Sgnw
+    {0x92400000u, 77u}, // ase -> Sgnw
     {0x9A400000u, 46u}, // asg -> Latn
     {0xBA400000u, 46u}, // aso -> Latn
     {0xCE400000u, 46u}, // ast -> Latn
@@ -183,29 +184,29 @@
     {0x9A600000u, 46u}, // atg -> Latn
     {0xA6600000u, 46u}, // atj -> Latn
     {0xE2800000u, 46u}, // auy -> Latn
-    {0x61760000u, 17u}, // av -> Cyrl
-    {0xAEA00000u,  1u}, // avl -> Arab
+    {0x61760000u, 18u}, // av -> Cyrl
+    {0xAEA00000u,  2u}, // avl -> Arab
     {0xB6A00000u, 46u}, // avn -> Latn
     {0xCEA00000u, 46u}, // avt -> Latn
     {0xD2A00000u, 46u}, // avu -> Latn
-    {0x82C00000u, 18u}, // awa -> Deva
+    {0x82C00000u, 19u}, // awa -> Deva
     {0x86C00000u, 46u}, // awb -> Latn
     {0xBAC00000u, 46u}, // awo -> Latn
     {0xDEC00000u, 46u}, // awx -> Latn
     {0x61790000u, 46u}, // ay -> Latn
     {0x87000000u, 46u}, // ayb -> Latn
     {0x617A0000u, 46u}, // az -> Latn
-    {0x617A4951u,  1u}, // az-IQ -> Arab
-    {0x617A4952u,  1u}, // az-IR -> Arab
-    {0x617A5255u, 17u}, // az-RU -> Cyrl
-    {0x62610000u, 17u}, // ba -> Cyrl
-    {0xAC010000u,  1u}, // bal -> Arab
+    {0x617A4951u,  2u}, // az-IQ -> Arab
+    {0x617A4952u,  2u}, // az-IR -> Arab
+    {0x617A5255u, 18u}, // az-RU -> Cyrl
+    {0x62610000u, 18u}, // ba -> Cyrl
+    {0xAC010000u,  2u}, // bal -> Arab
     {0xB4010000u, 46u}, // ban -> Latn
-    {0xBC010000u, 18u}, // bap -> Deva
+    {0xBC010000u, 19u}, // bap -> Deva
     {0xC4010000u, 46u}, // bar -> Latn
     {0xC8010000u, 46u}, // bas -> Latn
     {0xD4010000u, 46u}, // bav -> Latn
-    {0xDC010000u,  5u}, // bax -> Bamu
+    {0xDC010000u,  6u}, // bax -> Bamu
     {0x80210000u, 46u}, // bba -> Latn
     {0x84210000u, 46u}, // bbb -> Latn
     {0x88210000u, 46u}, // bbc -> Latn
@@ -219,31 +220,31 @@
     {0xB0410000u, 46u}, // bcm -> Latn
     {0xB4410000u, 46u}, // bcn -> Latn
     {0xB8410000u, 46u}, // bco -> Latn
-    {0xC0410000u, 20u}, // bcq -> Ethi
+    {0xC0410000u, 21u}, // bcq -> Ethi
     {0xD0410000u, 46u}, // bcu -> Latn
     {0x8C610000u, 46u}, // bdd -> Latn
-    {0x62650000u, 17u}, // be -> Cyrl
+    {0x62650000u, 18u}, // be -> Cyrl
     {0x94810000u, 46u}, // bef -> Latn
     {0x9C810000u, 46u}, // beh -> Latn
-    {0xA4810000u,  1u}, // bej -> Arab
+    {0xA4810000u,  2u}, // bej -> Arab
     {0xB0810000u, 46u}, // bem -> Latn
     {0xCC810000u, 46u}, // bet -> Latn
     {0xD8810000u, 46u}, // bew -> Latn
     {0xDC810000u, 46u}, // bex -> Latn
     {0xE4810000u, 46u}, // bez -> Latn
     {0x8CA10000u, 46u}, // bfd -> Latn
-    {0xC0A10000u, 84u}, // bfq -> Taml
-    {0xCCA10000u,  1u}, // bft -> Arab
-    {0xE0A10000u, 18u}, // bfy -> Deva
-    {0x62670000u, 17u}, // bg -> Cyrl
-    {0x88C10000u, 18u}, // bgc -> Deva
-    {0xB4C10000u,  1u}, // bgn -> Arab
-    {0xDCC10000u, 25u}, // bgx -> Grek
-    {0x84E10000u, 18u}, // bhb -> Deva
+    {0xC0A10000u, 85u}, // bfq -> Taml
+    {0xCCA10000u,  2u}, // bft -> Arab
+    {0xE0A10000u, 19u}, // bfy -> Deva
+    {0x62670000u, 18u}, // bg -> Cyrl
+    {0x88C10000u, 19u}, // bgc -> Deva
+    {0xB4C10000u,  2u}, // bgn -> Arab
+    {0xDCC10000u, 26u}, // bgx -> Grek
+    {0x84E10000u, 19u}, // bhb -> Deva
     {0x98E10000u, 46u}, // bhg -> Latn
-    {0xA0E10000u, 18u}, // bhi -> Deva
+    {0xA0E10000u, 19u}, // bhi -> Deva
     {0xACE10000u, 46u}, // bhl -> Latn
-    {0xB8E10000u, 18u}, // bho -> Deva
+    {0xB8E10000u, 19u}, // bho -> Deva
     {0xE0E10000u, 46u}, // bhy -> Latn
     {0x62690000u, 46u}, // bi -> Latn
     {0x85010000u, 46u}, // bib -> Latn
@@ -254,8 +255,8 @@
     {0xB9010000u, 46u}, // bio -> Latn
     {0xC1010000u, 46u}, // biq -> Latn
     {0x9D210000u, 46u}, // bjh -> Latn
-    {0xA1210000u, 20u}, // bji -> Ethi
-    {0xA5210000u, 18u}, // bjj -> Deva
+    {0xA1210000u, 21u}, // bji -> Ethi
+    {0xA5210000u, 19u}, // bjj -> Deva
     {0xB5210000u, 46u}, // bjn -> Latn
     {0xB9210000u, 46u}, // bjo -> Latn
     {0xC5210000u, 46u}, // bjr -> Latn
@@ -266,39 +267,39 @@
     {0xC1410000u, 46u}, // bkq -> Latn
     {0xD1410000u, 46u}, // bku -> Latn
     {0xD5410000u, 46u}, // bkv -> Latn
-    {0xCD610000u, 86u}, // blt -> Tavt
+    {0xCD610000u, 87u}, // blt -> Tavt
     {0x626D0000u, 46u}, // bm -> Latn
     {0x9D810000u, 46u}, // bmh -> Latn
     {0xA9810000u, 46u}, // bmk -> Latn
     {0xC1810000u, 46u}, // bmq -> Latn
     {0xD1810000u, 46u}, // bmu -> Latn
-    {0x626E0000u,  7u}, // bn -> Beng
+    {0x626E0000u,  8u}, // bn -> Beng
     {0x99A10000u, 46u}, // bng -> Latn
     {0xB1A10000u, 46u}, // bnm -> Latn
     {0xBDA10000u, 46u}, // bnp -> Latn
-    {0x626F0000u, 91u}, // bo -> Tibt
+    {0x626F0000u, 92u}, // bo -> Tibt
     {0xA5C10000u, 46u}, // boj -> Latn
     {0xB1C10000u, 46u}, // bom -> Latn
     {0xB5C10000u, 46u}, // bon -> Latn
-    {0xE1E10000u,  7u}, // bpy -> Beng
+    {0xE1E10000u,  8u}, // bpy -> Beng
     {0x8A010000u, 46u}, // bqc -> Latn
-    {0xA2010000u,  1u}, // bqi -> Arab
+    {0xA2010000u,  2u}, // bqi -> Arab
     {0xBE010000u, 46u}, // bqp -> Latn
     {0xD6010000u, 46u}, // bqv -> Latn
     {0x62720000u, 46u}, // br -> Latn
-    {0x82210000u, 18u}, // bra -> Deva
-    {0x9E210000u,  1u}, // brh -> Arab
-    {0xDE210000u, 18u}, // brx -> Deva
+    {0x82210000u, 19u}, // bra -> Deva
+    {0x9E210000u,  2u}, // brh -> Arab
+    {0xDE210000u, 19u}, // brx -> Deva
     {0xE6210000u, 46u}, // brz -> Latn
     {0x62730000u, 46u}, // bs -> Latn
     {0xA6410000u, 46u}, // bsj -> Latn
-    {0xC2410000u,  6u}, // bsq -> Bass
+    {0xC2410000u,  7u}, // bsq -> Bass
     {0xCA410000u, 46u}, // bss -> Latn
-    {0xCE410000u, 20u}, // bst -> Ethi
+    {0xCE410000u, 21u}, // bst -> Ethi
     {0xBA610000u, 46u}, // bto -> Latn
     {0xCE610000u, 46u}, // btt -> Latn
-    {0xD6610000u, 18u}, // btv -> Deva
-    {0x82810000u, 17u}, // bua -> Cyrl
+    {0xD6610000u, 19u}, // btv -> Deva
+    {0x82810000u, 18u}, // bua -> Cyrl
     {0x8A810000u, 46u}, // buc -> Latn
     {0x8E810000u, 46u}, // bud -> Latn
     {0x9A810000u, 46u}, // bug -> Latn
@@ -312,7 +313,7 @@
     {0xC6C10000u, 46u}, // bwr -> Latn
     {0x9EE10000u, 46u}, // bxh -> Latn
     {0x93010000u, 46u}, // bye -> Latn
-    {0xB7010000u, 20u}, // byn -> Ethi
+    {0xB7010000u, 21u}, // byn -> Ethi
     {0xC7010000u, 46u}, // byr -> Latn
     {0xCB010000u, 46u}, // bys -> Latn
     {0xD7010000u, 46u}, // byv -> Latn
@@ -327,44 +328,44 @@
     {0xB4020000u, 46u}, // can -> Latn
     {0xA4220000u, 46u}, // cbj -> Latn
     {0x9C420000u, 46u}, // cch -> Latn
-    {0xBC420000u,  9u}, // ccp -> Cakm
-    {0x63650000u, 17u}, // ce -> Cyrl
+    {0xBC420000u, 10u}, // ccp -> Cakm
+    {0x63650000u, 18u}, // ce -> Cyrl
     {0x84820000u, 46u}, // ceb -> Latn
     {0x80A20000u, 46u}, // cfa -> Latn
     {0x98C20000u, 46u}, // cgg -> Latn
     {0x63680000u, 46u}, // ch -> Latn
     {0xA8E20000u, 46u}, // chk -> Latn
-    {0xB0E20000u, 17u}, // chm -> Cyrl
+    {0xB0E20000u, 18u}, // chm -> Cyrl
     {0xB8E20000u, 46u}, // cho -> Latn
     {0xBCE20000u, 46u}, // chp -> Latn
-    {0xC4E20000u, 13u}, // chr -> Cher
+    {0xC4E20000u, 14u}, // chr -> Cher
     {0x89020000u, 46u}, // cic -> Latn
-    {0x81220000u,  1u}, // cja -> Arab
-    {0xB1220000u, 12u}, // cjm -> Cham
+    {0x81220000u,  2u}, // cja -> Arab
+    {0xB1220000u, 13u}, // cjm -> Cham
     {0xD5220000u, 46u}, // cjv -> Latn
-    {0x85420000u,  1u}, // ckb -> Arab
+    {0x85420000u,  2u}, // ckb -> Arab
     {0xAD420000u, 46u}, // ckl -> Latn
     {0xB9420000u, 46u}, // cko -> Latn
     {0xE1420000u, 46u}, // cky -> Latn
     {0x81620000u, 46u}, // cla -> Latn
     {0x91820000u, 46u}, // cme -> Latn
-    {0x99820000u, 80u}, // cmg -> Soyo
+    {0x99820000u, 81u}, // cmg -> Soyo
     {0x636F0000u, 46u}, // co -> Latn
-    {0xBDC20000u, 15u}, // cop -> Copt
+    {0xBDC20000u, 16u}, // cop -> Copt
     {0xC9E20000u, 46u}, // cps -> Latn
-    {0x63720000u, 10u}, // cr -> Cans
-    {0x9E220000u, 17u}, // crh -> Cyrl
-    {0xA6220000u, 10u}, // crj -> Cans
-    {0xAA220000u, 10u}, // crk -> Cans
-    {0xAE220000u, 10u}, // crl -> Cans
-    {0xB2220000u, 10u}, // crm -> Cans
+    {0x63720000u, 11u}, // cr -> Cans
+    {0x9E220000u, 18u}, // crh -> Cyrl
+    {0xA6220000u, 11u}, // crj -> Cans
+    {0xAA220000u, 11u}, // crk -> Cans
+    {0xAE220000u, 11u}, // crl -> Cans
+    {0xB2220000u, 11u}, // crm -> Cans
     {0xCA220000u, 46u}, // crs -> Latn
     {0x63730000u, 46u}, // cs -> Latn
     {0x86420000u, 46u}, // csb -> Latn
-    {0xDA420000u, 10u}, // csw -> Cans
-    {0x8E620000u, 67u}, // ctd -> Pauc
-    {0x63750000u, 17u}, // cu -> Cyrl
-    {0x63760000u, 17u}, // cv -> Cyrl
+    {0xDA420000u, 11u}, // csw -> Cans
+    {0x8E620000u, 68u}, // ctd -> Pauc
+    {0x63750000u, 18u}, // cu -> Cyrl
+    {0x63760000u, 18u}, // cv -> Cyrl
     {0x63790000u, 46u}, // cy -> Latn
     {0x64610000u, 46u}, // da -> Latn
     {0x8C030000u, 46u}, // dad -> Latn
@@ -372,11 +373,11 @@
     {0x98030000u, 46u}, // dag -> Latn
     {0x9C030000u, 46u}, // dah -> Latn
     {0xA8030000u, 46u}, // dak -> Latn
-    {0xC4030000u, 17u}, // dar -> Cyrl
+    {0xC4030000u, 18u}, // dar -> Cyrl
     {0xD4030000u, 46u}, // dav -> Latn
     {0x8C230000u, 46u}, // dbd -> Latn
     {0xC0230000u, 46u}, // dbq -> Latn
-    {0x88430000u,  1u}, // dcc -> Arab
+    {0x88430000u,  2u}, // dcc -> Arab
     {0xB4630000u, 46u}, // ddn -> Latn
     {0x64650000u, 46u}, // de -> Latn
     {0x8C830000u, 46u}, // ded -> Latn
@@ -384,53 +385,54 @@
     {0x80C30000u, 46u}, // dga -> Latn
     {0x9CC30000u, 46u}, // dgh -> Latn
     {0xA0C30000u, 46u}, // dgi -> Latn
-    {0xACC30000u,  1u}, // dgl -> Arab
+    {0xACC30000u,  2u}, // dgl -> Arab
     {0xC4C30000u, 46u}, // dgr -> Latn
     {0xE4C30000u, 46u}, // dgz -> Latn
     {0x81030000u, 46u}, // dia -> Latn
     {0x91230000u, 46u}, // dje -> Latn
+    {0x95830000u, 54u}, // dmf -> Medf
     {0xA5A30000u, 46u}, // dnj -> Latn
     {0x85C30000u, 46u}, // dob -> Latn
-    {0xA1C30000u, 18u}, // doi -> Deva
+    {0xA1C30000u, 19u}, // doi -> Deva
     {0xBDC30000u, 46u}, // dop -> Latn
     {0xD9C30000u, 46u}, // dow -> Latn
-    {0x9E230000u, 56u}, // drh -> Mong
+    {0x9E230000u, 57u}, // drh -> Mong
     {0xA2230000u, 46u}, // dri -> Latn
-    {0xCA230000u, 20u}, // drs -> Ethi
+    {0xCA230000u, 21u}, // drs -> Ethi
     {0x86430000u, 46u}, // dsb -> Latn
     {0xB2630000u, 46u}, // dtm -> Latn
     {0xBE630000u, 46u}, // dtp -> Latn
     {0xCA630000u, 46u}, // dts -> Latn
-    {0xE2630000u, 18u}, // dty -> Deva
+    {0xE2630000u, 19u}, // dty -> Deva
     {0x82830000u, 46u}, // dua -> Latn
     {0x8A830000u, 46u}, // duc -> Latn
     {0x8E830000u, 46u}, // dud -> Latn
     {0x9A830000u, 46u}, // dug -> Latn
-    {0x64760000u, 89u}, // dv -> Thaa
+    {0x64760000u, 90u}, // dv -> Thaa
     {0x82A30000u, 46u}, // dva -> Latn
     {0xDAC30000u, 46u}, // dww -> Latn
     {0xBB030000u, 46u}, // dyo -> Latn
     {0xD3030000u, 46u}, // dyu -> Latn
-    {0x647A0000u, 91u}, // dz -> Tibt
+    {0x647A0000u, 92u}, // dz -> Tibt
     {0x9B230000u, 46u}, // dzg -> Latn
     {0xD0240000u, 46u}, // ebu -> Latn
     {0x65650000u, 46u}, // ee -> Latn
     {0xA0A40000u, 46u}, // efi -> Latn
     {0xACC40000u, 46u}, // egl -> Latn
-    {0xE0C40000u, 19u}, // egy -> Egyp
+    {0xE0C40000u, 20u}, // egy -> Egyp
     {0x81440000u, 46u}, // eka -> Latn
     {0xE1440000u, 37u}, // eky -> Kali
-    {0x656C0000u, 25u}, // el -> Grek
+    {0x656C0000u, 26u}, // el -> Grek
     {0x81840000u, 46u}, // ema -> Latn
     {0xA1840000u, 46u}, // emi -> Latn
     {0x656E0000u, 46u}, // en -> Latn
-    {0x656E5841u, 98u}, // en-XA -> ~~~A
+    {0x656E5841u, 99u}, // en-XA -> ~~~A
     {0xB5A40000u, 46u}, // enn -> Latn
     {0xC1A40000u, 46u}, // enq -> Latn
     {0x656F0000u, 46u}, // eo -> Latn
     {0xA2240000u, 46u}, // eri -> Latn
     {0x65730000u, 46u}, // es -> Latn
-    {0x9A440000u, 23u}, // esg -> Gonm
+    {0x9A440000u, 24u}, // esg -> Gonm
     {0xD2440000u, 46u}, // esu -> Latn
     {0x65740000u, 46u}, // et -> Latn
     {0xC6640000u, 46u}, // etr -> Latn
@@ -441,7 +443,7 @@
     {0xBAC40000u, 46u}, // ewo -> Latn
     {0xCEE40000u, 46u}, // ext -> Latn
     {0x83240000u, 46u}, // eza -> Latn
-    {0x66610000u,  1u}, // fa -> Arab
+    {0x66610000u,  2u}, // fa -> Arab
     {0x80050000u, 46u}, // faa -> Latn
     {0x84050000u, 46u}, // fab -> Latn
     {0x98050000u, 46u}, // fag -> Latn
@@ -451,7 +453,7 @@
     {0xA0A50000u, 46u}, // ffi -> Latn
     {0xB0A50000u, 46u}, // ffm -> Latn
     {0x66690000u, 46u}, // fi -> Latn
-    {0x81050000u,  1u}, // fia -> Arab
+    {0x81050000u,  2u}, // fia -> Arab
     {0xAD050000u, 46u}, // fil -> Latn
     {0xCD050000u, 46u}, // fit -> Latn
     {0x666A0000u, 46u}, // fj -> Latn
@@ -468,7 +470,7 @@
     {0xBE250000u, 46u}, // frp -> Latn
     {0xC6250000u, 46u}, // frr -> Latn
     {0xCA250000u, 46u}, // frs -> Latn
-    {0x86850000u,  1u}, // fub -> Arab
+    {0x86850000u,  2u}, // fub -> Arab
     {0x8E850000u, 46u}, // fud -> Latn
     {0x92850000u, 46u}, // fue -> Latn
     {0x96850000u, 46u}, // fuf -> Latn
@@ -486,14 +488,14 @@
     {0x9C060000u, 46u}, // gah -> Latn
     {0xA4060000u, 46u}, // gaj -> Latn
     {0xB0060000u, 46u}, // gam -> Latn
-    {0xB4060000u, 28u}, // gan -> Hans
+    {0xB4060000u, 29u}, // gan -> Hans
     {0xD8060000u, 46u}, // gaw -> Latn
     {0xE0060000u, 46u}, // gay -> Latn
     {0x80260000u, 46u}, // gba -> Latn
     {0x94260000u, 46u}, // gbf -> Latn
-    {0xB0260000u, 18u}, // gbm -> Deva
+    {0xB0260000u, 19u}, // gbm -> Deva
     {0xE0260000u, 46u}, // gby -> Latn
-    {0xE4260000u,  1u}, // gbz -> Arab
+    {0xE4260000u,  2u}, // gbz -> Arab
     {0xC4460000u, 46u}, // gcr -> Latn
     {0x67640000u, 46u}, // gd -> Latn
     {0x90660000u, 46u}, // gde -> Latn
@@ -502,38 +504,38 @@
     {0x84860000u, 46u}, // geb -> Latn
     {0xA4860000u, 46u}, // gej -> Latn
     {0xAC860000u, 46u}, // gel -> Latn
-    {0xE4860000u, 20u}, // gez -> Ethi
+    {0xE4860000u, 21u}, // gez -> Ethi
     {0xA8A60000u, 46u}, // gfk -> Latn
-    {0xB4C60000u, 18u}, // ggn -> Deva
+    {0xB4C60000u, 19u}, // ggn -> Deva
     {0xC8E60000u, 46u}, // ghs -> Latn
     {0xAD060000u, 46u}, // gil -> Latn
     {0xB1060000u, 46u}, // gim -> Latn
-    {0xA9260000u,  1u}, // gjk -> Arab
+    {0xA9260000u,  2u}, // gjk -> Arab
     {0xB5260000u, 46u}, // gjn -> Latn
-    {0xD1260000u,  1u}, // gju -> Arab
+    {0xD1260000u,  2u}, // gju -> Arab
     {0xB5460000u, 46u}, // gkn -> Latn
     {0xBD460000u, 46u}, // gkp -> Latn
     {0x676C0000u, 46u}, // gl -> Latn
-    {0xA9660000u,  1u}, // glk -> Arab
+    {0xA9660000u,  2u}, // glk -> Arab
     {0xB1860000u, 46u}, // gmm -> Latn
-    {0xD5860000u, 20u}, // gmv -> Ethi
+    {0xD5860000u, 21u}, // gmv -> Ethi
     {0x676E0000u, 46u}, // gn -> Latn
     {0x8DA60000u, 46u}, // gnd -> Latn
     {0x99A60000u, 46u}, // gng -> Latn
     {0x8DC60000u, 46u}, // god -> Latn
-    {0x95C60000u, 20u}, // gof -> Ethi
+    {0x95C60000u, 21u}, // gof -> Ethi
     {0xA1C60000u, 46u}, // goi -> Latn
-    {0xB1C60000u, 18u}, // gom -> Deva
-    {0xB5C60000u, 87u}, // gon -> Telu
+    {0xB1C60000u, 19u}, // gom -> Deva
+    {0xB5C60000u, 88u}, // gon -> Telu
     {0xC5C60000u, 46u}, // gor -> Latn
     {0xC9C60000u, 46u}, // gos -> Latn
-    {0xCDC60000u, 24u}, // got -> Goth
+    {0xCDC60000u, 25u}, // got -> Goth
     {0x86260000u, 46u}, // grb -> Latn
-    {0x8A260000u, 16u}, // grc -> Cprt
-    {0xCE260000u,  7u}, // grt -> Beng
+    {0x8A260000u, 17u}, // grc -> Cprt
+    {0xCE260000u,  8u}, // grt -> Beng
     {0xDA260000u, 46u}, // grw -> Latn
     {0xDA460000u, 46u}, // gsw -> Latn
-    {0x67750000u, 26u}, // gu -> Gujr
+    {0x67750000u, 27u}, // gu -> Gujr
     {0x86860000u, 46u}, // gub -> Latn
     {0x8A860000u, 46u}, // guc -> Latn
     {0x8E860000u, 46u}, // gud -> Latn
@@ -543,25 +545,25 @@
     {0xE6860000u, 46u}, // guz -> Latn
     {0x67760000u, 46u}, // gv -> Latn
     {0x96A60000u, 46u}, // gvf -> Latn
-    {0xC6A60000u, 18u}, // gvr -> Deva
+    {0xC6A60000u, 19u}, // gvr -> Deva
     {0xCAA60000u, 46u}, // gvs -> Latn
-    {0x8AC60000u,  1u}, // gwc -> Arab
+    {0x8AC60000u,  2u}, // gwc -> Arab
     {0xA2C60000u, 46u}, // gwi -> Latn
-    {0xCEC60000u,  1u}, // gwt -> Arab
+    {0xCEC60000u,  2u}, // gwt -> Arab
     {0xA3060000u, 46u}, // gyi -> Latn
     {0x68610000u, 46u}, // ha -> Latn
-    {0x6861434Du,  1u}, // ha-CM -> Arab
-    {0x68615344u,  1u}, // ha-SD -> Arab
+    {0x6861434Du,  2u}, // ha-CM -> Arab
+    {0x68615344u,  2u}, // ha-SD -> Arab
     {0x98070000u, 46u}, // hag -> Latn
-    {0xA8070000u, 28u}, // hak -> Hans
+    {0xA8070000u, 29u}, // hak -> Hans
     {0xB0070000u, 46u}, // ham -> Latn
     {0xD8070000u, 46u}, // haw -> Latn
-    {0xE4070000u,  1u}, // haz -> Arab
+    {0xE4070000u,  2u}, // haz -> Arab
     {0x84270000u, 46u}, // hbb -> Latn
-    {0xE0670000u, 20u}, // hdy -> Ethi
+    {0xE0670000u, 21u}, // hdy -> Ethi
     {0x68650000u, 31u}, // he -> Hebr
     {0xE0E70000u, 46u}, // hhy -> Latn
-    {0x68690000u, 18u}, // hi -> Deva
+    {0x68690000u, 19u}, // hi -> Deva
     {0x81070000u, 46u}, // hia -> Latn
     {0x95070000u, 46u}, // hif -> Latn
     {0x99070000u, 46u}, // hig -> Latn
@@ -569,24 +571,24 @@
     {0xAD070000u, 46u}, // hil -> Latn
     {0x81670000u, 46u}, // hla -> Latn
     {0xD1670000u, 32u}, // hlu -> Hluw
-    {0x8D870000u, 70u}, // hmd -> Plrd
+    {0x8D870000u, 71u}, // hmd -> Plrd
     {0xCD870000u, 46u}, // hmt -> Latn
-    {0x8DA70000u,  1u}, // hnd -> Arab
-    {0x91A70000u, 18u}, // hne -> Deva
+    {0x8DA70000u,  2u}, // hnd -> Arab
+    {0x91A70000u, 19u}, // hne -> Deva
     {0xA5A70000u, 33u}, // hnj -> Hmng
     {0xB5A70000u, 46u}, // hnn -> Latn
-    {0xB9A70000u,  1u}, // hno -> Arab
+    {0xB9A70000u,  2u}, // hno -> Arab
     {0x686F0000u, 46u}, // ho -> Latn
-    {0x89C70000u, 18u}, // hoc -> Deva
-    {0xA5C70000u, 18u}, // hoj -> Deva
+    {0x89C70000u, 19u}, // hoc -> Deva
+    {0xA5C70000u, 19u}, // hoj -> Deva
     {0xCDC70000u, 46u}, // hot -> Latn
     {0x68720000u, 46u}, // hr -> Latn
     {0x86470000u, 46u}, // hsb -> Latn
-    {0xB6470000u, 28u}, // hsn -> Hans
+    {0xB6470000u, 29u}, // hsn -> Hans
     {0x68740000u, 46u}, // ht -> Latn
     {0x68750000u, 46u}, // hu -> Latn
     {0xA2870000u, 46u}, // hui -> Latn
-    {0x68790000u,  3u}, // hy -> Armn
+    {0x68790000u,  4u}, // hy -> Armn
     {0x687A0000u, 46u}, // hz -> Latn
     {0x69610000u, 46u}, // ia -> Latn
     {0xB4080000u, 46u}, // ian -> Latn
@@ -604,7 +606,7 @@
     {0x69670000u, 46u}, // ig -> Latn
     {0x84C80000u, 46u}, // igb -> Latn
     {0x90C80000u, 46u}, // ige -> Latn
-    {0x69690000u, 97u}, // ii -> Yiii
+    {0x69690000u, 98u}, // ii -> Yiii
     {0xA5280000u, 46u}, // ijj -> Latn
     {0x696B0000u, 46u}, // ik -> Latn
     {0xA9480000u, 46u}, // ikk -> Latn
@@ -614,13 +616,13 @@
     {0xB9680000u, 46u}, // ilo -> Latn
     {0xB9880000u, 46u}, // imo -> Latn
     {0x696E0000u, 46u}, // in -> Latn
-    {0x9DA80000u, 17u}, // inh -> Cyrl
+    {0x9DA80000u, 18u}, // inh -> Cyrl
     {0x696F0000u, 46u}, // io -> Latn
     {0xD1C80000u, 46u}, // iou -> Latn
     {0xA2280000u, 46u}, // iri -> Latn
     {0x69730000u, 46u}, // is -> Latn
     {0x69740000u, 46u}, // it -> Latn
-    {0x69750000u, 10u}, // iu -> Cans
+    {0x69750000u, 11u}, // iu -> Cans
     {0x69770000u, 31u}, // iw -> Hebr
     {0xB2C80000u, 46u}, // iwm -> Latn
     {0xCAC80000u, 46u}, // iws -> Latn
@@ -638,13 +640,13 @@
     {0x6A690000u, 31u}, // ji -> Hebr
     {0x85090000u, 46u}, // jib -> Latn
     {0x89890000u, 46u}, // jmc -> Latn
-    {0xAD890000u, 18u}, // jml -> Deva
+    {0xAD890000u, 19u}, // jml -> Deva
     {0x82290000u, 46u}, // jra -> Latn
     {0xCE890000u, 46u}, // jut -> Latn
     {0x6A760000u, 46u}, // jv -> Latn
     {0x6A770000u, 46u}, // jw -> Latn
-    {0x6B610000u, 21u}, // ka -> Geor
-    {0x800A0000u, 17u}, // kaa -> Cyrl
+    {0x6B610000u, 22u}, // ka -> Geor
+    {0x800A0000u, 18u}, // kaa -> Cyrl
     {0x840A0000u, 46u}, // kab -> Latn
     {0x880A0000u, 46u}, // kac -> Latn
     {0x8C0A0000u, 46u}, // kad -> Latn
@@ -652,37 +654,37 @@
     {0xA40A0000u, 46u}, // kaj -> Latn
     {0xB00A0000u, 46u}, // kam -> Latn
     {0xB80A0000u, 46u}, // kao -> Latn
-    {0x8C2A0000u, 17u}, // kbd -> Cyrl
+    {0x8C2A0000u, 18u}, // kbd -> Cyrl
     {0xB02A0000u, 46u}, // kbm -> Latn
     {0xBC2A0000u, 46u}, // kbp -> Latn
     {0xC02A0000u, 46u}, // kbq -> Latn
     {0xDC2A0000u, 46u}, // kbx -> Latn
-    {0xE02A0000u,  1u}, // kby -> Arab
+    {0xE02A0000u,  2u}, // kby -> Arab
     {0x984A0000u, 46u}, // kcg -> Latn
     {0xA84A0000u, 46u}, // kck -> Latn
     {0xAC4A0000u, 46u}, // kcl -> Latn
     {0xCC4A0000u, 46u}, // kct -> Latn
     {0x906A0000u, 46u}, // kde -> Latn
-    {0x9C6A0000u,  1u}, // kdh -> Arab
+    {0x9C6A0000u,  2u}, // kdh -> Arab
     {0xAC6A0000u, 46u}, // kdl -> Latn
-    {0xCC6A0000u, 90u}, // kdt -> Thai
+    {0xCC6A0000u, 91u}, // kdt -> Thai
     {0x808A0000u, 46u}, // kea -> Latn
     {0xB48A0000u, 46u}, // ken -> Latn
     {0xE48A0000u, 46u}, // kez -> Latn
     {0xB8AA0000u, 46u}, // kfo -> Latn
-    {0xC4AA0000u, 18u}, // kfr -> Deva
-    {0xE0AA0000u, 18u}, // kfy -> Deva
+    {0xC4AA0000u, 19u}, // kfr -> Deva
+    {0xE0AA0000u, 19u}, // kfy -> Deva
     {0x6B670000u, 46u}, // kg -> Latn
     {0x90CA0000u, 46u}, // kge -> Latn
     {0x94CA0000u, 46u}, // kgf -> Latn
     {0xBCCA0000u, 46u}, // kgp -> Latn
     {0x80EA0000u, 46u}, // kha -> Latn
-    {0x84EA0000u, 83u}, // khb -> Talu
-    {0xB4EA0000u, 18u}, // khn -> Deva
+    {0x84EA0000u, 84u}, // khb -> Talu
+    {0xB4EA0000u, 19u}, // khn -> Deva
     {0xC0EA0000u, 46u}, // khq -> Latn
     {0xC8EA0000u, 46u}, // khs -> Latn
-    {0xCCEA0000u, 58u}, // kht -> Mymr
-    {0xD8EA0000u,  1u}, // khw -> Arab
+    {0xCCEA0000u, 59u}, // kht -> Mymr
+    {0xD8EA0000u,  2u}, // khw -> Arab
     {0xE4EA0000u, 46u}, // khz -> Latn
     {0x6B690000u, 46u}, // ki -> Latn
     {0xA50A0000u, 46u}, // kij -> Latn
@@ -693,11 +695,11 @@
     {0x992A0000u, 45u}, // kjg -> Laoo
     {0xC92A0000u, 46u}, // kjs -> Latn
     {0xE12A0000u, 46u}, // kjy -> Latn
-    {0x6B6B0000u, 17u}, // kk -> Cyrl
-    {0x6B6B4146u,  1u}, // kk-AF -> Arab
-    {0x6B6B434Eu,  1u}, // kk-CN -> Arab
-    {0x6B6B4952u,  1u}, // kk-IR -> Arab
-    {0x6B6B4D4Eu,  1u}, // kk-MN -> Arab
+    {0x6B6B0000u, 18u}, // kk -> Cyrl
+    {0x6B6B4146u,  2u}, // kk-AF -> Arab
+    {0x6B6B434Eu,  2u}, // kk-CN -> Arab
+    {0x6B6B4952u,  2u}, // kk-IR -> Arab
+    {0x6B6B4D4Eu,  2u}, // kk-MN -> Arab
     {0x894A0000u, 46u}, // kkc -> Latn
     {0xA54A0000u, 46u}, // kkj -> Latn
     {0x6B6C0000u, 46u}, // kl -> Latn
@@ -716,8 +718,8 @@
     {0x95AA0000u, 46u}, // knf -> Latn
     {0xBDAA0000u, 46u}, // knp -> Latn
     {0x6B6F0000u, 43u}, // ko -> Kore
-    {0xA1CA0000u, 17u}, // koi -> Cyrl
-    {0xA9CA0000u, 18u}, // kok -> Deva
+    {0xA1CA0000u, 18u}, // koi -> Cyrl
+    {0xA9CA0000u, 19u}, // kok -> Deva
     {0xADCA0000u, 46u}, // kol -> Latn
     {0xC9CA0000u, 46u}, // kos -> Latn
     {0xE5CA0000u, 46u}, // koz -> Latn
@@ -729,58 +731,58 @@
     {0x860A0000u, 46u}, // kqb -> Latn
     {0x960A0000u, 46u}, // kqf -> Latn
     {0xCA0A0000u, 46u}, // kqs -> Latn
-    {0xE20A0000u, 20u}, // kqy -> Ethi
+    {0xE20A0000u, 21u}, // kqy -> Ethi
     {0x6B720000u, 46u}, // kr -> Latn
-    {0x8A2A0000u, 17u}, // krc -> Cyrl
+    {0x8A2A0000u, 18u}, // krc -> Cyrl
     {0xA22A0000u, 46u}, // kri -> Latn
     {0xA62A0000u, 46u}, // krj -> Latn
     {0xAE2A0000u, 46u}, // krl -> Latn
     {0xCA2A0000u, 46u}, // krs -> Latn
-    {0xD22A0000u, 18u}, // kru -> Deva
-    {0x6B730000u,  1u}, // ks -> Arab
+    {0xD22A0000u, 19u}, // kru -> Deva
+    {0x6B730000u,  2u}, // ks -> Arab
     {0x864A0000u, 46u}, // ksb -> Latn
     {0x8E4A0000u, 46u}, // ksd -> Latn
     {0x964A0000u, 46u}, // ksf -> Latn
     {0x9E4A0000u, 46u}, // ksh -> Latn
     {0xA64A0000u, 46u}, // ksj -> Latn
     {0xC64A0000u, 46u}, // ksr -> Latn
-    {0x866A0000u, 20u}, // ktb -> Ethi
+    {0x866A0000u, 21u}, // ktb -> Ethi
     {0xB26A0000u, 46u}, // ktm -> Latn
     {0xBA6A0000u, 46u}, // kto -> Latn
     {0xC66A0000u, 46u}, // ktr -> Latn
     {0x6B750000u, 46u}, // ku -> Latn
-    {0x6B754952u,  1u}, // ku-IR -> Arab
-    {0x6B754C42u,  1u}, // ku-LB -> Arab
+    {0x6B754952u,  2u}, // ku-IR -> Arab
+    {0x6B754C42u,  2u}, // ku-LB -> Arab
     {0x868A0000u, 46u}, // kub -> Latn
     {0x8E8A0000u, 46u}, // kud -> Latn
     {0x928A0000u, 46u}, // kue -> Latn
     {0xA68A0000u, 46u}, // kuj -> Latn
-    {0xB28A0000u, 17u}, // kum -> Cyrl
+    {0xB28A0000u, 18u}, // kum -> Cyrl
     {0xB68A0000u, 46u}, // kun -> Latn
     {0xBE8A0000u, 46u}, // kup -> Latn
     {0xCA8A0000u, 46u}, // kus -> Latn
-    {0x6B760000u, 17u}, // kv -> Cyrl
+    {0x6B760000u, 18u}, // kv -> Cyrl
     {0x9AAA0000u, 46u}, // kvg -> Latn
     {0xC6AA0000u, 46u}, // kvr -> Latn
-    {0xDEAA0000u,  1u}, // kvx -> Arab
+    {0xDEAA0000u,  2u}, // kvx -> Arab
     {0x6B770000u, 46u}, // kw -> Latn
     {0xA6CA0000u, 46u}, // kwj -> Latn
     {0xBACA0000u, 46u}, // kwo -> Latn
     {0xC2CA0000u, 46u}, // kwq -> Latn
     {0x82EA0000u, 46u}, // kxa -> Latn
-    {0x8AEA0000u, 20u}, // kxc -> Ethi
+    {0x8AEA0000u, 21u}, // kxc -> Ethi
     {0x92EA0000u, 46u}, // kxe -> Latn
-    {0xAEEA0000u, 18u}, // kxl -> Deva
-    {0xB2EA0000u, 90u}, // kxm -> Thai
-    {0xBEEA0000u,  1u}, // kxp -> Arab
+    {0xAEEA0000u, 19u}, // kxl -> Deva
+    {0xB2EA0000u, 91u}, // kxm -> Thai
+    {0xBEEA0000u,  2u}, // kxp -> Arab
     {0xDAEA0000u, 46u}, // kxw -> Latn
     {0xE6EA0000u, 46u}, // kxz -> Latn
-    {0x6B790000u, 17u}, // ky -> Cyrl
-    {0x6B79434Eu,  1u}, // ky-CN -> Arab
+    {0x6B790000u, 18u}, // ky -> Cyrl
+    {0x6B79434Eu,  2u}, // ky-CN -> Arab
     {0x6B795452u, 46u}, // ky-TR -> Latn
     {0x930A0000u, 46u}, // kye -> Latn
     {0xDF0A0000u, 46u}, // kyx -> Latn
-    {0x9F2A0000u,  1u}, // kzh -> Arab
+    {0x9F2A0000u,  2u}, // kzh -> Arab
     {0xA72A0000u, 46u}, // kzj -> Latn
     {0xC72A0000u, 46u}, // kzr -> Latn
     {0xCF2A0000u, 46u}, // kzt -> Latn
@@ -788,15 +790,15 @@
     {0x840B0000u, 48u}, // lab -> Lina
     {0x8C0B0000u, 31u}, // lad -> Hebr
     {0x980B0000u, 46u}, // lag -> Latn
-    {0x9C0B0000u,  1u}, // lah -> Arab
+    {0x9C0B0000u,  2u}, // lah -> Arab
     {0xA40B0000u, 46u}, // laj -> Latn
     {0xC80B0000u, 46u}, // las -> Latn
     {0x6C620000u, 46u}, // lb -> Latn
-    {0x902B0000u, 17u}, // lbe -> Cyrl
+    {0x902B0000u, 18u}, // lbe -> Cyrl
     {0xD02B0000u, 46u}, // lbu -> Latn
     {0xD82B0000u, 46u}, // lbw -> Latn
     {0xB04B0000u, 46u}, // lcm -> Latn
-    {0xBC4B0000u, 90u}, // lcp -> Thai
+    {0xBC4B0000u, 91u}, // lcp -> Thai
     {0x846B0000u, 46u}, // ldb -> Latn
     {0x8C8B0000u, 46u}, // led -> Latn
     {0x908B0000u, 46u}, // lee -> Latn
@@ -804,23 +806,23 @@
     {0xBC8B0000u, 47u}, // lep -> Lepc
     {0xC08B0000u, 46u}, // leq -> Latn
     {0xD08B0000u, 46u}, // leu -> Latn
-    {0xE48B0000u, 17u}, // lez -> Cyrl
+    {0xE48B0000u, 18u}, // lez -> Cyrl
     {0x6C670000u, 46u}, // lg -> Latn
     {0x98CB0000u, 46u}, // lgg -> Latn
     {0x6C690000u, 46u}, // li -> Latn
     {0x810B0000u, 46u}, // lia -> Latn
     {0x8D0B0000u, 46u}, // lid -> Latn
-    {0x950B0000u, 18u}, // lif -> Deva
+    {0x950B0000u, 19u}, // lif -> Deva
     {0x990B0000u, 46u}, // lig -> Latn
     {0x9D0B0000u, 46u}, // lih -> Latn
     {0xA50B0000u, 46u}, // lij -> Latn
     {0xC90B0000u, 49u}, // lis -> Lisu
     {0xBD2B0000u, 46u}, // ljp -> Latn
-    {0xA14B0000u,  1u}, // lki -> Arab
+    {0xA14B0000u,  2u}, // lki -> Arab
     {0xCD4B0000u, 46u}, // lkt -> Latn
     {0x916B0000u, 46u}, // lle -> Latn
     {0xB56B0000u, 46u}, // lln -> Latn
-    {0xB58B0000u, 87u}, // lmn -> Telu
+    {0xB58B0000u, 88u}, // lmn -> Telu
     {0xB98B0000u, 46u}, // lmo -> Latn
     {0xBD8B0000u, 46u}, // lmp -> Latn
     {0x6C6E0000u, 46u}, // ln -> Latn
@@ -833,25 +835,25 @@
     {0xC5CB0000u, 46u}, // lor -> Latn
     {0xC9CB0000u, 46u}, // los -> Latn
     {0xE5CB0000u, 46u}, // loz -> Latn
-    {0x8A2B0000u,  1u}, // lrc -> Arab
+    {0x8A2B0000u,  2u}, // lrc -> Arab
     {0x6C740000u, 46u}, // lt -> Latn
     {0x9A6B0000u, 46u}, // ltg -> Latn
     {0x6C750000u, 46u}, // lu -> Latn
     {0x828B0000u, 46u}, // lua -> Latn
     {0xBA8B0000u, 46u}, // luo -> Latn
     {0xE28B0000u, 46u}, // luy -> Latn
-    {0xE68B0000u,  1u}, // luz -> Arab
+    {0xE68B0000u,  2u}, // luz -> Arab
     {0x6C760000u, 46u}, // lv -> Latn
-    {0xAECB0000u, 90u}, // lwl -> Thai
-    {0x9F2B0000u, 28u}, // lzh -> Hans
+    {0xAECB0000u, 91u}, // lwl -> Thai
+    {0x9F2B0000u, 29u}, // lzh -> Hans
     {0xE72B0000u, 46u}, // lzz -> Latn
     {0x8C0C0000u, 46u}, // mad -> Latn
     {0x940C0000u, 46u}, // maf -> Latn
-    {0x980C0000u, 18u}, // mag -> Deva
-    {0xA00C0000u, 18u}, // mai -> Deva
+    {0x980C0000u, 19u}, // mag -> Deva
+    {0xA00C0000u, 19u}, // mai -> Deva
     {0xA80C0000u, 46u}, // mak -> Latn
     {0xB40C0000u, 46u}, // man -> Latn
-    {0xB40C474Eu, 60u}, // man-GN -> Nkoo
+    {0xB40C474Eu, 61u}, // man-GN -> Nkoo
     {0xC80C0000u, 46u}, // mas -> Latn
     {0xD80C0000u, 46u}, // maw -> Latn
     {0xE40C0000u, 46u}, // maz -> Latn
@@ -866,12 +868,12 @@
     {0xC44C0000u, 46u}, // mcr -> Latn
     {0xD04C0000u, 46u}, // mcu -> Latn
     {0x806C0000u, 46u}, // mda -> Latn
-    {0x906C0000u,  1u}, // mde -> Arab
-    {0x946C0000u, 17u}, // mdf -> Cyrl
+    {0x906C0000u,  2u}, // mde -> Arab
+    {0x946C0000u, 18u}, // mdf -> Cyrl
     {0x9C6C0000u, 46u}, // mdh -> Latn
     {0xA46C0000u, 46u}, // mdj -> Latn
     {0xC46C0000u, 46u}, // mdr -> Latn
-    {0xDC6C0000u, 20u}, // mdx -> Ethi
+    {0xDC6C0000u, 21u}, // mdx -> Ethi
     {0x8C8C0000u, 46u}, // med -> Latn
     {0x908C0000u, 46u}, // mee -> Latn
     {0xA88C0000u, 46u}, // mek -> Latn
@@ -879,7 +881,7 @@
     {0xC48C0000u, 46u}, // mer -> Latn
     {0xCC8C0000u, 46u}, // met -> Latn
     {0xD08C0000u, 46u}, // meu -> Latn
-    {0x80AC0000u,  1u}, // mfa -> Arab
+    {0x80AC0000u,  2u}, // mfa -> Arab
     {0x90AC0000u, 46u}, // mfe -> Latn
     {0xB4AC0000u, 46u}, // mfn -> Latn
     {0xB8AC0000u, 46u}, // mfo -> Latn
@@ -888,7 +890,7 @@
     {0x9CCC0000u, 46u}, // mgh -> Latn
     {0xACCC0000u, 46u}, // mgl -> Latn
     {0xB8CC0000u, 46u}, // mgo -> Latn
-    {0xBCCC0000u, 18u}, // mgp -> Deva
+    {0xBCCC0000u, 19u}, // mgp -> Deva
     {0xE0CC0000u, 46u}, // mgy -> Latn
     {0x6D680000u, 46u}, // mh -> Latn
     {0xA0EC0000u, 46u}, // mhi -> Latn
@@ -896,26 +898,25 @@
     {0x6D690000u, 46u}, // mi -> Latn
     {0x950C0000u, 46u}, // mif -> Latn
     {0xB50C0000u, 46u}, // min -> Latn
-    {0xC90C0000u, 30u}, // mis -> Hatr
     {0xD90C0000u, 46u}, // miw -> Latn
-    {0x6D6B0000u, 17u}, // mk -> Cyrl
-    {0xA14C0000u,  1u}, // mki -> Arab
+    {0x6D6B0000u, 18u}, // mk -> Cyrl
+    {0xA14C0000u,  2u}, // mki -> Arab
     {0xAD4C0000u, 46u}, // mkl -> Latn
     {0xBD4C0000u, 46u}, // mkp -> Latn
     {0xD94C0000u, 46u}, // mkw -> Latn
-    {0x6D6C0000u, 55u}, // ml -> Mlym
+    {0x6D6C0000u, 56u}, // ml -> Mlym
     {0x916C0000u, 46u}, // mle -> Latn
     {0xBD6C0000u, 46u}, // mlp -> Latn
     {0xC96C0000u, 46u}, // mls -> Latn
     {0xB98C0000u, 46u}, // mmo -> Latn
     {0xD18C0000u, 46u}, // mmu -> Latn
     {0xDD8C0000u, 46u}, // mmx -> Latn
-    {0x6D6E0000u, 17u}, // mn -> Cyrl
-    {0x6D6E434Eu, 56u}, // mn-CN -> Mong
+    {0x6D6E0000u, 18u}, // mn -> Cyrl
+    {0x6D6E434Eu, 57u}, // mn-CN -> Mong
     {0x81AC0000u, 46u}, // mna -> Latn
     {0x95AC0000u, 46u}, // mnf -> Latn
-    {0xA1AC0000u,  7u}, // mni -> Beng
-    {0xD9AC0000u, 58u}, // mnw -> Mymr
+    {0xA1AC0000u,  8u}, // mni -> Beng
+    {0xD9AC0000u, 59u}, // mnw -> Mymr
     {0x6D6F0000u, 46u}, // mo -> Latn
     {0x81CC0000u, 46u}, // moa -> Latn
     {0x91CC0000u, 46u}, // moe -> Latn
@@ -927,39 +928,39 @@
     {0xCDEC0000u, 46u}, // mpt -> Latn
     {0xDDEC0000u, 46u}, // mpx -> Latn
     {0xAE0C0000u, 46u}, // mql -> Latn
-    {0x6D720000u, 18u}, // mr -> Deva
-    {0x8E2C0000u, 18u}, // mrd -> Deva
-    {0xA62C0000u, 17u}, // mrj -> Cyrl
-    {0xBA2C0000u, 57u}, // mro -> Mroo
+    {0x6D720000u, 19u}, // mr -> Deva
+    {0x8E2C0000u, 19u}, // mrd -> Deva
+    {0xA62C0000u, 18u}, // mrj -> Cyrl
+    {0xBA2C0000u, 58u}, // mro -> Mroo
     {0x6D730000u, 46u}, // ms -> Latn
-    {0x6D734343u,  1u}, // ms-CC -> Arab
+    {0x6D734343u,  2u}, // ms-CC -> Arab
     {0x6D740000u, 46u}, // mt -> Latn
     {0x8A6C0000u, 46u}, // mtc -> Latn
     {0x966C0000u, 46u}, // mtf -> Latn
     {0xA26C0000u, 46u}, // mti -> Latn
-    {0xC66C0000u, 18u}, // mtr -> Deva
+    {0xC66C0000u, 19u}, // mtr -> Deva
     {0x828C0000u, 46u}, // mua -> Latn
     {0xC68C0000u, 46u}, // mur -> Latn
     {0xCA8C0000u, 46u}, // mus -> Latn
     {0x82AC0000u, 46u}, // mva -> Latn
     {0xB6AC0000u, 46u}, // mvn -> Latn
-    {0xE2AC0000u,  1u}, // mvy -> Arab
+    {0xE2AC0000u,  2u}, // mvy -> Arab
     {0xAACC0000u, 46u}, // mwk -> Latn
-    {0xC6CC0000u, 18u}, // mwr -> Deva
+    {0xC6CC0000u, 19u}, // mwr -> Deva
     {0xD6CC0000u, 46u}, // mwv -> Latn
     {0xDACC0000u, 34u}, // mww -> Hmnp
     {0x8AEC0000u, 46u}, // mxc -> Latn
     {0xB2EC0000u, 46u}, // mxm -> Latn
-    {0x6D790000u, 58u}, // my -> Mymr
+    {0x6D790000u, 59u}, // my -> Mymr
     {0xAB0C0000u, 46u}, // myk -> Latn
-    {0xB30C0000u, 20u}, // mym -> Ethi
-    {0xD70C0000u, 17u}, // myv -> Cyrl
+    {0xB30C0000u, 21u}, // mym -> Ethi
+    {0xD70C0000u, 18u}, // myv -> Cyrl
     {0xDB0C0000u, 46u}, // myw -> Latn
     {0xDF0C0000u, 46u}, // myx -> Latn
     {0xE70C0000u, 52u}, // myz -> Mand
     {0xAB2C0000u, 46u}, // mzk -> Latn
     {0xB32C0000u, 46u}, // mzm -> Latn
-    {0xB72C0000u,  1u}, // mzn -> Arab
+    {0xB72C0000u,  2u}, // mzn -> Arab
     {0xBF2C0000u, 46u}, // mzp -> Latn
     {0xDB2C0000u, 46u}, // mzw -> Latn
     {0xE72C0000u, 46u}, // mzz -> Latn
@@ -967,7 +968,7 @@
     {0x880D0000u, 46u}, // nac -> Latn
     {0x940D0000u, 46u}, // naf -> Latn
     {0xA80D0000u, 46u}, // nak -> Latn
-    {0xB40D0000u, 28u}, // nan -> Hans
+    {0xB40D0000u, 29u}, // nan -> Hans
     {0xBC0D0000u, 46u}, // nap -> Latn
     {0xC00D0000u, 46u}, // naq -> Latn
     {0xC80D0000u, 46u}, // nas -> Latn
@@ -981,9 +982,9 @@
     {0x6E640000u, 46u}, // nd -> Latn
     {0x886D0000u, 46u}, // ndc -> Latn
     {0xC86D0000u, 46u}, // nds -> Latn
-    {0x6E650000u, 18u}, // ne -> Deva
+    {0x6E650000u, 19u}, // ne -> Deva
     {0x848D0000u, 46u}, // neb -> Latn
-    {0xD88D0000u, 18u}, // new -> Deva
+    {0xD88D0000u, 19u}, // new -> Deva
     {0xDC8D0000u, 46u}, // nex -> Latn
     {0xC4AD0000u, 46u}, // nfr -> Latn
     {0x6E670000u, 46u}, // ng -> Latn
@@ -1011,17 +1012,17 @@
     {0x9DAD0000u, 46u}, // nnh -> Latn
     {0xA9AD0000u, 46u}, // nnk -> Latn
     {0xB1AD0000u, 46u}, // nnm -> Latn
-    {0xBDAD0000u, 94u}, // nnp -> Wcho
+    {0xBDAD0000u, 95u}, // nnp -> Wcho
     {0x6E6F0000u, 46u}, // no -> Latn
     {0x8DCD0000u, 44u}, // nod -> Lana
-    {0x91CD0000u, 18u}, // noe -> Deva
-    {0xB5CD0000u, 72u}, // non -> Runr
+    {0x91CD0000u, 19u}, // noe -> Deva
+    {0xB5CD0000u, 73u}, // non -> Runr
     {0xBDCD0000u, 46u}, // nop -> Latn
     {0xD1CD0000u, 46u}, // nou -> Latn
-    {0xBA0D0000u, 60u}, // nqo -> Nkoo
+    {0xBA0D0000u, 61u}, // nqo -> Nkoo
     {0x6E720000u, 46u}, // nr -> Latn
     {0x862D0000u, 46u}, // nrb -> Latn
-    {0xAA4D0000u, 10u}, // nsk -> Cans
+    {0xAA4D0000u, 11u}, // nsk -> Cans
     {0xB64D0000u, 46u}, // nsn -> Latn
     {0xBA4D0000u, 46u}, // nso -> Latn
     {0xCA4D0000u, 46u}, // nss -> Latn
@@ -1049,18 +1050,18 @@
     {0xB5AE0000u, 46u}, // onn -> Latn
     {0xC9AE0000u, 46u}, // ons -> Latn
     {0xB1EE0000u, 46u}, // opm -> Latn
-    {0x6F720000u, 65u}, // or -> Orya
+    {0x6F720000u, 66u}, // or -> Orya
     {0xBA2E0000u, 46u}, // oro -> Latn
-    {0xD22E0000u,  1u}, // oru -> Arab
-    {0x6F730000u, 17u}, // os -> Cyrl
-    {0x824E0000u, 66u}, // osa -> Osge
-    {0x826E0000u,  1u}, // ota -> Arab
-    {0xAA6E0000u, 64u}, // otk -> Orkh
+    {0xD22E0000u,  2u}, // oru -> Arab
+    {0x6F730000u, 18u}, // os -> Cyrl
+    {0x824E0000u, 67u}, // osa -> Osge
+    {0x826E0000u,  2u}, // ota -> Arab
+    {0xAA6E0000u, 65u}, // otk -> Orkh
     {0xB32E0000u, 46u}, // ozm -> Latn
-    {0x70610000u, 27u}, // pa -> Guru
-    {0x7061504Bu,  1u}, // pa-PK -> Arab
+    {0x70610000u, 28u}, // pa -> Guru
+    {0x7061504Bu,  2u}, // pa-PK -> Arab
     {0x980F0000u, 46u}, // pag -> Latn
-    {0xAC0F0000u, 68u}, // pal -> Phli
+    {0xAC0F0000u, 69u}, // pal -> Phli
     {0xB00F0000u, 46u}, // pam -> Latn
     {0xBC0F0000u, 46u}, // pap -> Latn
     {0xD00F0000u, 46u}, // pau -> Latn
@@ -1070,28 +1071,28 @@
     {0x886F0000u, 46u}, // pdc -> Latn
     {0xCC6F0000u, 46u}, // pdt -> Latn
     {0x8C8F0000u, 46u}, // ped -> Latn
-    {0xB88F0000u, 95u}, // peo -> Xpeo
+    {0xB88F0000u, 96u}, // peo -> Xpeo
     {0xDC8F0000u, 46u}, // pex -> Latn
     {0xACAF0000u, 46u}, // pfl -> Latn
-    {0xACEF0000u,  1u}, // phl -> Arab
-    {0xB4EF0000u, 69u}, // phn -> Phnx
+    {0xACEF0000u,  2u}, // phl -> Arab
+    {0xB4EF0000u, 70u}, // phn -> Phnx
     {0xAD0F0000u, 46u}, // pil -> Latn
     {0xBD0F0000u, 46u}, // pip -> Latn
-    {0x814F0000u,  8u}, // pka -> Brah
+    {0x814F0000u,  9u}, // pka -> Brah
     {0xB94F0000u, 46u}, // pko -> Latn
     {0x706C0000u, 46u}, // pl -> Latn
     {0x816F0000u, 46u}, // pla -> Latn
     {0xC98F0000u, 46u}, // pms -> Latn
     {0x99AF0000u, 46u}, // png -> Latn
     {0xB5AF0000u, 46u}, // pnn -> Latn
-    {0xCDAF0000u, 25u}, // pnt -> Grek
+    {0xCDAF0000u, 26u}, // pnt -> Grek
     {0xB5CF0000u, 46u}, // pon -> Latn
-    {0x81EF0000u, 18u}, // ppa -> Deva
+    {0x81EF0000u, 19u}, // ppa -> Deva
     {0xB9EF0000u, 46u}, // ppo -> Latn
     {0x822F0000u, 39u}, // pra -> Khar
-    {0x8E2F0000u,  1u}, // prd -> Arab
+    {0x8E2F0000u,  2u}, // prd -> Arab
     {0x9A2F0000u, 46u}, // prg -> Latn
-    {0x70730000u,  1u}, // ps -> Arab
+    {0x70730000u,  2u}, // ps -> Arab
     {0xCA4F0000u, 46u}, // pss -> Latn
     {0x70740000u, 46u}, // pt -> Latn
     {0xBE6F0000u, 46u}, // ptp -> Latn
@@ -1101,23 +1102,23 @@
     {0x8A900000u, 46u}, // quc -> Latn
     {0x9A900000u, 46u}, // qug -> Latn
     {0xA0110000u, 46u}, // rai -> Latn
-    {0xA4110000u, 18u}, // raj -> Deva
+    {0xA4110000u, 19u}, // raj -> Deva
     {0xB8110000u, 46u}, // rao -> Latn
     {0x94510000u, 46u}, // rcf -> Latn
     {0xA4910000u, 46u}, // rej -> Latn
     {0xAC910000u, 46u}, // rel -> Latn
     {0xC8910000u, 46u}, // res -> Latn
     {0xB4D10000u, 46u}, // rgn -> Latn
-    {0x98F10000u,  1u}, // rhg -> Arab
+    {0x98F10000u,  2u}, // rhg -> Arab
     {0x81110000u, 46u}, // ria -> Latn
-    {0x95110000u, 88u}, // rif -> Tfng
+    {0x95110000u, 89u}, // rif -> Tfng
     {0x95114E4Cu, 46u}, // rif-NL -> Latn
-    {0xC9310000u, 18u}, // rjs -> Deva
-    {0xCD510000u,  7u}, // rkt -> Beng
+    {0xC9310000u, 19u}, // rjs -> Deva
+    {0xCD510000u,  8u}, // rkt -> Beng
     {0x726D0000u, 46u}, // rm -> Latn
     {0x95910000u, 46u}, // rmf -> Latn
     {0xB9910000u, 46u}, // rmo -> Latn
-    {0xCD910000u,  1u}, // rmt -> Arab
+    {0xCD910000u,  2u}, // rmt -> Arab
     {0xD1910000u, 46u}, // rmu -> Latn
     {0x726E0000u, 46u}, // rn -> Latn
     {0x81B10000u, 46u}, // rna -> Latn
@@ -1128,49 +1129,49 @@
     {0xB9D10000u, 46u}, // roo -> Latn
     {0xBA310000u, 46u}, // rro -> Latn
     {0xB2710000u, 46u}, // rtm -> Latn
-    {0x72750000u, 17u}, // ru -> Cyrl
-    {0x92910000u, 17u}, // rue -> Cyrl
+    {0x72750000u, 18u}, // ru -> Cyrl
+    {0x92910000u, 18u}, // rue -> Cyrl
     {0x9A910000u, 46u}, // rug -> Latn
     {0x72770000u, 46u}, // rw -> Latn
     {0xAAD10000u, 46u}, // rwk -> Latn
     {0xBAD10000u, 46u}, // rwo -> Latn
     {0xD3110000u, 38u}, // ryu -> Kana
-    {0x73610000u, 18u}, // sa -> Deva
+    {0x73610000u, 19u}, // sa -> Deva
     {0x94120000u, 46u}, // saf -> Latn
-    {0x9C120000u, 17u}, // sah -> Cyrl
+    {0x9C120000u, 18u}, // sah -> Cyrl
     {0xC0120000u, 46u}, // saq -> Latn
     {0xC8120000u, 46u}, // sas -> Latn
-    {0xCC120000u, 63u}, // sat -> Olck
+    {0xCC120000u, 64u}, // sat -> Olck
     {0xD4120000u, 46u}, // sav -> Latn
-    {0xE4120000u, 75u}, // saz -> Saur
+    {0xE4120000u, 76u}, // saz -> Saur
     {0x80320000u, 46u}, // sba -> Latn
     {0x90320000u, 46u}, // sbe -> Latn
     {0xBC320000u, 46u}, // sbp -> Latn
     {0x73630000u, 46u}, // sc -> Latn
-    {0xA8520000u, 18u}, // sck -> Deva
-    {0xAC520000u,  1u}, // scl -> Arab
+    {0xA8520000u, 19u}, // sck -> Deva
+    {0xAC520000u,  2u}, // scl -> Arab
     {0xB4520000u, 46u}, // scn -> Latn
     {0xB8520000u, 46u}, // sco -> Latn
     {0xC8520000u, 46u}, // scs -> Latn
-    {0x73640000u,  1u}, // sd -> Arab
+    {0x73640000u,  2u}, // sd -> Arab
     {0x88720000u, 46u}, // sdc -> Latn
-    {0x9C720000u,  1u}, // sdh -> Arab
+    {0x9C720000u,  2u}, // sdh -> Arab
     {0x73650000u, 46u}, // se -> Latn
     {0x94920000u, 46u}, // sef -> Latn
     {0x9C920000u, 46u}, // seh -> Latn
     {0xA0920000u, 46u}, // sei -> Latn
     {0xC8920000u, 46u}, // ses -> Latn
     {0x73670000u, 46u}, // sg -> Latn
-    {0x80D20000u, 62u}, // sga -> Ogam
+    {0x80D20000u, 63u}, // sga -> Ogam
     {0xC8D20000u, 46u}, // sgs -> Latn
-    {0xD8D20000u, 20u}, // sgw -> Ethi
+    {0xD8D20000u, 21u}, // sgw -> Ethi
     {0xE4D20000u, 46u}, // sgz -> Latn
     {0x73680000u, 46u}, // sh -> Latn
-    {0xA0F20000u, 88u}, // shi -> Tfng
+    {0xA0F20000u, 89u}, // shi -> Tfng
     {0xA8F20000u, 46u}, // shk -> Latn
-    {0xB4F20000u, 58u}, // shn -> Mymr
-    {0xD0F20000u,  1u}, // shu -> Arab
-    {0x73690000u, 77u}, // si -> Sinh
+    {0xB4F20000u, 59u}, // shn -> Mymr
+    {0xD0F20000u,  2u}, // shu -> Arab
+    {0x73690000u, 78u}, // si -> Sinh
     {0x8D120000u, 46u}, // sid -> Latn
     {0x99120000u, 46u}, // sig -> Latn
     {0xAD120000u, 46u}, // sil -> Latn
@@ -1178,7 +1179,7 @@
     {0xC5320000u, 46u}, // sjr -> Latn
     {0x736B0000u, 46u}, // sk -> Latn
     {0x89520000u, 46u}, // skc -> Latn
-    {0xC5520000u,  1u}, // skr -> Arab
+    {0xC5520000u,  2u}, // skr -> Arab
     {0xC9520000u, 46u}, // sks -> Latn
     {0x736C0000u, 46u}, // sl -> Latn
     {0x8D720000u, 46u}, // sld -> Latn
@@ -1189,7 +1190,7 @@
     {0x81920000u, 46u}, // sma -> Latn
     {0xA5920000u, 46u}, // smj -> Latn
     {0xB5920000u, 46u}, // smn -> Latn
-    {0xBD920000u, 73u}, // smp -> Samr
+    {0xBD920000u, 74u}, // smp -> Samr
     {0xC1920000u, 46u}, // smq -> Latn
     {0xC9920000u, 46u}, // sms -> Latn
     {0x736E0000u, 46u}, // sn -> Latn
@@ -1199,24 +1200,24 @@
     {0xDDB20000u, 46u}, // snx -> Latn
     {0xE1B20000u, 46u}, // sny -> Latn
     {0x736F0000u, 46u}, // so -> Latn
-    {0x99D20000u, 78u}, // sog -> Sogd
+    {0x99D20000u, 79u}, // sog -> Sogd
     {0xA9D20000u, 46u}, // sok -> Latn
     {0xC1D20000u, 46u}, // soq -> Latn
-    {0xD1D20000u, 90u}, // sou -> Thai
+    {0xD1D20000u, 91u}, // sou -> Thai
     {0xE1D20000u, 46u}, // soy -> Latn
     {0x8DF20000u, 46u}, // spd -> Latn
     {0xADF20000u, 46u}, // spl -> Latn
     {0xC9F20000u, 46u}, // sps -> Latn
     {0x73710000u, 46u}, // sq -> Latn
-    {0x73720000u, 17u}, // sr -> Cyrl
+    {0x73720000u, 18u}, // sr -> Cyrl
     {0x73724D45u, 46u}, // sr-ME -> Latn
     {0x7372524Fu, 46u}, // sr-RO -> Latn
     {0x73725255u, 46u}, // sr-RU -> Latn
     {0x73725452u, 46u}, // sr-TR -> Latn
-    {0x86320000u, 79u}, // srb -> Sora
+    {0x86320000u, 80u}, // srb -> Sora
     {0xB6320000u, 46u}, // srn -> Latn
     {0xC6320000u, 46u}, // srr -> Latn
-    {0xDE320000u, 18u}, // srx -> Deva
+    {0xDE320000u, 19u}, // srx -> Deva
     {0x73730000u, 46u}, // ss -> Latn
     {0x8E520000u, 46u}, // ssd -> Latn
     {0x9A520000u, 46u}, // ssg -> Latn
@@ -1232,18 +1233,18 @@
     {0xCA920000u, 46u}, // sus -> Latn
     {0x73760000u, 46u}, // sv -> Latn
     {0x73770000u, 46u}, // sw -> Latn
-    {0x86D20000u,  1u}, // swb -> Arab
+    {0x86D20000u,  2u}, // swb -> Arab
     {0x8AD20000u, 46u}, // swc -> Latn
     {0x9AD20000u, 46u}, // swg -> Latn
     {0xBED20000u, 46u}, // swp -> Latn
-    {0xD6D20000u, 18u}, // swv -> Deva
+    {0xD6D20000u, 19u}, // swv -> Deva
     {0xB6F20000u, 46u}, // sxn -> Latn
     {0xDAF20000u, 46u}, // sxw -> Latn
-    {0xAF120000u,  7u}, // syl -> Beng
-    {0xC7120000u, 81u}, // syr -> Syrc
+    {0xAF120000u,  8u}, // syl -> Beng
+    {0xC7120000u, 82u}, // syr -> Syrc
     {0xAF320000u, 46u}, // szl -> Latn
-    {0x74610000u, 84u}, // ta -> Taml
-    {0xA4130000u, 18u}, // taj -> Deva
+    {0x74610000u, 85u}, // ta -> Taml
+    {0xA4130000u, 19u}, // taj -> Deva
     {0xAC130000u, 46u}, // tal -> Latn
     {0xB4130000u, 46u}, // tan -> Latn
     {0xC0130000u, 46u}, // taq -> Latn
@@ -1256,28 +1257,28 @@
     {0xE4330000u, 46u}, // tbz -> Latn
     {0xA0530000u, 46u}, // tci -> Latn
     {0xE0530000u, 42u}, // tcy -> Knda
-    {0x8C730000u, 82u}, // tdd -> Tale
-    {0x98730000u, 18u}, // tdg -> Deva
-    {0x9C730000u, 18u}, // tdh -> Deva
+    {0x8C730000u, 83u}, // tdd -> Tale
+    {0x98730000u, 19u}, // tdg -> Deva
+    {0x9C730000u, 19u}, // tdh -> Deva
     {0xD0730000u, 46u}, // tdu -> Latn
-    {0x74650000u, 87u}, // te -> Telu
+    {0x74650000u, 88u}, // te -> Telu
     {0x8C930000u, 46u}, // ted -> Latn
     {0xB0930000u, 46u}, // tem -> Latn
     {0xB8930000u, 46u}, // teo -> Latn
     {0xCC930000u, 46u}, // tet -> Latn
     {0xA0B30000u, 46u}, // tfi -> Latn
-    {0x74670000u, 17u}, // tg -> Cyrl
-    {0x7467504Bu,  1u}, // tg-PK -> Arab
+    {0x74670000u, 18u}, // tg -> Cyrl
+    {0x7467504Bu,  2u}, // tg-PK -> Arab
     {0x88D30000u, 46u}, // tgc -> Latn
     {0xB8D30000u, 46u}, // tgo -> Latn
     {0xD0D30000u, 46u}, // tgu -> Latn
-    {0x74680000u, 90u}, // th -> Thai
-    {0xACF30000u, 18u}, // thl -> Deva
-    {0xC0F30000u, 18u}, // thq -> Deva
-    {0xC4F30000u, 18u}, // thr -> Deva
-    {0x74690000u, 20u}, // ti -> Ethi
+    {0x74680000u, 91u}, // th -> Thai
+    {0xACF30000u, 19u}, // thl -> Deva
+    {0xC0F30000u, 19u}, // thq -> Deva
+    {0xC4F30000u, 19u}, // thr -> Deva
+    {0x74690000u, 21u}, // ti -> Ethi
     {0x95130000u, 46u}, // tif -> Latn
-    {0x99130000u, 20u}, // tig -> Ethi
+    {0x99130000u, 21u}, // tig -> Ethi
     {0xA9130000u, 46u}, // tik -> Latn
     {0xB1130000u, 46u}, // tim -> Latn
     {0xB9130000u, 46u}, // tio -> Latn
@@ -1285,7 +1286,7 @@
     {0x746B0000u, 46u}, // tk -> Latn
     {0xAD530000u, 46u}, // tkl -> Latn
     {0xC5530000u, 46u}, // tkr -> Latn
-    {0xCD530000u, 18u}, // tkt -> Deva
+    {0xCD530000u, 19u}, // tkt -> Deva
     {0x746C0000u, 46u}, // tl -> Latn
     {0x95730000u, 46u}, // tlf -> Latn
     {0xDD730000u, 46u}, // tlx -> Latn
@@ -1305,19 +1306,19 @@
     {0x74720000u, 46u}, // tr -> Latn
     {0xD2330000u, 46u}, // tru -> Latn
     {0xD6330000u, 46u}, // trv -> Latn
-    {0xDA330000u,  1u}, // trw -> Arab
+    {0xDA330000u,  2u}, // trw -> Arab
     {0x74730000u, 46u}, // ts -> Latn
-    {0x8E530000u, 25u}, // tsd -> Grek
-    {0x96530000u, 18u}, // tsf -> Deva
+    {0x8E530000u, 26u}, // tsd -> Grek
+    {0x96530000u, 19u}, // tsf -> Deva
     {0x9A530000u, 46u}, // tsg -> Latn
-    {0xA6530000u, 91u}, // tsj -> Tibt
+    {0xA6530000u, 92u}, // tsj -> Tibt
     {0xDA530000u, 46u}, // tsw -> Latn
-    {0x74740000u, 17u}, // tt -> Cyrl
+    {0x74740000u, 18u}, // tt -> Cyrl
     {0x8E730000u, 46u}, // ttd -> Latn
     {0x92730000u, 46u}, // tte -> Latn
     {0xA6730000u, 46u}, // ttj -> Latn
     {0xC6730000u, 46u}, // ttr -> Latn
-    {0xCA730000u, 90u}, // tts -> Thai
+    {0xCA730000u, 91u}, // tts -> Thai
     {0xCE730000u, 46u}, // ttt -> Latn
     {0x9E930000u, 46u}, // tuh -> Latn
     {0xAE930000u, 46u}, // tul -> Latn
@@ -1328,25 +1329,26 @@
     {0xD2B30000u, 46u}, // tvu -> Latn
     {0x9ED30000u, 46u}, // twh -> Latn
     {0xC2D30000u, 46u}, // twq -> Latn
-    {0x9AF30000u, 85u}, // txg -> Tang
+    {0x9AF30000u, 86u}, // txg -> Tang
     {0x74790000u, 46u}, // ty -> Latn
     {0x83130000u, 46u}, // tya -> Latn
-    {0xD7130000u, 17u}, // tyv -> Cyrl
+    {0xD7130000u, 18u}, // tyv -> Cyrl
     {0xB3330000u, 46u}, // tzm -> Latn
     {0xD0340000u, 46u}, // ubu -> Latn
-    {0xB0740000u, 17u}, // udm -> Cyrl
-    {0x75670000u,  1u}, // ug -> Arab
-    {0x75674B5Au, 17u}, // ug-KZ -> Cyrl
-    {0x75674D4Eu, 17u}, // ug-MN -> Cyrl
-    {0x80D40000u, 92u}, // uga -> Ugar
-    {0x756B0000u, 17u}, // uk -> Cyrl
+    {0xA0740000u,  0u}, // udi -> Aghb
+    {0xB0740000u, 18u}, // udm -> Cyrl
+    {0x75670000u,  2u}, // ug -> Arab
+    {0x75674B5Au, 18u}, // ug-KZ -> Cyrl
+    {0x75674D4Eu, 18u}, // ug-MN -> Cyrl
+    {0x80D40000u, 93u}, // uga -> Ugar
+    {0x756B0000u, 18u}, // uk -> Cyrl
     {0xA1740000u, 46u}, // uli -> Latn
     {0x85940000u, 46u}, // umb -> Latn
-    {0xC5B40000u,  7u}, // unr -> Beng
-    {0xC5B44E50u, 18u}, // unr-NP -> Deva
-    {0xDDB40000u,  7u}, // unx -> Beng
+    {0xC5B40000u,  8u}, // unr -> Beng
+    {0xC5B44E50u, 19u}, // unr-NP -> Deva
+    {0xDDB40000u,  8u}, // unx -> Beng
     {0xA9D40000u, 46u}, // uok -> Latn
-    {0x75720000u,  1u}, // ur -> Arab
+    {0x75720000u,  2u}, // ur -> Arab
     {0xA2340000u, 46u}, // uri -> Latn
     {0xCE340000u, 46u}, // urt -> Latn
     {0xDA340000u, 46u}, // urw -> Latn
@@ -1356,10 +1358,10 @@
     {0x9EB40000u, 46u}, // uvh -> Latn
     {0xAEB40000u, 46u}, // uvl -> Latn
     {0x757A0000u, 46u}, // uz -> Latn
-    {0x757A4146u,  1u}, // uz-AF -> Arab
-    {0x757A434Eu, 17u}, // uz-CN -> Cyrl
+    {0x757A4146u,  2u}, // uz-AF -> Arab
+    {0x757A434Eu, 18u}, // uz-CN -> Cyrl
     {0x98150000u, 46u}, // vag -> Latn
-    {0xA0150000u, 93u}, // vai -> Vaii
+    {0xA0150000u, 94u}, // vai -> Vaii
     {0xB4150000u, 46u}, // van -> Latn
     {0x76650000u, 46u}, // ve -> Latn
     {0x88950000u, 46u}, // vec -> Latn
@@ -1378,12 +1380,12 @@
     {0x77610000u, 46u}, // wa -> Latn
     {0x90160000u, 46u}, // wae -> Latn
     {0xA4160000u, 46u}, // waj -> Latn
-    {0xAC160000u, 20u}, // wal -> Ethi
+    {0xAC160000u, 21u}, // wal -> Ethi
     {0xB4160000u, 46u}, // wan -> Latn
     {0xC4160000u, 46u}, // war -> Latn
     {0xBC360000u, 46u}, // wbp -> Latn
-    {0xC0360000u, 87u}, // wbq -> Telu
-    {0xC4360000u, 18u}, // wbr -> Deva
+    {0xC0360000u, 88u}, // wbq -> Telu
+    {0xC4360000u, 19u}, // wbr -> Deva
     {0xA0560000u, 46u}, // wci -> Latn
     {0xC4960000u, 46u}, // wer -> Latn
     {0xA0D60000u, 46u}, // wgi -> Latn
@@ -1396,40 +1398,40 @@
     {0xC9760000u, 46u}, // wls -> Latn
     {0xB9960000u, 46u}, // wmo -> Latn
     {0x89B60000u, 46u}, // wnc -> Latn
-    {0xA1B60000u,  1u}, // wni -> Arab
+    {0xA1B60000u,  2u}, // wni -> Arab
     {0xD1B60000u, 46u}, // wnu -> Latn
     {0x776F0000u, 46u}, // wo -> Latn
     {0x85D60000u, 46u}, // wob -> Latn
     {0xC9D60000u, 46u}, // wos -> Latn
     {0xCA360000u, 46u}, // wrs -> Latn
-    {0x9A560000u, 22u}, // wsg -> Gong
+    {0x9A560000u, 23u}, // wsg -> Gong
     {0xAA560000u, 46u}, // wsk -> Latn
-    {0xB2760000u, 18u}, // wtm -> Deva
-    {0xD2960000u, 28u}, // wuu -> Hans
+    {0xB2760000u, 19u}, // wtm -> Deva
+    {0xD2960000u, 29u}, // wuu -> Hans
     {0xD6960000u, 46u}, // wuv -> Latn
     {0x82D60000u, 46u}, // wwa -> Latn
     {0xD4170000u, 46u}, // xav -> Latn
     {0xA0370000u, 46u}, // xbi -> Latn
-    {0xB8570000u, 14u}, // xco -> Chrs
-    {0xC4570000u, 11u}, // xcr -> Cari
+    {0xB8570000u, 15u}, // xco -> Chrs
+    {0xC4570000u, 12u}, // xcr -> Cari
     {0xC8970000u, 46u}, // xes -> Latn
     {0x78680000u, 46u}, // xh -> Latn
     {0x81770000u, 46u}, // xla -> Latn
     {0x89770000u, 50u}, // xlc -> Lyci
     {0x8D770000u, 51u}, // xld -> Lydi
-    {0x95970000u, 21u}, // xmf -> Geor
+    {0x95970000u, 22u}, // xmf -> Geor
     {0xB5970000u, 53u}, // xmn -> Mani
-    {0xC5970000u, 54u}, // xmr -> Merc
-    {0x81B70000u, 59u}, // xna -> Narb
-    {0xC5B70000u, 18u}, // xnr -> Deva
+    {0xC5970000u, 55u}, // xmr -> Merc
+    {0x81B70000u, 60u}, // xna -> Narb
+    {0xC5B70000u, 19u}, // xnr -> Deva
     {0x99D70000u, 46u}, // xog -> Latn
     {0xB5D70000u, 46u}, // xon -> Latn
-    {0xC5F70000u, 71u}, // xpr -> Prti
+    {0xC5F70000u, 72u}, // xpr -> Prti
     {0x86370000u, 46u}, // xrb -> Latn
-    {0x82570000u, 74u}, // xsa -> Sarb
+    {0x82570000u, 75u}, // xsa -> Sarb
     {0xA2570000u, 46u}, // xsi -> Latn
     {0xB2570000u, 46u}, // xsm -> Latn
-    {0xC6570000u, 18u}, // xsr -> Deva
+    {0xC6570000u, 19u}, // xsr -> Deva
     {0x92D70000u, 46u}, // xwe -> Latn
     {0xB0180000u, 46u}, // yam -> Latn
     {0xB8180000u, 46u}, // yao -> Latn
@@ -1458,33 +1460,33 @@
     {0xAE380000u, 46u}, // yrl -> Latn
     {0xCA580000u, 46u}, // yss -> Latn
     {0x82980000u, 46u}, // yua -> Latn
-    {0x92980000u, 29u}, // yue -> Hant
-    {0x9298434Eu, 28u}, // yue-CN -> Hans
+    {0x92980000u, 30u}, // yue -> Hant
+    {0x9298434Eu, 29u}, // yue-CN -> Hans
     {0xA6980000u, 46u}, // yuj -> Latn
     {0xCE980000u, 46u}, // yut -> Latn
     {0xDA980000u, 46u}, // yuw -> Latn
     {0x7A610000u, 46u}, // za -> Latn
     {0x98190000u, 46u}, // zag -> Latn
-    {0xA4790000u,  1u}, // zdj -> Arab
+    {0xA4790000u,  2u}, // zdj -> Arab
     {0x80990000u, 46u}, // zea -> Latn
-    {0x9CD90000u, 88u}, // zgh -> Tfng
-    {0x7A680000u, 28u}, // zh -> Hans
-    {0x7A684155u, 29u}, // zh-AU -> Hant
-    {0x7A68424Eu, 29u}, // zh-BN -> Hant
-    {0x7A684742u, 29u}, // zh-GB -> Hant
-    {0x7A684746u, 29u}, // zh-GF -> Hant
-    {0x7A68484Bu, 29u}, // zh-HK -> Hant
-    {0x7A684944u, 29u}, // zh-ID -> Hant
-    {0x7A684D4Fu, 29u}, // zh-MO -> Hant
-    {0x7A685041u, 29u}, // zh-PA -> Hant
-    {0x7A685046u, 29u}, // zh-PF -> Hant
-    {0x7A685048u, 29u}, // zh-PH -> Hant
-    {0x7A685352u, 29u}, // zh-SR -> Hant
-    {0x7A685448u, 29u}, // zh-TH -> Hant
-    {0x7A685457u, 29u}, // zh-TW -> Hant
-    {0x7A685553u, 29u}, // zh-US -> Hant
-    {0x7A68564Eu, 29u}, // zh-VN -> Hant
-    {0xDCF90000u, 61u}, // zhx -> Nshu
+    {0x9CD90000u, 89u}, // zgh -> Tfng
+    {0x7A680000u, 29u}, // zh -> Hans
+    {0x7A684155u, 30u}, // zh-AU -> Hant
+    {0x7A68424Eu, 30u}, // zh-BN -> Hant
+    {0x7A684742u, 30u}, // zh-GB -> Hant
+    {0x7A684746u, 30u}, // zh-GF -> Hant
+    {0x7A68484Bu, 30u}, // zh-HK -> Hant
+    {0x7A684944u, 30u}, // zh-ID -> Hant
+    {0x7A684D4Fu, 30u}, // zh-MO -> Hant
+    {0x7A685041u, 30u}, // zh-PA -> Hant
+    {0x7A685046u, 30u}, // zh-PF -> Hant
+    {0x7A685048u, 30u}, // zh-PH -> Hant
+    {0x7A685352u, 30u}, // zh-SR -> Hant
+    {0x7A685448u, 30u}, // zh-TH -> Hant
+    {0x7A685457u, 30u}, // zh-TW -> Hant
+    {0x7A685553u, 30u}, // zh-US -> Hant
+    {0x7A68564Eu, 30u}, // zh-VN -> Hant
+    {0xDCF90000u, 62u}, // zhx -> Nshu
     {0x81190000u, 46u}, // zia -> Latn
     {0xCD590000u, 41u}, // zkt -> Kits
     {0xB1790000u, 46u}, // zlm -> Latn
@@ -1642,6 +1644,7 @@
     0xB48343414C61746ELLU, // den_Latn_CA
     0xC4C343414C61746ELLU, // dgr_Latn_CA
     0x91234E454C61746ELLU, // dje_Latn_NE
+    0x95834E474D656466LLU, // dmf_Medf_NG
     0xA5A343494C61746ELLU, // dnj_Latn_CI
     0xA1C3494E44657661LLU, // doi_Deva_IN
     0x9E23434E4D6F6E67LLU, // drh_Mong_CN
@@ -1917,8 +1920,6 @@
     0x6D684D484C61746ELLU, // mh_Latn_MH
     0x6D694E5A4C61746ELLU, // mi_Latn_NZ
     0xB50C49444C61746ELLU, // min_Latn_ID
-    0xC90C495148617472LLU, // mis_Hatr_IQ
-    0xC90C4E474D656466LLU, // mis_Medf_NG
     0x6D6B4D4B4379726CLLU, // mk_Cyrl_MK
     0x6D6C494E4D6C796DLLU, // ml_Mlym_IN
     0xC96C53444C61746ELLU, // mls_Latn_SD
@@ -2174,6 +2175,7 @@
     0x747950464C61746ELLU, // ty_Latn_PF
     0xD71352554379726CLLU, // tyv_Cyrl_RU
     0xB3334D414C61746ELLU, // tzm_Latn_MA
+    0xA074525541676862LLU, // udi_Aghb_RU
     0xB07452554379726CLLU, // udm_Cyrl_RU
     0x7567434E41726162LLU, // ug_Arab_CN
     0x75674B5A4379726CLLU, // ug_Cyrl_KZ
@@ -2382,6 +2384,8 @@
     {0x65735553u, 0x6573A424u}, // es-US -> es-419
     {0x65735559u, 0x6573A424u}, // es-UY -> es-419
     {0x65735645u, 0x6573A424u}, // es-VE -> es-419
+    {0x6E620000u, 0x6E6F0000u}, // nb -> no
+    {0x6E6E0000u, 0x6E6F0000u}, // nn -> no
     {0x7074414Fu, 0x70745054u}, // pt-AO -> pt-PT
     {0x70744348u, 0x70745054u}, // pt-CH -> pt-PT
     {0x70744356u, 0x70745054u}, // pt-CV -> pt-PT
diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
index 4ec525a..0269128 100644
--- a/libs/androidfw/PosixUtils.cpp
+++ b/libs/androidfw/PosixUtils.cpp
@@ -114,10 +114,10 @@
       std::unique_ptr<ProcResult> result(new ProcResult());
       result->status = status;
       const auto out = ReadFile(stdout[0]);
-      result->stdout = out ? *out : "";
+      result->stdout_str = out ? *out : "";
       close(stdout[0]);
       const auto err = ReadFile(stderr[0]);
-      result->stderr = err ? *err : "";
+      result->stderr_str = err ? *err : "";
       close(stderr[0]);
       return result;
   }
diff --git a/libs/androidfw/include/androidfw/PosixUtils.h b/libs/androidfw/include/androidfw/PosixUtils.h
index 8fc3ee2..bb20847 100644
--- a/libs/androidfw/include/androidfw/PosixUtils.h
+++ b/libs/androidfw/include/androidfw/PosixUtils.h
@@ -23,8 +23,8 @@
 
 struct ProcResult {
   int status;
-  std::string stdout;
-  std::string stderr;
+  std::string stdout_str;
+  std::string stderr_str;
 };
 
 // Fork, exec and wait for an external process. Return nullptr if the process could not be launched,
diff --git a/libs/androidfw/tests/PosixUtils_test.cpp b/libs/androidfw/tests/PosixUtils_test.cpp
index cf97f87..c7b3eba 100644
--- a/libs/androidfw/tests/PosixUtils_test.cpp
+++ b/libs/androidfw/tests/PosixUtils_test.cpp
@@ -30,14 +30,14 @@
   const auto result = ExecuteBinary({"/bin/date", "--help"});
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, 0);
-  ASSERT_EQ(result->stdout.find("usage: date "), 0);
+  ASSERT_EQ(result->stdout_str.find("usage: date "), 0);
 }
 
 TEST(PosixUtilsTest, RelativePathToBinary) {
   const auto result = ExecuteBinary({"date", "--help"});
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, 0);
-  ASSERT_EQ(result->stdout.find("usage: date "), 0);
+  ASSERT_EQ(result->stdout_str.find("usage: date "), 0);
 }
 
 TEST(PosixUtilsTest, BadParameters) {
diff --git a/libs/hwui/jni/PaintFilter.cpp b/libs/hwui/jni/PaintFilter.cpp
index ec115b4..86d4742 100644
--- a/libs/hwui/jni/PaintFilter.cpp
+++ b/libs/hwui/jni/PaintFilter.cpp
@@ -74,7 +74,7 @@
     result |= RegisterMethodsOrDie(env, "android/graphics/PaintFlagsDrawFilter", paintflags_methods,
                                    NELEM(paintflags_methods));
 
-    return 0;
+    return result;
 }
 
 }
diff --git a/media/OWNERS b/media/OWNERS
index abfc8bf..0aff43e 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,8 +1,7 @@
-chz@google.com
+# Bug component: 1344
 elaurent@google.com
 essick@google.com
 etalvala@google.com
-gkasten@google.com
 hdmoon@google.com
 hkuang@google.com
 hunga@google.com
@@ -13,16 +12,13 @@
 jsharkey@android.com
 klhyun@google.com
 lajos@google.com
-marcone@google.com
 nchalko@google.com
 philburk@google.com
 quxiangfang@google.com
 wonsik@google.com
 
-# LON
-andrewlewis@google.com
-aquilescanta@google.com
-olly@google.com
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
 
 # SEO
 sungsoo@google.com
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d22e97c..8390ae4 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5273,6 +5273,40 @@
         }
     }
 
+    /**
+    * Indicate Le Audio output device connection state change and eventually suppress
+    * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
+    * @param device Bluetooth device connected/disconnected
+    * @param state new connection state (BluetoothProfile.STATE_xxx)
+    * @param suppressNoisyIntent if true the
+    * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
+    * {@hide}
+    */
+    public void setBluetoothLeAudioOutDeviceConnectionState(BluetoothDevice device, int state,
+            boolean suppressNoisyIntent) {
+        final IAudioService service = getService();
+        try {
+            service.setBluetoothLeAudioOutDeviceConnectionState(device, state, suppressNoisyIntent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+    * Indicate Le Audio input connection state change.
+    * @param device Bluetooth device connected/disconnected
+    * @param state new connection state (BluetoothProfile.STATE_xxx)
+    * {@hide}
+    */
+    public void setBluetoothLeAudioInDeviceConnectionState(BluetoothDevice device, int state) {
+        final IAudioService service = getService();
+        try {
+            service.setBluetoothLeAudioInDeviceConnectionState(device, state);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
      /**
      * Indicate A2DP source or sink connection state change and eventually suppress
      * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index ed48b56..73bc428 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -256,6 +256,11 @@
     void setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
             int state, boolean suppressNoisyIntent, int musicDevice);
 
+    void setBluetoothLeAudioOutDeviceConnectionState(in BluetoothDevice device, int state,
+            boolean suppressNoisyIntent);
+
+    void setBluetoothLeAudioInDeviceConnectionState(in BluetoothDevice device, int state);
+
     void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 9657b25e..c7c503d 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2178,12 +2178,6 @@
                 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;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 559a61d..0f9e89a 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -900,7 +900,7 @@
     private @NonNull List<Bitmap> getFramesAtIndexInternal(
             int frameIndex, int numFrames, @Nullable BitmapParams params) {
         if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO))) {
-            throw new IllegalStateException("Does not contail video or image sequences");
+            throw new IllegalStateException("Does not contain video or image sequences");
         }
         int frameCount = Integer.parseInt(
                 extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT));
@@ -1018,7 +1018,7 @@
 
     private Bitmap getImageAtIndexInternal(int imageIndex, @Nullable BitmapParams params) {
         if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE))) {
-            throw new IllegalStateException("Does not contail still images");
+            throw new IllegalStateException("Does not contain still images");
         }
 
         String imageCount = extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_COUNT);
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index cf06fad..813dee3 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -1,9 +1,9 @@
 # Bug component: 1344
-
 fgoldfain@google.com
 elaurent@google.com
 lajos@google.com
-olly@google.com
-andrewlewis@google.com
 sungsoo@google.com
 jmtrivi@google.com
+
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/media/jni/OWNERS b/media/jni/OWNERS
index f1b0237..445672b 100644
--- a/media/jni/OWNERS
+++ b/media/jni/OWNERS
@@ -2,4 +2,4 @@
 per-file android_mtp_*.cpp=marcone@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com
 
 # extra for TV related files
-per-file android_media_tv_*=nchalko@google.com,quxiangfang@google.com
+per-file android_media_tv_*=hgchen@google.com,quxiangfang@google.com
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 0d53ab1..2691983 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-
 #include <stdio.h>
+#include <unordered_set>
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "AudioEffects-JNI"
@@ -58,21 +58,14 @@
 struct effect_callback_cookie {
     jclass      audioEffect_class;  // AudioEffect class
     jobject     audioEffect_ref;    // AudioEffect object instance
- };
-
-// ----------------------------------------------------------------------------
-class AudioEffectJniStorage {
-    public:
-        effect_callback_cookie mCallbackData;
-
-    AudioEffectJniStorage() {
-    }
-
-    ~AudioEffectJniStorage() {
-    }
-
+    bool        busy;
+    Condition   cond;
 };
 
+// ----------------------------------------------------------------------------
+struct AudioEffectJniStorage {
+    effect_callback_cookie mCallbackData{};
+};
 
 jint AudioEffectJni::translateNativeErrorToJava(int code) {
     switch(code) {
@@ -101,6 +94,7 @@
 }
 
 static Mutex sLock;
+static std::unordered_set<effect_callback_cookie*> sAudioEffectCallBackCookies;
 
 // ----------------------------------------------------------------------------
 static void effectCallback(int event, void* user, void *info) {
@@ -121,7 +115,13 @@
         ALOGW("effectCallback error user %p, env %p", user, env);
         return;
     }
-
+    {
+        Mutex::Autolock l(sLock);
+        if (sAudioEffectCallBackCookies.count(callbackInfo) == 0) {
+            return;
+        }
+        callbackInfo->busy = true;
+    }
     ALOGV("effectCallback: callbackInfo %p, audioEffect_ref %p audioEffect_class %p",
             callbackInfo,
             callbackInfo->audioEffect_ref,
@@ -188,6 +188,11 @@
         env->ExceptionDescribe();
         env->ExceptionClear();
     }
+    {
+        Mutex::Autolock l(sLock);
+        callbackInfo->busy = false;
+        callbackInfo->cond.broadcast();
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -396,6 +401,10 @@
         setAudioEffect(env, thiz, lpAudioEffect);
     }
 
+    {
+        Mutex::Autolock l(sLock);
+        sAudioEffectCallBackCookies.insert(&lpJniStorage->mCallbackData);
+    }
     env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
 
     return (jint) AUDIOEFFECT_SUCCESS;
@@ -427,6 +436,7 @@
 
 
 // ----------------------------------------------------------------------------
+#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000
 static void android_media_AudioEffect_native_release(JNIEnv *env,  jobject thiz) {
     sp<AudioEffect> lpAudioEffect = setAudioEffect(env, thiz, 0);
     if (lpAudioEffect == 0) {
@@ -442,7 +452,17 @@
     env->SetLongField(thiz, fields.fidJniData, 0);
 
     if (lpJniStorage) {
-        ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
+        Mutex::Autolock l(sLock);
+        effect_callback_cookie *lpCookie = &lpJniStorage->mCallbackData;
+        ALOGV("deleting lpJniStorage: %p\n", lpJniStorage);
+        sAudioEffectCallBackCookies.erase(lpCookie);
+        while (lpCookie->busy) {
+            if (lpCookie->cond.waitRelative(sLock,
+                                            milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
+                                                    NO_ERROR) {
+                break;
+            }
+        }
         env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_class);
         env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_ref);
         delete lpJniStorage;
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 4c5970a..609fafe 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <stdio.h>
+#include <unordered_set>
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "visualizers-JNI"
@@ -63,6 +64,12 @@
     jclass      visualizer_class;  // Visualizer class
     jobject     visualizer_ref;    // Visualizer object instance
 
+    // 'busy_count' and 'cond' together with 'sLock' are used to serialize
+    // concurrent access to the callback cookie from 'setup'/'release'
+    // and the callback.
+    int         busy_count;
+    Condition   cond;
+
     // Lazily allocated arrays used to hold callback data provided to java
     // applications.  These arrays are allocated during the first callback and
     // reallocated when the size of the callback data changes.  Allocating on
@@ -70,14 +77,12 @@
     // reference to the provided data (they need to make a copy if they want to
     // hold onto outside of the callback scope), but it avoids GC thrash caused
     // by constantly allocating and releasing arrays to hold callback data.
+    // 'callback_data_lock' must never be held at the same time with 'sLock'.
     Mutex       callback_data_lock;
     jbyteArray  waveform_data;
     jbyteArray  fft_data;
 
-    visualizer_callback_cookie() {
-        waveform_data = NULL;
-        fft_data = NULL;
-    }
+    // Assumes use of default initialization by the client.
 
     ~visualizer_callback_cookie() {
         cleanupBuffers();
@@ -102,15 +107,8 @@
  };
 
 // ----------------------------------------------------------------------------
-class VisualizerJniStorage {
-    public:
-        visualizer_callback_cookie mCallbackData;
-
-    VisualizerJniStorage() {
-    }
-
-    ~VisualizerJniStorage() {
-    }
+struct VisualizerJniStorage {
+    visualizer_callback_cookie mCallbackData{};
 };
 
 
@@ -136,6 +134,7 @@
 }
 
 static Mutex sLock;
+static std::unordered_set<visualizer_callback_cookie*> sVisualizerCallBackCookies;
 
 // ----------------------------------------------------------------------------
 static void ensureArraySize(JNIEnv *env, jbyteArray *array, uint32_t size) {
@@ -173,11 +172,19 @@
         return;
     }
 
+    {
+        Mutex::Autolock l(sLock);
+        if (sVisualizerCallBackCookies.count(callbackInfo) == 0) {
+            return;
+        }
+        callbackInfo->busy_count++;
+    }
     ALOGV("captureCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p",
             callbackInfo,
             callbackInfo->visualizer_ref,
             callbackInfo->visualizer_class);
 
+    {
     AutoMutex lock(&callbackInfo->callback_data_lock);
 
     if (waveformSize != 0 && waveform != NULL) {
@@ -219,11 +226,17 @@
                 jArray);
         }
     }
+    }  // callback_data_lock scope
 
     if (env->ExceptionCheck()) {
         env->ExceptionDescribe();
         env->ExceptionClear();
     }
+    {
+        Mutex::Autolock l(sLock);
+        callbackInfo->busy_count--;
+        callbackInfo->cond.broadcast();
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -332,16 +345,41 @@
                                                      void *info) {
     if ((event == AudioEffect::EVENT_ERROR) &&
         (*((status_t*)info) == DEAD_OBJECT)) {
-        VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage*)user;
-        visualizer_callback_cookie* callbackInfo = &lpJniStorage->mCallbackData;
+        visualizer_callback_cookie* callbackInfo =
+                (visualizer_callback_cookie *)user;
         JNIEnv *env = AndroidRuntime::getJNIEnv();
 
+        if (!user || !env) {
+            ALOGW("effectCallback error user %p, env %p", user, env);
+            return;
+        }
+        {
+            Mutex::Autolock l(sLock);
+            if (sVisualizerCallBackCookies.count(callbackInfo) == 0) {
+                return;
+            }
+            callbackInfo->busy_count++;
+        }
+        ALOGV("effectCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p",
+            callbackInfo,
+            callbackInfo->visualizer_ref,
+            callbackInfo->visualizer_class);
+
         env->CallStaticVoidMethod(
             callbackInfo->visualizer_class,
             fields.midPostNativeEvent,
             callbackInfo->visualizer_ref,
             NATIVE_EVENT_SERVER_DIED,
             0, NULL);
+        if (env->ExceptionCheck()) {
+            env->ExceptionDescribe();
+            env->ExceptionClear();
+        }
+        {
+            Mutex::Autolock l(sLock);
+            callbackInfo->busy_count--;
+            callbackInfo->cond.broadcast();
+        }
     }
 }
 
@@ -389,7 +427,7 @@
     }
     lpVisualizer->set(0,
                       android_media_visualizer_effect_callback,
-                      lpJniStorage,
+                      &lpJniStorage->mCallbackData,
                       (audio_session_t) sessionId);
 
     lStatus = translateError(lpVisualizer->initCheck());
@@ -410,6 +448,10 @@
 
     setVisualizer(env, thiz, lpVisualizer);
 
+    {
+        Mutex::Autolock l(sLock);
+        sVisualizerCallBackCookies.insert(&lpJniStorage->mCallbackData);
+    }
     env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
 
     return VISUALIZER_SUCCESS;
@@ -432,13 +474,15 @@
 }
 
 // ----------------------------------------------------------------------------
+#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000
 static void android_media_visualizer_native_release(JNIEnv *env,  jobject thiz) {
-    { //limit scope so that lpVisualizer is deleted before JNI storage data.
+    {
         sp<Visualizer> lpVisualizer = setVisualizer(env, thiz, 0);
         if (lpVisualizer == 0) {
             return;
         }
         lpVisualizer->release();
+        // Visualizer can still can be held by AudioEffect::EffectClient
     }
     // delete the JNI data
     VisualizerJniStorage* lpJniStorage =
@@ -449,9 +493,22 @@
     env->SetLongField(thiz, fields.fidJniData, 0);
 
     if (lpJniStorage) {
+        {
+        Mutex::Autolock l(sLock);
+        visualizer_callback_cookie *lpCookie = &lpJniStorage->mCallbackData;
         ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
+        sVisualizerCallBackCookies.erase(lpCookie);
+        while (lpCookie->busy_count > 0) {
+            if (lpCookie->cond.waitRelative(sLock,
+                                            milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
+                                                    NO_ERROR) {
+                break;
+            }
+        }
+        ALOG_ASSERT(lpCookie->busy_count == 0, "Unbalanced busy_count inc/dec");
         env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class);
         env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref);
+        }  // sLock scope
         delete lpJniStorage;
     }
 }
@@ -707,4 +764,3 @@
 {
     return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
 }
-
diff --git a/media/tests/EffectsTest/AndroidManifest.xml b/media/tests/EffectsTest/AndroidManifest.xml
index 9b59891..ad0c10e 100644
--- a/media/tests/EffectsTest/AndroidManifest.xml
+++ b/media/tests/EffectsTest/AndroidManifest.xml
@@ -13,6 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+<!--
+Make sure to enable access to the mic in settings and run:
+adb shell am compat enable ALLOW_TEST_API_ACCESS com.android.effectstest
+-->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.effectstest">
diff --git a/media/tests/EffectsTest/res/layout/bassboosttest.xml b/media/tests/EffectsTest/res/layout/bassboosttest.xml
index ac912c8..5f9132c 100644
--- a/media/tests/EffectsTest/res/layout/bassboosttest.xml
+++ b/media/tests/EffectsTest/res/layout/bassboosttest.xml
@@ -187,6 +187,11 @@
                  android:layout_height="wrap_content"
                  android:scaleType="fitXY"/>
 
+            <Button android:id="@+id/hammer_on_release_bug"
+                    android:layout_width="fill_parent" android:layout_height="wrap_content"
+                    android:text="@string/hammer_on_release_bug_name">
+            </Button>
+
         </LinearLayout>
 
     </ScrollView>
diff --git a/media/tests/EffectsTest/res/layout/visualizertest.xml b/media/tests/EffectsTest/res/layout/visualizertest.xml
index 18d7a36..85dabbc 100644
--- a/media/tests/EffectsTest/res/layout/visualizertest.xml
+++ b/media/tests/EffectsTest/res/layout/visualizertest.xml
@@ -175,6 +175,11 @@
 
     </LinearLayout>
 
+    <Button android:id="@+id/hammer_on_release_bug"
+            android:layout_width="fill_parent" android:layout_height="wrap_content"
+            android:text="@string/hammer_on_release_bug_name">
+    </Button>
+
     <ImageView
          android:src="@android:drawable/divider_horizontal_dark"
          android:layout_width="fill_parent"
diff --git a/media/tests/EffectsTest/res/values/strings.xml b/media/tests/EffectsTest/res/values/strings.xml
index 7c12da1..a44c7e9 100644
--- a/media/tests/EffectsTest/res/values/strings.xml
+++ b/media/tests/EffectsTest/res/values/strings.xml
@@ -37,4 +37,6 @@
     <string name="send_level_name">Send Level</string>
     <!-- Toggles use of a multi-threaded client for an effect [CHAR LIMIT=24] -->
     <string name="effect_multithreaded">Multithreaded Use</string>
+    <!-- Runs a stress test for a bug related to simultaneous release of multiple effect instances [CHAR LIMIT=24] -->
+    <string name="hammer_on_release_bug_name">Hammer on release()</string>
 </resources>
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
index cce2acc..a207bf1 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
@@ -17,29 +17,24 @@
 package com.android.effectstest;
 
 import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
+import android.media.audiofx.AudioEffect;
+import android.media.audiofx.BassBoost;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.View.OnClickListener;
 import android.view.View;
-import android.view.ViewGroup;
+import android.view.View.OnClickListener;
 import android.widget.Button;
-import android.widget.TextView;
-import android.widget.EditText;
-import android.widget.SeekBar;
-import android.widget.ToggleButton;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
-import java.nio.ByteOrder;
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.Map;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.ToggleButton;
 
-import android.media.audiofx.BassBoost;
-import android.media.audiofx.AudioEffect;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
 
 public class BassBoostTest extends Activity implements OnCheckedChangeListener {
 
@@ -78,6 +73,9 @@
         mReleaseButton = (ToggleButton)findViewById(R.id.bbReleaseButton);
         mOnOffButton = (ToggleButton)findViewById(R.id.bassboostOnOff);
 
+        final Button hammerReleaseTest = (Button) findViewById(R.id.hammer_on_release_bug);
+        hammerReleaseTest.setEnabled(false);
+
         getEffect(sSession);
 
         if (mBassBoost != null) {
@@ -93,6 +91,14 @@
             mStrength = new BassBoostParam(mBassBoost, 0, 1000, seekBar, textView);
             seekBar.setOnSeekBarChangeListener(mStrength);
             mStrength.setEnabled(mBassBoost.getStrengthSupported());
+
+            hammerReleaseTest.setEnabled(true);
+            hammerReleaseTest.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    runHammerReleaseTest(hammerReleaseTest);
+                }
+            });
         }
     }
 
@@ -273,4 +279,52 @@
         }
     }
 
+    // Stress-tests releasing of AudioEffect by doing repeated creation
+    // and subsequent releasing. Also forces emission of callbacks from
+    // the AudioFlinger by setting a control status listener. Since all
+    // effect instances are bound to the same session, the AF will
+    // notify them about the change in their status. This can reveal racy
+    // behavior w.r.t. releasing.
+    class HammerReleaseTest extends Thread {
+        private static final int NUM_EFFECTS = 10;
+        private static final int NUM_ITERATIONS = 100;
+        private final int mSession;
+        private final Runnable mOnComplete;
+
+        HammerReleaseTest(int session, Runnable onComplete) {
+            mSession = session;
+            mOnComplete = onComplete;
+        }
+
+        @Override
+        public void run() {
+            Log.w(TAG, "HammerReleaseTest started");
+            BassBoost[] effects = new BassBoost[NUM_EFFECTS];
+            for (int i = 0; i < NUM_ITERATIONS; i++) {
+                for (int j = 0; j < NUM_EFFECTS; j++) {
+                    effects[j] = new BassBoost(0, mSession);
+                    effects[j].setControlStatusListener(mEffectListener);
+                    yield();
+                }
+                for (int j = NUM_EFFECTS - 1; j >= 0; j--) {
+                    Log.w(TAG, "HammerReleaseTest releasing effect " + (Object) effects[j]);
+                    effects[j].release();
+                    effects[j] = null;
+                    yield();
+                }
+            }
+            Log.w(TAG, "HammerReleaseTest ended");
+            runOnUiThread(mOnComplete);
+        }
+    }
+
+    private void runHammerReleaseTest(Button controlButton) {
+        controlButton.setEnabled(false);
+        HammerReleaseTest thread = new HammerReleaseTest(sSession,
+                () -> {
+                    controlButton.setEnabled(true);
+                });
+        thread.start();
+    }
+
 }
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
index 2e141c5..dcfe11a 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
@@ -17,6 +17,7 @@
 package com.android.effectstest;
 
 import android.app.Activity;
+import android.media.audiofx.Visualizer;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -24,6 +25,8 @@
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.EditText;
@@ -74,11 +77,22 @@
         mCallbackOn = false;
         mCallbackButton.setChecked(mCallbackOn);
 
+        final Button hammerReleaseTest = (Button) findViewById(R.id.hammer_on_release_bug);
+        hammerReleaseTest.setEnabled(false);
+
         mMultithreadedButton.setOnCheckedChangeListener(this);
         if (getEffect(sSession) != null) {
             mReleaseButton.setOnCheckedChangeListener(this);
             mOnOffButton.setOnCheckedChangeListener(this);
             mCallbackButton.setOnCheckedChangeListener(this);
+
+            hammerReleaseTest.setEnabled(true);
+            hammerReleaseTest.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    runHammerReleaseTest(hammerReleaseTest);
+                }
+            });
         }
     }
 
@@ -214,4 +228,50 @@
         }
     }
 
+    // Stress-tests releasing of AudioEffect by doing repeated creation
+    // and subsequent releasing. Unlike a similar class in BassBoostTest,
+    // this one doesn't sets a control status listener because Visualizer
+    // doesn't inherit from AudioEffect and doesn't implement this method
+    // by itself.
+    class HammerReleaseTest extends Thread {
+        private static final int NUM_EFFECTS = 10;
+        private static final int NUM_ITERATIONS = 100;
+        private final int mSession;
+        private final Runnable mOnComplete;
+
+        HammerReleaseTest(int session, Runnable onComplete) {
+            mSession = session;
+            mOnComplete = onComplete;
+        }
+
+        @Override
+        public void run() {
+            Log.w(TAG, "HammerReleaseTest started");
+            Visualizer[] effects = new Visualizer[NUM_EFFECTS];
+            for (int i = 0; i < NUM_ITERATIONS; i++) {
+                for (int j = 0; j < NUM_EFFECTS; j++) {
+                    effects[j] = new Visualizer(mSession);
+                    yield();
+                }
+                for (int j = NUM_EFFECTS - 1; j >= 0; j--) {
+                    Log.w(TAG, "HammerReleaseTest releasing effect " + (Object) effects[j]);
+                    effects[j].release();
+                    effects[j] = null;
+                    yield();
+                }
+            }
+            Log.w(TAG, "HammerReleaseTest ended");
+            runOnUiThread(mOnComplete);
+        }
+    }
+
+    private void runHammerReleaseTest(Button controlButton) {
+        controlButton.setEnabled(false);
+        HammerReleaseTest thread = new HammerReleaseTest(sSession,
+                () -> {
+                    controlButton.setEnabled(true);
+                });
+        thread.start();
+    }
+
 }
diff --git a/mms/OWNERS b/mms/OWNERS
index befc320..7f05a2a 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -2,7 +2,6 @@
 
 tgunn@google.com
 breadley@google.com
-hallliu@google.com
 rgreenwalt@google.com
 amitmahajan@google.com
 fionaxu@google.com
@@ -10,7 +9,10 @@
 jminjie@google.com
 satk@google.com
 shuoq@google.com
-refuhoo@google.com
 nazaninb@google.com
 sarahchin@google.com
-dbright@google.com
\ No newline at end of file
+xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index 5668840..0d23f05 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -1,7 +1,6 @@
 set noparent
 tgunn@google.com
 breadley@google.com
-hallliu@google.com
 rgreenwalt@google.com
 amitmahajan@google.com
 fionaxu@google.com
@@ -9,9 +8,11 @@
 jminjie@google.com
 satk@google.com
 shuoq@google.com
-refuhoo@google.com
 nazaninb@google.com
 sarahchin@google.com
-dbright@google.com
 xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
 
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index b4d520d..1bc4983 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -33,6 +33,10 @@
             <intent-filter>
                 <action android:name="android.os.image.action.START_INSTALL" />
                 <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="content" />
+                <data android:scheme="file" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
             </intent-filter>
         </activity>
 
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 11d1b0a..087275e 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -322,6 +322,11 @@
                 return true;
             }
 
+            if (TextUtils.equals(Environment.DIRECTORY_ANDROID.toLowerCase(),
+                    path.toLowerCase())) {
+                return true;
+            }
+
             return false;
         } catch (IOException e) {
             throw new IllegalArgumentException(
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 59d8acb..70baf1d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
@@ -125,6 +126,9 @@
         addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
         addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
 
+        addHandler(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE,
+                new SetMemberAvailableHandler());
+
         registerAdapterIntentReceiver();
     }
 
@@ -293,6 +297,8 @@
                 BluetoothDevice device) {
             short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
             String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
+            final boolean isCoordinatedSetMember =
+                    intent.getBooleanExtra(BluetoothDevice.EXTRA_IS_COORDINATED_SET_MEMBER, false);
             // TODO Pick up UUID. They should be available for 2.1 devices.
             // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
             CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
@@ -307,6 +313,7 @@
             }
             cachedDevice.setRssi(rssi);
             cachedDevice.setJustDiscovered(true);
+            cachedDevice.setIsCoordinatedSetMember(isCoordinatedSetMember);
         }
     }
 
@@ -335,6 +342,12 @@
             }
             int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                     BluetoothDevice.ERROR);
+
+            if (mDeviceManager.onBondStateChangedIfProcess(device, bondState)) {
+                Log.d(TAG, "Should not update UI for the set member");
+                return;
+            }
+
             CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
             if (cachedDevice == null) {
                 Log.w(TAG, "Got bonding state changed for " + device +
@@ -348,8 +361,10 @@
             cachedDevice.onBondingStateChanged(bondState);
 
             if (bondState == BluetoothDevice.BOND_NONE) {
-                /* Check if we need to remove other Hearing Aid devices */
-                if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+                // Check if we need to remove other Coordinated set member devices / Hearing Aid
+                // devices
+                if (cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
+                        || cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
                     mDeviceManager.onDeviceUnpaired(cachedDevice);
                 }
                 int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
@@ -496,4 +511,29 @@
             dispatchAudioModeChanged();
         }
     }
+
+    private class SetMemberAvailableHandler implements Handler {
+        @Override
+        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+            final String action = intent.getAction();
+            if (device == null) {
+                Log.e(TAG, "SetMemberAvailableHandler: device is null");
+                return;
+            }
+
+            if (action == null) {
+                Log.e(TAG, "SetMemberAvailableHandler: action is null");
+                return;
+            }
+
+            final int groupId = intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID,
+                    BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+            if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+                Log.e(TAG, "SetMemberAvailableHandler: Invalid group id");
+                return;
+            }
+
+            mDeviceManager.onSetMemberAppear(device, groupId);
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 4c80b91..78fc139 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
@@ -41,7 +42,9 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -66,6 +69,7 @@
     private final Object mProfileLock = new Object();
     BluetoothDevice mDevice;
     private long mHiSyncId;
+    private int mGroupId;
     // Need this since there is no method for getting RSSI
     short mRssi;
     // mProfiles and mRemovedProfiles does not do swap() between main and sub device. It is
@@ -80,6 +84,8 @@
 
     boolean mJustDiscovered;
 
+    boolean mIsCoordinatedSetMember = false;
+
     private final Collection<Callback> mCallbacks = new CopyOnWriteArrayList<>();
 
     /**
@@ -98,6 +104,8 @@
     private boolean mIsA2dpProfileConnectedFail = false;
     private boolean mIsHeadsetProfileConnectedFail = false;
     private boolean mIsHearingAidProfileConnectedFail = false;
+    // Group member devices for the coordinated set
+    private Set<CachedBluetoothDevice> mMemberDevices = new HashSet<CachedBluetoothDevice>();
     // Group second device for Hearing Aid
     private CachedBluetoothDevice mSubDevice;
 
@@ -131,6 +139,7 @@
         mDevice = device;
         fillData();
         mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
+        mGroupId = BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
     }
 
     /**
@@ -297,6 +306,42 @@
         return mHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
     }
 
+    /**
+     * Mark the discovered device as member of coordinated set.
+     *
+     * @param isCoordinatedSetMember {@code true}, if the device is a member of a coordinated set.
+     */
+    public void setIsCoordinatedSetMember(boolean isCoordinatedSetMember) {
+        mIsCoordinatedSetMember = isCoordinatedSetMember;
+    }
+
+    /**
+     * Check if the device is a CSIP member device.
+     *
+     * @return {@code true}, if this device supports CSIP, otherwise returns {@code false}.
+     */
+    public boolean isCoordinatedSetMemberDevice() {
+        return mIsCoordinatedSetMember;
+    }
+
+    /**
+    * Get the coordinated set group id.
+    *
+    * @return the group id.
+    */
+    public int getGroupId() {
+        return mGroupId;
+    }
+
+    /**
+    * Set the coordinated set group id.
+    *
+    * @param id the group id from the CSIP.
+    */
+    public void setGroupId(int id) {
+        mGroupId = id;
+    }
+
     void onBondingDockConnect() {
         // Attempt to connect if UUIDs are available. Otherwise,
         // we will connect when the ACTION_UUID intent arrives.
@@ -1171,4 +1216,52 @@
         mSubDevice.mJustDiscovered = tmpJustDiscovered;
         fetchActiveDevices();
     }
+
+    /**
+     * @return a set of member devices that are in the same coordinated set with this device.
+     */
+    public Set<CachedBluetoothDevice> getMemberDevice() {
+        return mMemberDevices;
+    }
+
+    /**
+     * Store the member devices that are in the same coordinated set.
+     */
+    public void setMemberDevice(CachedBluetoothDevice memberDevice) {
+        mMemberDevices.add(memberDevice);
+    }
+
+    /**
+     * Remove a device from the member device sets.
+     */
+    public void removeMemberDevice(CachedBluetoothDevice memberDevice) {
+        mMemberDevices.remove(memberDevice);
+    }
+
+    /**
+     * In order to show the preference for the whole group, we always set the main device as the
+     * first connected device in the coordinated set, and then switch the content of the main
+     * device and member devices.
+     *
+     * @param prevMainDevice the previous Main device, it will be added into the member device set.
+     * @param newMainDevie the new Main device, it will be removed from the member device set.
+     */
+    public void switchMemberDeviceContent(CachedBluetoothDevice prevMainDevice,
+            CachedBluetoothDevice newMainDevie) {
+        // Backup from main device
+        final BluetoothDevice tmpDevice = mDevice;
+        final short tmpRssi = mRssi;
+        final boolean tmpJustDiscovered = mJustDiscovered;
+        // Set main device from sub device
+        mDevice = newMainDevie.mDevice;
+        mRssi = newMainDevie.mRssi;
+        mJustDiscovered = newMainDevie.mJustDiscovered;
+        setMemberDevice(prevMainDevice);
+        mMemberDevices.remove(newMainDevie);
+        // Set sub device from backup
+        newMainDevie.mDevice = tmpDevice;
+        newMainDevie.mRssi = tmpRssi;
+        newMainDevie.mJustDiscovered = tmpJustDiscovered;
+        fetchActiveDevices();
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index cca9cfa..0256615 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -18,6 +18,7 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.util.Log;
 
@@ -26,6 +27,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
@@ -41,11 +43,15 @@
     final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
     @VisibleForTesting
     HearingAidDeviceManager mHearingAidDeviceManager;
+    @VisibleForTesting
+    CsipDeviceManager mCsipDeviceManager;
+    BluetoothDevice mOngoingSetMemberPair;
 
     CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
         mContext = context;
         mBtManager = localBtManager;
         mHearingAidDeviceManager = new HearingAidDeviceManager(localBtManager, mCachedDevices);
+        mCsipDeviceManager = new CsipDeviceManager(localBtManager, mCachedDevices);
     }
 
     public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
@@ -79,7 +85,16 @@
             if (cachedDevice.getDevice().equals(device)) {
                 return cachedDevice;
             }
-            // Check sub devices if it exists
+            // Check the member devices for the coordinated set if it exists
+            final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
+            if (memberDevices != null) {
+                for (CachedBluetoothDevice memberDevice : memberDevices) {
+                    if (memberDevice.getDevice().equals(device)) {
+                        return memberDevice;
+                    }
+                }
+            }
+            // Check sub devices for hearing aid if it exists
             CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
             if (subDevice != null && subDevice.getDevice().equals(device)) {
                 return subDevice;
@@ -102,8 +117,10 @@
             newDevice = findDevice(device);
             if (newDevice == null) {
                 newDevice = new CachedBluetoothDevice(mContext, profileManager, device);
+                mCsipDeviceManager.initCsipDeviceIfNeeded(newDevice);
                 mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(newDevice);
-                if (!mHearingAidDeviceManager.setSubDeviceIfNeeded(newDevice)) {
+                if (!mCsipDeviceManager.setMemberDeviceIfNeeded(newDevice)
+                        && !mHearingAidDeviceManager.setSubDeviceIfNeeded(newDevice)) {
                     mCachedDevices.add(newDevice);
                     mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
                 }
@@ -114,13 +131,23 @@
     }
 
     /**
-     * Returns device summary of the pair of the hearing aid passed as the parameter.
+     * Returns device summary of the pair of the hearing aid / CSIP passed as the parameter.
      *
      * @param CachedBluetoothDevice device
-     * @return Device summary, or if the pair does not exist or if it is not a hearing aid,
-     * then {@code null}.
+     * @return Device summary, or if the pair does not exist or if it is not a hearing aid or
+     * a CSIP set member, then {@code null}.
      */
     public synchronized String getSubDeviceSummary(CachedBluetoothDevice device) {
+        final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice();
+        if (memberDevices != null) {
+            for (CachedBluetoothDevice memberDevice : memberDevices) {
+                if (!memberDevice.isConnected()) {
+                    return null;
+                }
+            }
+
+            return device.getConnectionSummary();
+        }
         CachedBluetoothDevice subDevice = device.getSubDevice();
         if (subDevice != null && subDevice.isConnected()) {
             return subDevice.getConnectionSummary();
@@ -132,12 +159,22 @@
      * Search for existing sub device {@link CachedBluetoothDevice}.
      *
      * @param device the address of the Bluetooth device
-     * @return true for found sub device or false.
+     * @return true for found sub / member device or false.
      */
     public synchronized boolean isSubDevice(BluetoothDevice device) {
         for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
             if (!cachedDevice.getDevice().equals(device)) {
-                // Check sub devices if it exists
+                // Check the member devices of the coordinated set if it exists
+                Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
+                if (memberDevices != null) {
+                    for (CachedBluetoothDevice memberDevice : memberDevices) {
+                        if (memberDevice.getDevice().equals(device)) {
+                            return true;
+                        }
+                    }
+                    continue;
+                }
+                // Check sub devices of hearing aid if it exists
                 CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
                 if (subDevice != null && subDevice.getDevice().equals(device)) {
                     return true;
@@ -157,6 +194,14 @@
     }
 
     /**
+     * Updates the Csip devices; specifically the GroupId's. This routine is called when the
+     * CSIS is connected and the GroupId's are now available.
+     */
+    public synchronized void updateCsipDevices() {
+        mCsipDeviceManager.updateCsipDevices();
+    }
+
+    /**
      * Attempts to get the name of a remote device, otherwise returns the address.
      *
      * @param device The remote device.
@@ -185,6 +230,16 @@
     private void clearNonBondedSubDevices() {
         for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
             CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+            final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
+            if (memberDevices != null) {
+                for (CachedBluetoothDevice memberDevice : memberDevices) {
+                    // Member device exists and it is not bonded
+                    if (memberDevice.getDevice().getBondState() == BluetoothDevice.BOND_NONE) {
+                        cachedDevice.removeMemberDevice(memberDevice);
+                    }
+                }
+                return;
+            }
             CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
             if (subDevice != null
                     && subDevice.getDevice().getBondState() == BluetoothDevice.BOND_NONE) {
@@ -201,6 +256,13 @@
         for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
             CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
             cachedDevice.setJustDiscovered(false);
+            final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
+            if (memberDevices != null) {
+                for (CachedBluetoothDevice memberDevice : memberDevices) {
+                    memberDevice.setJustDiscovered(false);
+                }
+                return;
+            }
             final CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
             if (subDevice != null) {
                 subDevice.setJustDiscovered(false);
@@ -214,10 +276,19 @@
         if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
             for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
                 CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
-                CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
-                if (subDevice != null) {
-                    if (subDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
-                        cachedDevice.setSubDevice(null);
+                final Set<CachedBluetoothDevice> memberDevices = cachedDevice.getMemberDevice();
+                if (memberDevices != null) {
+                    for (CachedBluetoothDevice memberDevice : memberDevices) {
+                        if (memberDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
+                            cachedDevice.removeMemberDevice(memberDevice);
+                        }
+                    }
+                } else {
+                    CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+                    if (subDevice != null) {
+                        if (subDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
+                            cachedDevice.setSubDevice(null);
+                        }
                     }
                 }
                 if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
@@ -229,13 +300,32 @@
     }
 
     public synchronized boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice
-            cachedDevice, int state) {
-        return mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
+            cachedDevice, int state, int profileId) {
+        if (profileId == BluetoothProfile.HEARING_AID) {
+            return mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
                 state);
+        }
+        if (profileId == BluetoothProfile.CSIP_SET_COORDINATOR) {
+            return mCsipDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
+                state);
+        }
+        return false;
     }
 
     public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
-        CachedBluetoothDevice mainDevice = mHearingAidDeviceManager.findMainDevice(device);
+        CachedBluetoothDevice mainDevice = mCsipDeviceManager.findMainDevice(device);
+        final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice();
+        if (memberDevices != null) {
+            // Main device is unpaired, to unpair the member device
+            for (CachedBluetoothDevice memberDevice : memberDevices) {
+                memberDevice.unpair();
+                device.removeMemberDevice(memberDevice);
+            }
+        } else if (mainDevice != null) {
+            // the member device unpaired, to unpair main device
+            mainDevice.unpair();
+        }
+        mainDevice = mHearingAidDeviceManager.findMainDevice(device);
         CachedBluetoothDevice subDevice = device.getSubDevice();
         if (subDevice != null) {
             // Main device is unpaired, to unpair sub device
@@ -248,6 +338,74 @@
         }
     }
 
+    /**
+     * Called when we found a set member of a group. The function will check the {@code groupId} if
+     * it exists and if there is a ongoing pair, the device would be ignored.
+     *
+     * @param device The found device
+     * @param groupId The group id of the found device
+     */
+    public synchronized void onSetMemberAppear(BluetoothDevice device, int groupId) {
+        Log.d(TAG, "onSetMemberAppear, groupId: " + groupId + " device: " + device.toString());
+
+        if (mOngoingSetMemberPair != null) {
+            Log.d(TAG, "Ongoing set memberPairing in process, drop it!");
+            return;
+        }
+
+        if (mCsipDeviceManager.onSetMemberAppear(device, groupId)) {
+            mOngoingSetMemberPair = device;
+        }
+    }
+
+    /**
+     * Called when the bond state change. If the bond state change is related with the
+     * ongoing set member pair, the cachedBluetoothDevice will be created but the UI
+     * would not be updated. For the other case, return {@code false} to go through the normal
+     * flow.
+     *
+     * @param device The device
+     * @param bondState The new bond state
+     *
+     * @return {@code true}, if the bond state change for the device is handled inside this
+     * function, and would not like to update the UI. If not, return {@code false}.
+     */
+    public synchronized boolean onBondStateChangedIfProcess(BluetoothDevice device, int bondState) {
+        if (mOngoingSetMemberPair == null || !mOngoingSetMemberPair.equals(device)) {
+            return false;
+        }
+
+        if (bondState == BluetoothDevice.BOND_BONDING) {
+            return true;
+        }
+
+        mOngoingSetMemberPair = null;
+        if (bondState != BluetoothDevice.BOND_NONE) {
+            if (findDevice(device) == null) {
+                final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+                CachedBluetoothDevice newDevice =
+                        new CachedBluetoothDevice(mContext, profileManager, device);
+                mCachedDevices.add(newDevice);
+                findDevice(device).connect();
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the device is the one which is initial paired locally by CSIP. The setting
+     * would depned on it to accept the pairing request automatically
+     *
+     * @param device The device
+     *
+     * @return {@code true}, if the device is ongoing pair by CSIP. Otherwise, return
+     * {@code false}.
+     */
+    public boolean isOngoingPairByCsip(BluetoothDevice device) {
+        return !(mOngoingSetMemberPair == null) && mOngoingSetMemberPair.equals(device);
+    }
+
     private void log(String msg) {
         if (DEBUG) {
             Log.d(TAG, msg);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
new file mode 100644
index 0000000..347e14b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * CsipDeviceManager manages the set of remote CSIP Bluetooth devices.
+ */
+public class CsipDeviceManager {
+    private static final String TAG = "CsipDeviceManager";
+    private static final boolean DEBUG = BluetoothUtils.D;
+
+    private final LocalBluetoothManager mBtManager;
+    private final List<CachedBluetoothDevice> mCachedDevices;
+
+    CsipDeviceManager(LocalBluetoothManager localBtManager,
+            List<CachedBluetoothDevice> cachedDevices) {
+        mBtManager = localBtManager;
+        mCachedDevices = cachedDevices;
+    };
+
+    void initCsipDeviceIfNeeded(CachedBluetoothDevice newDevice) {
+        // Current it only supports the base uuid for CSIP and group this set in UI.
+        final int groupId = getBaseGroupId(newDevice.getDevice());
+        if (isValidGroupId(groupId)) {
+            log("initCsipDeviceIfNeeded: " + newDevice + " (group: " + groupId + ")");
+            // Once groupId is valid, assign groupId
+            newDevice.setGroupId(groupId);
+        }
+    }
+
+    private int getBaseGroupId(BluetoothDevice device) {
+        final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+        final CsipSetCoordinatorProfile profileProxy = profileManager
+                .getCsipSetCoordinatorProfile();
+        if (profileProxy != null) {
+            final Map<Integer, ParcelUuid> groupIdMap = profileProxy
+                    .getGroupUuidMapByDevice(device);
+            if (groupIdMap == null) {
+                return BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
+            }
+
+            for (Map.Entry<Integer, ParcelUuid> entry: groupIdMap.entrySet()) {
+                if (entry.getValue().equals(BluetoothUuid.BASE_UUID)) {
+                    return entry.getKey();
+                }
+            }
+        }
+        return BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
+    }
+
+    boolean setMemberDeviceIfNeeded(CachedBluetoothDevice newDevice) {
+        final int groupId = newDevice.getGroupId();
+        if (isValidGroupId(groupId)) {
+            final CachedBluetoothDevice CsipDevice = getCachedDevice(groupId);
+            log("setMemberDeviceIfNeeded, main: " + CsipDevice + ", member: " + newDevice);
+            // Just add one of the coordinated set from a pair in the list that is shown in the UI.
+            // Once there is other devices with the same groupId, to add new device as member
+            // devices.
+            if (CsipDevice != null) {
+                CsipDevice.setMemberDevice(newDevice);
+                newDevice.setName(CsipDevice.getName());
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isValidGroupId(int groupId) {
+        return groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID;
+    }
+
+    private CachedBluetoothDevice getCachedDevice(int groupId) {
+        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+            if (cachedDevice.getGroupId() == groupId) {
+                return cachedDevice;
+            }
+        }
+        return null;
+    }
+
+    // To collect all set member devices and call #onGroupIdChanged to group device by GroupId
+    void updateCsipDevices() {
+        final Set<Integer> newGroupIdSet = new HashSet<Integer>();
+        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+            // Do nothing if GroupId has been assigned
+            if (!isValidGroupId(cachedDevice.getGroupId())) {
+                final int newGroupId = getBaseGroupId(cachedDevice.getDevice());
+                // Do nothing if there is no GroupId on Bluetooth device
+                if (isValidGroupId(newGroupId)) {
+                    cachedDevice.setGroupId(newGroupId);
+                    newGroupIdSet.add(newGroupId);
+                }
+            }
+        }
+        for (int groupId : newGroupIdSet) {
+            onGroupIdChanged(groupId);
+        }
+    }
+
+    // Group devices by groupId
+    @VisibleForTesting
+    void onGroupIdChanged(int groupId) {
+        int firstMatchedIndex = -1;
+        CachedBluetoothDevice mainDevice = null;
+
+        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+            final CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+            if (cachedDevice.getGroupId() != groupId) {
+                continue;
+            }
+
+            if (firstMatchedIndex == -1) {
+                // Found the first one
+                firstMatchedIndex = i;
+                mainDevice = cachedDevice;
+                continue;
+            }
+
+            log("onGroupIdChanged: removed from UI device =" + cachedDevice
+                    + ", with groupId=" + groupId + " firstMatchedIndex=" + firstMatchedIndex);
+
+            mainDevice.setMemberDevice(cachedDevice);
+            mCachedDevices.remove(i);
+            mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+            break;
+        }
+    }
+
+    // @return {@code true}, the event is processed inside the method. It is for updating
+    // le audio device on group relationship when receiving connected or disconnected.
+    // @return {@code false}, it is not le audio device or to process it same as other profiles
+    boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice cachedDevice,
+            int state) {
+        log("onProfileConnectionStateChangedIfProcessed: " + cachedDevice + ", state: " + state);
+        switch (state) {
+            case BluetoothProfile.STATE_CONNECTED:
+                onGroupIdChanged(cachedDevice.getGroupId());
+                CachedBluetoothDevice mainDevice = findMainDevice(cachedDevice);
+                if (mainDevice != null) {
+                    if (mainDevice.isConnected()) {
+                        // When main device exists and in connected state, receiving member device
+                        // connection. To refresh main device UI
+                        mainDevice.refresh();
+                        return true;
+                    } else {
+                        // When both LE Audio devices are disconnected, receiving member device
+                        // connection. To switch content and dispatch to notify UI change
+                        mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice);
+                        mainDevice.switchMemberDeviceContent(mainDevice, cachedDevice);
+                        mainDevice.refresh();
+                        // It is necessary to do remove and add for updating the mapping on
+                        // preference and device
+                        mBtManager.getEventManager().dispatchDeviceAdded(mainDevice);
+                        return true;
+                    }
+                }
+                break;
+            case BluetoothProfile.STATE_DISCONNECTED:
+                mainDevice = findMainDevice(cachedDevice);
+                if (mainDevice != null) {
+                    // When main device exists, receiving sub device disconnection
+                    // To update main device UI
+                    mainDevice.refresh();
+                    return true;
+                }
+                final Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice();
+                if (memberSet == null) {
+                    break;
+                }
+
+                for (CachedBluetoothDevice device: memberSet) {
+                    if (device.isConnected()) {
+                        // Main device is disconnected and sub device is connected
+                        // To copy data from sub device to main device
+                        mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+                        cachedDevice.switchMemberDeviceContent(device, cachedDevice);
+                        cachedDevice.refresh();
+                        // It is necessary to do remove and add for updating the mapping on
+                        // preference and device
+                        mBtManager.getEventManager().dispatchDeviceAdded(cachedDevice);
+                        return true;
+                    }
+                }
+                break;
+            default:
+                // Do not handle this state.
+        }
+        return false;
+    }
+
+    CachedBluetoothDevice findMainDevice(CachedBluetoothDevice device) {
+        if (device == null || mCachedDevices == null) {
+            return null;
+        }
+
+        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+            if (isValidGroupId(cachedDevice.getGroupId())) {
+                Set<CachedBluetoothDevice> memberSet = cachedDevice.getMemberDevice();
+                if (memberSet == null) {
+                    continue;
+                }
+
+                for (CachedBluetoothDevice memberDevice: memberSet) {
+                    if (memberDevice != null && memberDevice.equals(device)) {
+                        return cachedDevice;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Called when we found a set member of a group. The function will check bond state, and
+     * the {@code groupId} if it exists, and then create the bond.
+     *
+     * @param device The found device
+     * @param groupId The group id of the found device
+     *
+     * @return {@code true}, if the we create bond with the device. Otherwise, return
+     * {@code false}.
+     */
+    public boolean onSetMemberAppear(BluetoothDevice device, int groupId) {
+        if (device.getBondState() != BluetoothDevice.BOND_NONE) {
+            return false;
+        }
+
+        if (getCachedDevice(groupId) != null) {
+            device.createBond(BluetoothDevice.TRANSPORT_LE);
+            return true;
+        }
+
+        return false;
+    }
+
+    private void log(String msg) {
+        if (DEBUG) {
+            Log.d(TAG, msg);
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipSetCoordinatorProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipSetCoordinatorProfile.java
new file mode 100644
index 0000000..6da249c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipSetCoordinatorProfile.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2021 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.bluetooth;
+
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCsipSetCoordinator;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CSIP Set Coordinator handles Bluetooth CSIP Set Coordinator role profile.
+ */
+public class CsipSetCoordinatorProfile implements LocalBluetoothProfile {
+    private static final String TAG = "CsipSetCoordinatorProfile";
+    private static final boolean VDBG = true;
+
+    private Context mContext;
+
+    private BluetoothCsipSetCoordinator mService;
+    private boolean mIsProfileReady;
+
+    private final CachedBluetoothDeviceManager mDeviceManager;
+
+    static final String NAME = "CSIP Set Coordinator";
+    private final LocalBluetoothProfileManager mProfileManager;
+
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 1;
+
+    // These callbacks run on the main thread.
+    private final class CoordinatedSetServiceListener implements BluetoothProfile.ServiceListener {
+        @RequiresApi(32)
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            if (VDBG) {
+                Log.d(TAG, "Bluetooth service connected");
+            }
+            mService = (BluetoothCsipSetCoordinator) proxy;
+            // We just bound to the service, so refresh the UI for any connected CSIP devices.
+            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+            while (!deviceList.isEmpty()) {
+                BluetoothDevice nextDevice = deviceList.remove(0);
+                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+                // we may add a new device here, but generally this should not happen
+                if (device == null) {
+                    if (VDBG) {
+                        Log.d(TAG, "CsipSetCoordinatorProfile found new device: " + nextDevice);
+                    }
+                    device = mDeviceManager.addDevice(nextDevice);
+                }
+                device.onProfileStateChanged(
+                        CsipSetCoordinatorProfile.this, BluetoothProfile.STATE_CONNECTED);
+                device.refresh();
+            }
+
+            mDeviceManager.updateCsipDevices();
+            mProfileManager.callServiceConnectedListeners();
+            mIsProfileReady = true;
+        }
+
+        public void onServiceDisconnected(int profile) {
+            if (VDBG) {
+                Log.d(TAG, "Bluetooth service disconnected");
+            }
+            mProfileManager.callServiceDisconnectedListeners();
+            mIsProfileReady = false;
+        }
+    }
+
+    CsipSetCoordinatorProfile(Context context, CachedBluetoothDeviceManager deviceManager,
+            LocalBluetoothProfileManager profileManager) {
+        mContext = context;
+        mDeviceManager = deviceManager;
+        mProfileManager = profileManager;
+
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context,
+                new CoordinatedSetServiceListener(), BluetoothProfile.CSIP_SET_COORDINATOR);
+    }
+
+    /**
+     * Get CSIP devices matching connection states{
+     *
+     * @code BluetoothProfile.STATE_CONNECTED,
+     * @code BluetoothProfile.STATE_CONNECTING,
+     * @code BluetoothProfile.STATE_DISCONNECTING}
+     *
+     * @return Matching device list
+     */
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
+        return mService.getDevicesMatchingConnectionStates(
+                new int[] {BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING,
+                        BluetoothProfile.STATE_DISCONNECTING});
+    }
+
+    /**
+     * Gets the connection status of the device.
+     *
+     * @code BluetoothProfile.STATE_CONNECTED,
+     * @code BluetoothProfile.STATE_CONNECTING,
+     * @code BluetoothProfile.STATE_DISCONNECTING}
+     *
+     * @return Connection status, {@code BluetoothProfile.STATE_DISCONNECTED} if unknown.
+     */
+    public int getConnectionStatus(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+        return mService.getConnectionState(device);
+    }
+
+    @Override
+    public boolean isProfileReady() {
+        return mIsProfileReady;
+    }
+
+    @Override
+    public int getProfileId() {
+        return BluetoothProfile.CSIP_SET_COORDINATOR;
+    }
+
+    @Override
+    public boolean accessProfileEnabled() {
+        return false;
+    }
+
+    @Override
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled(BluetoothDevice device) {
+        if (mService == null || device == null) {
+            return false;
+        }
+        return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN;
+    }
+
+    @Override
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (mService == null || device == null) {
+            return CONNECTION_POLICY_FORBIDDEN;
+        }
+        return mService.getConnectionPolicy(device);
+    }
+
+    @Override
+    public boolean setEnabled(BluetoothDevice device, boolean enabled) {
+        boolean isEnabled = false;
+        if (mService == null || device == null) {
+            return false;
+        }
+        if (enabled) {
+            if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) {
+                isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
+            }
+        } else {
+            isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN);
+        }
+
+        return isEnabled;
+    }
+
+    @Override
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    @Override
+    public int getNameResource(BluetoothDevice device) {
+        return R.string.summary_empty;
+    }
+
+    @Override
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        int state = getConnectionStatus(device);
+        return BluetoothUtils.getConnectionStateSummary(state);
+    }
+
+    @Override
+    public int getDrawableResource(BluetoothClass btClass) {
+        return 0;
+    }
+
+    /**
+     * Get the device's groups and correspondsing uuids map.
+     * @param device the bluetooth device
+     * @return Map of groups ids and related UUIDs
+     */
+    public Map<Integer, ParcelUuid> getGroupUuidMapByDevice(BluetoothDevice device) {
+        if (mService == null || device == null) {
+            return null;
+        }
+        return mService.getGroupUuidMapByDevice(device);
+    }
+
+    /**
+     * Return the profile name as a string.
+     */
+    public String toString() {
+        return NAME;
+    }
+
+    @RequiresApi(32)
+    protected void finalize() {
+        if (VDBG) {
+            Log.d(TAG, "finalize()");
+        }
+        if (mService != null) {
+            try {
+                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
+                        BluetoothProfile.CSIP_SET_COORDINATOR, mService);
+                mService = null;
+            } catch (Throwable t) {
+                Log.w(TAG, "Error cleaning up CSIP Set Coordinator proxy", t);
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 34fdc1e..24113c5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -19,6 +19,7 @@
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothA2dpSink;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHeadsetClient;
@@ -100,7 +101,9 @@
     private PbapClientProfile mPbapClientProfile;
     private PbapServerProfile mPbapProfile;
     private HearingAidProfile mHearingAidProfile;
+    private CsipSetCoordinatorProfile mCsipSetCoordinatorProfile;
     private SapProfile mSapProfile;
+    private VolumeControlProfile mVolumeControlProfile;
 
     /**
      * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -220,6 +223,25 @@
             mSapProfile = new SapProfile(mContext, mDeviceManager, this);
             addProfile(mSapProfile, SapProfile.NAME, BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
         }
+        if (mVolumeControlProfile == null
+                && supportedList.contains(BluetoothProfile.VOLUME_CONTROL)) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding local Volume Control profile");
+            }
+            mVolumeControlProfile = new VolumeControlProfile();
+            // Note: no event handler for VCP, only for being connectable.
+            mProfileNameMap.put(VolumeControlProfile.NAME, mVolumeControlProfile);
+        }
+        if (mCsipSetCoordinatorProfile == null
+                && supportedList.contains(BluetoothProfile.CSIP_SET_COORDINATOR)) {
+            if (DEBUG) {
+                Log.d(TAG, "Adding local CSIP set coordinator profile");
+            }
+            mCsipSetCoordinatorProfile =
+                    new CsipSetCoordinatorProfile(mContext, mDeviceManager, this);
+            addProfile(mCsipSetCoordinatorProfile, mCsipSetCoordinatorProfile.NAME,
+                    BluetoothCsipSetCoordinator.ACTION_CSIS_CONNECTION_STATE_CHANGED);
+        }
         mEventManager.registerProfileIntentReceiver();
     }
 
@@ -296,11 +318,35 @@
                     }
                 }
             }
+
+            if (getCsipSetCoordinatorProfile() != null
+                    && mProfile instanceof CsipSetCoordinatorProfile
+                    && newState == BluetoothProfile.STATE_CONNECTED) {
+                // Check if the GroupID has being initialized
+                if (cachedDevice.getGroupId() == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+                    final Map<Integer, ParcelUuid> groupIdMap = getCsipSetCoordinatorProfile()
+                            .getGroupUuidMapByDevice(cachedDevice.getDevice());
+                    if (groupIdMap != null) {
+                        for (Map.Entry<Integer, ParcelUuid> entry: groupIdMap.entrySet()) {
+                            if (entry.getValue().equals(BluetoothUuid.BASE_UUID)) {
+                                cachedDevice.setGroupId(entry.getKey());
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+
             cachedDevice.onProfileStateChanged(mProfile, newState);
             // Dispatch profile changed after device update
-            if (!(cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
-                    && mDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
-                    newState))) {
+            boolean needDispatchProfileConnectionState = true;
+            if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
+                    || cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+                needDispatchProfileConnectionState = !mDeviceManager
+                        .onProfileConnectionStateChangedIfProcessed(cachedDevice, newState,
+                        mProfile.getProfileId());
+            }
+            if (needDispatchProfileConnectionState) {
                 cachedDevice.refresh();
                 mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
                         mProfile.getProfileId());
@@ -451,6 +497,10 @@
         return mHidDeviceProfile;
     }
 
+    public CsipSetCoordinatorProfile getCsipSetCoordinatorProfile() {
+        return mCsipSetCoordinatorProfile;
+    }
+
     /**
      * Fill in a list of LocalBluetoothProfile objects that are supported by
      * the local device and the remote device.
@@ -565,6 +615,18 @@
             removedProfiles.remove(mSapProfile);
         }
 
+        if (mVolumeControlProfile != null
+                && ArrayUtils.contains(uuids, BluetoothUuid.VOLUME_CONTROL)) {
+            profiles.add(mVolumeControlProfile);
+            removedProfiles.remove(mVolumeControlProfile);
+        }
+
+        if (mCsipSetCoordinatorProfile != null
+                && ArrayUtils.contains(uuids, BluetoothUuid.COORDINATED_SET)) {
+            profiles.add(mCsipSetCoordinatorProfile);
+            removedProfiles.remove(mCsipSetCoordinatorProfile);
+        }
+
         if (DEBUG) {
             Log.d(TAG,"New Profiles" + profiles.toString());
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
new file mode 100644
index 0000000..511df28
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/VolumeControlProfile.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+
+/**
+ * VolumeControlProfile handles Bluetooth Volume Control Controller role
+ */
+public class VolumeControlProfile implements LocalBluetoothProfile {
+    private static final String TAG = "VolumeControlProfile";
+    static final String NAME = "VCP";
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 23;
+
+    @Override
+    public boolean accessProfileEnabled() {
+        return false;
+    }
+
+    @Override
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    @Override
+    public int getConnectionStatus(BluetoothDevice device) {
+        return BluetoothProfile.STATE_DISCONNECTED; // Settings app doesn't handle VCP
+    }
+
+    @Override
+    public boolean isEnabled(BluetoothDevice device) {
+        return false;
+    }
+
+    @Override
+    public int getConnectionPolicy(BluetoothDevice device) {
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; // Settings app doesn't handle VCP
+    }
+
+    @Override
+    public boolean setEnabled(BluetoothDevice device, boolean enabled) {
+        return false;
+    }
+
+    @Override
+    public boolean isProfileReady() {
+        return true;
+    }
+
+    @Override
+    public int getProfileId() {
+        return BluetoothProfile.VOLUME_CONTROL;
+    }
+
+    public String toString() {
+        return NAME;
+    }
+
+    @Override
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    @Override
+    public int getNameResource(BluetoothDevice device) {
+        return 0; // VCP profile not displayed in UI
+    }
+
+    @Override
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        return 0;   // VCP profile not displayed in UI
+    }
+
+    @Override
+    public int getDrawableResource(BluetoothClass btClass) {
+        // no icon for VCP
+        return 0;
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/OWNERS b/packages/SettingsLib/tests/robotests/OWNERS
new file mode 100644
index 0000000..8a7a27ee
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/OWNERS
@@ -0,0 +1,2 @@
+# We do not guard tests - everyone is welcomed to contribute to tests.
+per-file *.java=*
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index fd5b053..4f8fa2f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -206,7 +206,7 @@
         mContext.sendBroadcast(mIntent);
 
         verify(mDeviceManager).onProfileConnectionStateChangedIfProcessed(mCachedBluetoothDevice,
-                BluetoothProfile.STATE_CONNECTED);
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
     }
 
     /**
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 10600e3..0e9a51d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -513,7 +513,7 @@
         <provider android:name=".HeapDumpProvider"
                   android:authorities="com.android.shell.heapdump"
                   android:grantUriPermissions="true"
-                  android:exported="true" />
+                  android:exported="false" />
 
         <activity
             android:name=".BugreportWarningActivity"
diff --git a/services/OWNERS b/services/OWNERS
index b7128a3..a083319 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -4,3 +4,4 @@
 per-file art-profile* = calin@google.com, ngeoffray@google.com, vmarko@google.com
 
 per-file java/com/android/server/* = toddke@google.com,patb@google.com
+per-file tests/servicestests/src/com/android/server/systemconfig/* = patb@google.com
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index d1c3a02..1c614a0 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -114,7 +114,6 @@
             mUiAutomationFlags = flags;
             mUiAutomationServiceInfo = accessibilityServiceInfo;
             mUiAutomationService.mServiceInterface = serviceClient;
-            mUiAutomationService.onAdded();
             try {
                 mUiAutomationService.mServiceInterface.asBinder().linkToDeath(mUiAutomationService,
                         0);
@@ -124,6 +123,8 @@
                 return;
             }
 
+            mUiAutomationService.onAdded();
+
             mUiAutomationService.connectServiceUnknownThread();
         }
     }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 12a94e1..bdeb4d5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -81,7 +81,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Locale;
@@ -176,8 +175,6 @@
     private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
     private boolean mBinding;
     private boolean mUnbinding;
-    private int mWaitForEnableRetry;
-    private int mWaitForDisableRetry;
 
     private BluetoothModeChangeHelper mBluetoothModeChangeHelper;
 
@@ -786,35 +783,6 @@
         return mIsHearingAidProfileSupported;
     }
 
-    @Override
-    /** @hide */
-    public java.util.List<String> getSystemConfigEnabledProfilesForPackage(String packageName) {
-        if (Binder.getCallingUid() != Process.BLUETOOTH_UID) {
-            Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth");
-            return null;
-        }
-
-        SystemConfig systemConfig = SystemConfig.getInstance();
-        if (systemConfig == null) {
-            return null;
-        }
-
-        android.util.ArrayMap<String, Boolean> componentEnabledStates =
-                systemConfig.getComponentsEnabledStates(packageName);
-        if (componentEnabledStates == null) {
-            return null;
-        }
-
-        ArrayList enabledProfiles = new ArrayList<String>();
-        for (Map.Entry<String, Boolean> entry : componentEnabledStates.entrySet()) {
-            if (entry.getValue()) {
-                enabledProfiles.add(entry.getKey());
-            }
-        }
-
-        return enabledProfiles;
-    }
-
     private boolean isDeviceProvisioned() {
         return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED,
                 0) != 0;
@@ -963,14 +931,15 @@
         if (mState == BluetoothAdapter.STATE_ON
                 || mState == BluetoothAdapter.STATE_BLE_ON
                 || mState == BluetoothAdapter.STATE_TURNING_ON
-                || mState == BluetoothAdapter.STATE_TURNING_OFF) {
-            Log.d(TAG, "enableBLE(): Bluetooth already enabled");
+                || mState == BluetoothAdapter.STATE_TURNING_OFF
+                || mState == BluetoothAdapter.STATE_BLE_TURNING_ON) {
+            Log.d(TAG, "enableBLE(): Bluetooth is already enabled or is turning on");
             return true;
         }
         synchronized (mReceiver) {
             // waive WRITE_SECURE_SETTINGS permission check
-            sendEnableMsg(false,
-                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
+            sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
+                    packageName, true);
         }
         return true;
     }
@@ -1764,6 +1733,8 @@
 
     private class BluetoothHandler extends Handler {
         boolean mGetNameAddressOnly = false;
+        private int mWaitForEnableRetry;
+        private int mWaitForDisableRetry;
 
         BluetoothHandler(Looper looper) {
             super(looper);
@@ -1811,11 +1782,12 @@
 
                 case MESSAGE_ENABLE:
                     int quietEnable = msg.arg1;
+                    int isBle  = msg.arg2;
                     if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
                             || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
                         // We are handling enable or disable right now, wait for it.
                         mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE,
-                                quietEnable, 0), ENABLE_DISABLE_DELAY_MS);
+                                quietEnable, isBle), ENABLE_DISABLE_DELAY_MS);
                         break;
                     }
 
@@ -1830,13 +1802,28 @@
                     try {
                         mBluetoothLock.readLock().lock();
                         if (mBluetooth != null) {
+                            boolean isHandled = true;
                             int state = mBluetooth.getState();
-                            if (state == BluetoothAdapter.STATE_BLE_ON) {
-                                Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
-                                mBluetooth.onLeServiceUp();
-                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-                                break;
+                            switch (state) {
+                                case BluetoothAdapter.STATE_BLE_ON:
+                                    if (isBle == 1) {
+                                        Slog.i(TAG, "Already at BLE_ON State");
+                                    } else {
+                                        Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
+                                        mBluetooth.onLeServiceUp();
+                                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
+                                    }
+                                    break;
+                                case BluetoothAdapter.STATE_BLE_TURNING_ON:
+                                case BluetoothAdapter.STATE_TURNING_ON:
+                                case BluetoothAdapter.STATE_ON:
+                                    Slog.i(TAG, "MESSAGE_ENABLE: already enabled");
+                                    break;
+                                default:
+                                    isHandled = false;
+                                    break;
                             }
+                            if (isHandled) break;
                         }
                     } catch (RemoteException e) {
                         Slog.e(TAG, "", e);
@@ -2430,7 +2417,8 @@
         try {
             foregroundUser = ActivityManager.getCurrentUser();
             valid = (callingUser == foregroundUser) || parentUser == foregroundUser
-                    || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid;
+                    || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid
+                    || callingAppId == Process.SHELL_UID;
             if (DBG && !valid) {
                 Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
                         + callingUser + " parentUser=" + parentUser + " foregroundUser="
@@ -2456,6 +2444,16 @@
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
     }
 
+    private boolean isBleState(int state) {
+        switch (state) {
+            case BluetoothAdapter.STATE_BLE_ON:
+            case BluetoothAdapter.STATE_BLE_TURNING_ON:
+            case BluetoothAdapter.STATE_BLE_TURNING_OFF:
+                return true;
+        }
+        return false;
+    }
+
     private void bluetoothStateChangeHandler(int prevState, int newState) {
         boolean isStandardBroadcast = true;
         if (prevState == newState) { // No change. Nothing to do.
@@ -2474,8 +2472,15 @@
                 sendBluetoothServiceDownCallback();
                 unbindAndFinish();
                 sendBleStateChanged(prevState, newState);
-                // Don't broadcast as it has already been broadcast before
-                isStandardBroadcast = false;
+
+                /* Currently, the OFF intent is broadcasted externally only when we transition
+                 * from TURNING_OFF to BLE_ON state. So if the previous state is a BLE state,
+                 * we are guaranteed that the OFF intent has been broadcasted earlier and we
+                 * can safely skip it.
+                 * Conversely, if the previous state is not a BLE state, it indicates that some
+                 * sort of crash has occurred, moving us directly to STATE_OFF without ever
+                 * passing through BLE_ON. We should broadcast the OFF intent in this case. */
+                isStandardBroadcast = !isBleState(prevState);
 
             } else if (!intermediate_off) {
                 // connect to GattService
@@ -2528,6 +2533,11 @@
                 // Show prevState of BLE_ON as OFF to standard users
                 prevState = BluetoothAdapter.STATE_OFF;
             }
+            if (DBG) {
+                Slog.d(TAG,
+                        "Sending State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
+                                + BluetoothAdapter.nameForState(newState));
+            }
             Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
             intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
             intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
@@ -2566,7 +2576,12 @@
     }
 
     private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
-        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
+        sendEnableMsg(quietMode, reason, packageName, false);
+    }
+
+    private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {
+        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0,
+                  isBle ? 1 : 0));
         addActiveLog(reason, packageName, true);
         mLastEnabledTime = SystemClock.elapsedRealtime();
     }
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 26ecee8..d483f18 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -38,6 +38,7 @@
 import android.net.VpnService;
 import android.net.util.NetdService;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.INetworkManagementService;
@@ -348,9 +349,18 @@
     /**
      * Start legacy VPN, controlling native daemons as needed. Creates a
      * secondary thread to perform connection work, returning quickly.
+     *
+     * Legacy VPN is deprecated starting from Android S. So this API shouldn't be called if the
+     * initial SDK version of device is Android S+. Otherwise, UnsupportedOperationException will be
+     * thrown.
      */
+    @SuppressWarnings("AndroidFrameworkCompatChange")  // This is not an app-visible API.
     @Override
     public void startLegacyVpn(VpnProfile profile) {
+        if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.S
+                && VpnProfile.isLegacyType(profile.type)) {
+            throw new UnsupportedOperationException("Legacy VPN is deprecated");
+        }
         int user = UserHandle.getUserId(mDeps.getCallingUid());
         // Note that if the caller is not system (uid >= Process.FIRST_APPLICATION_UID),
         // the code might not work well since getActiveNetwork might return null if the uid is
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index ed83a64..bfc4fe7 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -1362,7 +1362,10 @@
                 if (args.length > 1) {
                     hostname = args[1];
                 }
-                PairDevice device = new PairDevice(fingerprints, hostname, false);
+                PairDevice device = new PairDevice();
+                device.name = fingerprints;
+                device.guid = hostname;
+                device.connected = false;
                 intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
                 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
                 // Add the key into the keystore
@@ -1844,8 +1847,11 @@
                 if (args.length > 1) {
                     hostname = args[1];
                 }
-                pairedDevices.put(keyEntry.getKey(), new PairDevice(
-                        hostname, fingerprints, mWifiConnectedKeys.contains(keyEntry.getKey())));
+                PairDevice pairDevice = new PairDevice();
+                pairDevice.name = hostname;
+                pairDevice.guid = fingerprints;
+                pairDevice.connected = mWifiConnectedKeys.contains(keyEntry.getKey());
+                pairedDevices.put(keyEntry.getKey(), pairDevice);
             }
             return pairedDevices;
         }
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 29bb542..7a4d2ce 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -27,6 +27,8 @@
 import android.debug.AdbManager;
 import android.debug.AdbManagerInternal;
 import android.debug.AdbTransportType;
+import android.debug.FingerprintAndPairDevice;
+import android.debug.IAdbCallback;
 import android.debug.IAdbManager;
 import android.debug.IAdbTransport;
 import android.debug.PairDevice;
@@ -35,6 +37,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -87,6 +90,7 @@
     private final AdbConnectionPortListener mPortListener = new AdbConnectionPortListener();
     private AdbDebuggingManager.AdbConnectionPortPoller mConnectionPortPoller;
 
+    private final RemoteCallbackList<IAdbCallback> mCallbacks = new RemoteCallbackList<>();
     /**
      * Manages the service lifecycle for {@code AdbService} in {@code SystemServer}.
      */
@@ -348,12 +352,21 @@
     }
 
     @Override
-    public Map<String, PairDevice> getPairedDevices() {
+    public FingerprintAndPairDevice[] getPairedDevices() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
-        if (mDebuggingManager != null) {
-            return mDebuggingManager.getPairedDevices();
+        if (mDebuggingManager == null) {
+            return null;
         }
-        return null;
+        Map<String, PairDevice> map = mDebuggingManager.getPairedDevices();
+        FingerprintAndPairDevice[] ret = new FingerprintAndPairDevice[map.size()];
+        int i = 0;
+        for (Map.Entry<String, PairDevice> entry : map.entrySet()) {
+            ret[i] = new FingerprintAndPairDevice();
+            ret[i].keyFingerprint = entry.getKey();
+            ret[i].device = entry.getValue();
+            i++;
+        }
+        return ret;
     }
 
     @Override
@@ -401,6 +414,21 @@
         return mConnectionPort.get();
     }
 
+    @Override
+    public void registerCallback(IAdbCallback callback) throws RemoteException {
+        if (DEBUG) {
+            Slog.d(TAG, "Registering callback " + callback);
+        }
+        mCallbacks.register(callback);
+    }
+
+    @Override
+    public void unregisterCallback(IAdbCallback callback) throws RemoteException {
+        if (DEBUG) {
+            Slog.d(TAG, "Unregistering callback " + callback);
+        }
+        mCallbacks.unregister(callback);
+    }
     /**
      * This listener is only used when ro.adb.secure=0. Otherwise, AdbDebuggingManager will
      * do this.
@@ -507,6 +535,23 @@
         if (mDebuggingManager != null) {
             mDebuggingManager.setAdbEnabled(enable, transportType);
         }
+
+        if (DEBUG) {
+            Slog.d(TAG, "Broadcasting enable = " + enable + ", type = " + transportType);
+        }
+        mCallbacks.broadcast((callback) -> {
+            if (DEBUG) {
+                Slog.d(TAG, "Sending enable = " + enable + ", type = " + transportType
+                        + " to " + callback);
+            }
+            try {
+                callback.onDebuggingChanged(enable, transportType);
+            } catch (RemoteException ex) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Unable to send onDebuggingChanged:", ex);
+                }
+            }
+        });
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index b886dc1..6d85273 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -734,11 +734,8 @@
         }
         ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
 
-        if (!r.mAllowWhileInUsePermissionInFgs) {
-            r.mAllowWhileInUsePermissionInFgs =
-                    shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid,
-                            callingUid, service, r, allowBackgroundActivityStarts);
-        }
+        setFgsRestrictionLocked(callingPackage, callingPid, callingUid, r,
+                allowBackgroundActivityStarts);
 
         return cmp;
     }
@@ -935,7 +932,18 @@
     void killMisbehavingService(ServiceRecord r,
             int appUid, int appPid, String localPackageName) {
         synchronized (mAm) {
-            stopServiceLocked(r);
+            if (!r.destroying) {
+                // This service is still alive, stop it.
+                stopServiceLocked(r);
+            } else {
+                // Check if there is another instance of it being started in parallel,
+                // if so, stop that too to avoid spamming the system.
+                final ServiceMap smap = getServiceMapLocked(r.userId);
+                final ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
+                if (found != null) {
+                    stopServiceLocked(found);
+                }
+            }
             mAm.crashApplication(appUid, appPid, localPackageName, -1,
                     "Bad notification for startForeground", true /*force*/);
         }
@@ -1400,14 +1408,6 @@
                         +  String.format("0x%08X", manifestType)
                         + " in service element of manifest file");
                 }
-                // If the foreground service is not started from TOP process, do not allow it to
-                // have while-in-use location/camera/microphone access.
-                if (!r.mAllowWhileInUsePermissionInFgs) {
-                    Slog.w(TAG,
-                            "Foreground service started from background can not have "
-                                    + "location/camera/microphone access: service "
-                                    + r.shortInstanceName);
-                }
             }
             boolean alreadyStartedOp = false;
             boolean stopProcStatsOp = false;
@@ -1455,6 +1455,57 @@
                     ignoreForeground = true;
                 }
 
+                if (!ignoreForeground) {
+                    if (r.mStartForegroundCount == 0) {
+                        /*
+                        If the service was started with startService(), not
+                        startForegroundService(), and if startForeground() isn't called within
+                        mFgsStartForegroundTimeoutMs, then we check the state of the app
+                        (who owns the service, which is the app that called startForeground())
+                        again. If the app is in the foreground, or in any other cases where
+                        FGS-starts are allowed, then we still allow the FGS to be started.
+                        Otherwise, startForeground() would fail.
+
+                        If the service was started with startForegroundService(), then the service
+                        must call startForeground() within a timeout anyway, so we don't need this
+                        check.
+                        */
+                        if (!r.fgRequired) {
+                            final long delayMs = SystemClock.elapsedRealtime() - r.createRealTime;
+                            if (delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs) {
+                                resetFgsRestrictionLocked(r);
+                                setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.pid,
+                                        r.appInfo.uid, r, false);
+                                EventLog.writeEvent(0x534e4554, "183147114",
+                                        r.appInfo.uid,
+                                        "call setFgsRestrictionLocked again due to "
+                                                + "startForegroundTimeout");
+                            }
+                        }
+                    } else if (r.mStartForegroundCount >= 1) {
+                        // The second or later time startForeground() is called after service is
+                        // started. Check for app state again.
+                        final long delayMs = SystemClock.elapsedRealtime() -
+                                r.mLastSetFgsRestrictionTime;
+                        if (delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs) {
+                            resetFgsRestrictionLocked(r);
+                            setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.pid,
+                                    r.appInfo.uid, r, false);
+                            EventLog.writeEvent(0x534e4554, "183147114", r.appInfo.uid,
+                                    "call setFgsRestrictionLocked for "
+                                            + (r.mStartForegroundCount + 1) + "th startForeground");
+                        }
+                    }
+                    // If the foreground service is not started from TOP process, do not allow it to
+                    // have while-in-use location/camera/microphone access.
+                    if (!r.mAllowWhileInUsePermissionInFgs) {
+                        Slog.w(TAG,
+                                "Foreground service started from background can not have "
+                                        + "location/camera/microphone access: service "
+                                        + r.shortInstanceName);
+                    }
+                }
+
                 // Apps under strict background restrictions simply don't get to have foreground
                 // services, so now that we've enforced the startForegroundService() contract
                 // we only do the machinery of making the service foreground when the app
@@ -1490,6 +1541,7 @@
                             active.mNumActive++;
                         }
                         r.isForeground = true;
+                        r.mStartForegroundCount++;
                         if (!stopProcStatsOp) {
                             ServiceState stracker = r.getTracker();
                             if (stracker != null) {
@@ -1548,6 +1600,7 @@
                     decActiveForegroundAppLocked(smap, r);
                 }
                 r.isForeground = false;
+                resetFgsRestrictionLocked(r);
                 ServiceState stracker = r.getTracker();
                 if (stracker != null) {
                     stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
@@ -2107,12 +2160,7 @@
                 }
             }
 
-            if (!s.mAllowWhileInUsePermissionInFgs) {
-                s.mAllowWhileInUsePermissionInFgs =
-                        shouldAllowWhileInUsePermissionInFgsLocked(callingPackage,
-                                callingPid, callingUid,
-                                service, s, false);
-            }
+            setFgsRestrictionLocked(callingPackage, callingPid, callingUid, s, false);
 
             if (s.app != null) {
                 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
@@ -3408,7 +3456,7 @@
         r.isForeground = false;
         r.foregroundId = 0;
         r.foregroundNoti = null;
-        r.mAllowWhileInUsePermissionInFgs = false;
+        resetFgsRestrictionLocked(r);
 
         // Clear start entries.
         r.clearDeliveredStartsLocked();
@@ -4889,7 +4937,7 @@
      * @return true if allow, false otherwise.
      */
     private boolean shouldAllowWhileInUsePermissionInFgsLocked(String callingPackage,
-            int callingPid, int callingUid, Intent intent, ServiceRecord r,
+            int callingPid, int callingUid, ServiceRecord r,
             boolean allowBackgroundActivityStarts) {
         // Is the background FGS start restriction turned on?
         if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
@@ -4975,6 +5023,28 @@
     boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid,
             String callingPackage) {
         return shouldAllowWhileInUsePermissionInFgsLocked(
-                callingPackage, callingPid, callingUid, null, null, false);
+                callingPackage, callingPid, callingUid, null, false);
+    }
+
+    /**
+     * In R, mAllowWhileInUsePermissionInFgs is to allow while-in-use permissions in foreground
+     *  service or not. while-in-use permissions in FGS started from background might be restricted.
+     * @param callingPackage caller app's package name.
+     * @param callingUid caller app's uid.
+     * @param r the service to start.
+     * @return true if allow, false otherwise.
+     */
+    private void setFgsRestrictionLocked(String callingPackage,
+            int callingPid, int callingUid, ServiceRecord r,
+            boolean allowBackgroundActivityStarts) {
+        r.mLastSetFgsRestrictionTime = SystemClock.elapsedRealtime();
+        if (!r.mAllowWhileInUsePermissionInFgs) {
+            r.mAllowWhileInUsePermissionInFgs = shouldAllowWhileInUsePermissionInFgsLocked(
+                    callingPackage, callingPid, callingUid, r, allowBackgroundActivityStarts);
+        }
+    }
+
+    private void resetFgsRestrictionLocked(ServiceRecord r) {
+        r.mAllowWhileInUsePermissionInFgs = false;
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 7be843f..00d8208e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -88,6 +88,7 @@
     static final String KEY_PROCESS_START_ASYNC = "process_start_async";
     static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
     static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
+    static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout";
     static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold";
 
     private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
@@ -121,6 +122,7 @@
     private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
     private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
     private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
+    private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000;
     private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000;
 
     // Flag stored in the DeviceConfig API.
@@ -273,6 +275,12 @@
     // this long.
     public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
 
+    /**
+     * When service started from background, before the timeout it can be promoted to FGS by calling
+     * Service.startForeground().
+     */
+    volatile long mFgsStartForegroundTimeoutMs = DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS;
+
     // Indicates whether the activity starts logging is enabled.
     // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
     volatile boolean mFlagActivityStartsLoggingEnabled;
@@ -421,6 +429,9 @@
                             case KEY_MIN_ASSOC_LOG_DURATION:
                                 updateMinAssocLogDuration();
                                 break;
+                            case KEY_FGS_START_FOREGROUND_TIMEOUT:
+                                updateFgsStartForegroundTimeout();
+                                break;
                             default:
                                 break;
                         }
@@ -697,6 +708,13 @@
                 /* defaultValue */ DEFAULT_MIN_ASSOC_LOG_DURATION);
     }
 
+    private void updateFgsStartForegroundTimeout() {
+        mFgsStartForegroundTimeoutMs = DeviceConfig.getLong(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_FGS_START_FOREGROUND_TIMEOUT,
+                DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS);
+    }
+
     void dump(PrintWriter pw) {
         pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
                 + Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");
@@ -769,6 +787,8 @@
         pw.println(Arrays.toString(IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.toArray()));
         pw.print("  "); pw.print(KEY_MIN_ASSOC_LOG_DURATION); pw.print("=");
         pw.println(MIN_ASSOC_LOG_DURATION);
+        pw.print("  "); pw.print(KEY_FGS_START_FOREGROUND_TIMEOUT); pw.print("=");
+        pw.println(mFgsStartForegroundTimeoutMs);
 
         pw.println();
         if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7a985f4..82bd123 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4133,7 +4133,7 @@
         // control of all writes to the file in question.
 
         // We must complete all stack dumps within 20 seconds.
-        long remainingTime = 20 * 1000;
+        long remainingTime = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
 
         // As applications are usually interested with the ANR stack traces, but we can't share with
         // them the stack traces other than their own stacks. So after the very first PID is
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index af89907..50f3520 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -94,7 +94,6 @@
 import com.android.server.compat.PlatformCompat;
 
 import java.io.BufferedReader;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -787,8 +786,7 @@
             return -1;
         }
 
-        File file = new File(filename);
-        file.delete();
+        // Writes an error message to stderr on failure
         ParcelFileDescriptor fd = openFileForSystem(filename, "w");
         if (fd == null) {
             return -1;
@@ -942,16 +940,16 @@
             String logNameTimeString = LOG_NAME_TIME_FORMATTER.format(localDateTime);
             heapFile = "/data/local/tmp/heapdump-" + logNameTimeString + ".prof";
         }
-        pw.println("File: " + heapFile);
-        pw.flush();
 
-        File file = new File(heapFile);
-        file.delete();
+        // Writes an error message to stderr on failure
         ParcelFileDescriptor fd = openFileForSystem(heapFile, "w");
         if (fd == null) {
             return -1;
         }
 
+        pw.println("File: " + heapFile);
+        pw.flush();
+
         final CountDownLatch latch = new CountDownLatch(1);
 
         final RemoteCallback finishCallback = new RemoteCallback(new OnResultListener() {
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 39f79ca..ef47b1e 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -22,6 +22,7 @@
 import android.net.wifi.WifiManager;
 import android.os.BatteryStats;
 import android.os.Bundle;
+import android.os.OutcomeReceiver;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.ServiceManager;
@@ -40,6 +41,7 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.function.pooled.PooledLambda;
 
+import java.util.concurrent.ExecutionException;
 import libcore.util.EmptyArray;
 
 import java.util.concurrent.CompletableFuture;
@@ -405,7 +407,7 @@
         // We will request data from external processes asynchronously, and wait on a timeout.
         SynchronousResultReceiver wifiReceiver = null;
         SynchronousResultReceiver bluetoothReceiver = null;
-        SynchronousResultReceiver modemReceiver = null;
+        CompletableFuture<ModemActivityInfo> modemFuture = CompletableFuture.completedFuture(null);
         boolean railUpdated = false;
 
         if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
@@ -460,8 +462,22 @@
             }
 
             if (mTelephony != null) {
-                modemReceiver = new SynchronousResultReceiver("telephony");
-                mTelephony.requestModemActivityInfo(modemReceiver);
+                CompletableFuture<ModemActivityInfo> temp = new CompletableFuture<>();
+                mTelephony.requestModemActivityInfo(Runnable::run,
+                        new OutcomeReceiver<ModemActivityInfo,
+                                TelephonyManager.ModemActivityInfoException>() {
+                            @Override
+                            public void onResult(ModemActivityInfo result) {
+                                temp.complete(result);
+                            }
+
+                            @Override
+                            public void onError(TelephonyManager.ModemActivityInfoException e) {
+                                Slog.w(TAG, "error reading modem stats:" + e);
+                                temp.complete(null);
+                            }
+                        });
+                modemFuture = temp;
             }
             if (!railUpdated) {
                 synchronized (mStats) {
@@ -472,7 +488,17 @@
 
         final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
         final BluetoothActivityEnergyInfo bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
-        final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
+        ModemActivityInfo modemInfo = null;
+        try {
+            modemInfo = modemFuture.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
+                    TimeUnit.MILLISECONDS);
+        } catch (TimeoutException | InterruptedException e) {
+            Slog.w(TAG, "timeout or interrupt reading modem stats: " + e);
+        } catch (ExecutionException e) {
+            Slog.w(TAG, "exception reading modem stats: " + e.getCause());
+        }
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
 
         synchronized (mStats) {
             mStats.addHistoryEventLocked(
@@ -519,11 +545,7 @@
         }
 
         if (modemInfo != null) {
-            if (modemInfo.isValid()) {
-                mStats.updateMobileRadioState(modemInfo);
-            } else {
-                Slog.w(TAG, "modem info is invalid: " + modemInfo);
-            }
+            mStats.updateMobileRadioState(modemInfo);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index b45237c..34ba3e0 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1164,7 +1164,7 @@
     }
 
     @Override
-    public void noteResetBleScan() {
+    public void noteBleScanReset() {
         enforceCallingPermission();
         synchronized (mStats) {
             mStats.noteResetBluetoothScanLocked();
@@ -1208,7 +1208,7 @@
     public void noteModemControllerActivity(ModemActivityInfo info) {
         enforceCallingPermission();
 
-        if (info == null || !info.isValid()) {
+        if (info == null) {
             Slog.e(TAG, "invalid modem data given: " + info);
             return;
         }
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
index 1ecb9eb..598f086 100644
--- a/services/core/java/com/android/server/am/LmkdConnection.java
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -50,7 +50,7 @@
      * Used to hold the data for the statsd atoms logging
      * Must be in sync with statslog.h
      */
-    private static final int LMKD_REPLY_MAX_SIZE = 214;
+    private static final int LMKD_REPLY_MAX_SIZE = 222;
 
     // connection listener interface
     interface LmkdConnectionListener {
diff --git a/services/core/java/com/android/server/am/LmkdStatsReporter.java b/services/core/java/com/android/server/am/LmkdStatsReporter.java
index a8d0582..9158891 100644
--- a/services/core/java/com/android/server/am/LmkdStatsReporter.java
+++ b/services/core/java/com/android/server/am/LmkdStatsReporter.java
@@ -64,11 +64,14 @@
             final int freeMemKb = inputData.readInt();
             final int freeSwapKb = inputData.readInt();
             final int killReason = inputData.readInt();
+            final int thrashing = inputData.readInt();
+            final int maxThrashing = inputData.readInt();
             final String procName = inputData.readUTF();
 
             FrameworkStatsLog.write(FrameworkStatsLog.LMK_KILL_OCCURRED, uid, procName, oomScore,
                     pgFault, pgMajFault, rssInBytes, cacheInBytes, swapInBytes, processStartTimeNS,
-                    minOomScore, freeMemKb, freeSwapKb, mapKillReason(killReason));
+                    minOomScore, freeMemKb, freeSwapKb, mapKillReason(killReason), thrashing,
+                    maxThrashing);
         } catch (IOException e) {
             Slog.e(TAG, "Invalid buffer data. Failed to log LMK_KILL_OCCURRED");
             return;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 1b65dba..0e62828 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -142,6 +142,10 @@
     // allow while-in-use permissions in foreground service or not.
     // while-in-use permissions in FGS started from background might be restricted.
     boolean mAllowWhileInUsePermissionInFgs;
+    // The number of times Service.startForeground() is called;
+    int mStartForegroundCount;
+    // Last time mAllowWhileInUsePermissionInFgs is set.
+    long mLastSetFgsRestrictionTime;
 
     // the most recent package that start/bind this service.
     String mRecentCallingPackage;
@@ -406,6 +410,8 @@
         }
         pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs=");
                 pw.println(mAllowWhileInUsePermissionInFgs);
+        pw.print(prefix); pw.print("startForegroundCount=");
+        pw.println(mStartForegroundCount);
         pw.print(prefix); pw.print("recentCallingPackage=");
                 pw.println(mRecentCallingPackage);
         if (delayed) {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index c20a01d..00dfd38 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -84,6 +84,7 @@
         DeviceConfig.NAMESPACE_CONNECTIVITY,
         DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS,
+        DeviceConfig.NAMESPACE_LMKD_NATIVE,
         DeviceConfig.NAMESPACE_MEDIA_NATIVE,
         DeviceConfig.NAMESPACE_NETD_NATIVE,
         DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 26f5c4c..b5e6c11 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -563,6 +563,37 @@
         sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
+    private static final class LeAudioDeviceConnectionInfo {
+        final @NonNull BluetoothDevice mDevice;
+        final @AudioService.BtProfileConnectionState int mState;
+        final boolean mSupprNoisy;
+        final @NonNull String mEventSource;
+
+        LeAudioDeviceConnectionInfo(@NonNull BluetoothDevice device,
+                @AudioService.BtProfileConnectionState int state,
+                boolean suppressNoisyIntent, @NonNull String eventSource) {
+            mDevice = device;
+            mState = state;
+            mSupprNoisy = suppressNoisyIntent;
+            mEventSource = eventSource;
+        }
+    }
+
+    /*package*/ void postBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            boolean suppressNoisyIntent, @NonNull String eventSource) {
+        final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
+                device, state, suppressNoisyIntent, eventSource);
+        sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+    }
+
+    /*package*/ void postBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            @NonNull String eventSource) {
+        final LeAudioDeviceConnectionInfo info = new LeAudioDeviceConnectionInfo(
+                device, state, false, eventSource);
+        sendLMsgNoDelay(MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+    }
 
     /**
      * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn().
@@ -849,6 +880,23 @@
                 delay);
     }
 
+    /*package*/ void postSetLeAudioOutConnectionState(
+            @AudioService.BtProfileConnectionState int state,
+            @NonNull BluetoothDevice device, int delay) {
+        sendILMsg(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE, SENDMSG_QUEUE,
+                state,
+                device,
+                delay);
+    }
+
+    /*package*/ void postSetLeAudioInConnectionState(
+            @AudioService.BtProfileConnectionState int state,
+            @NonNull BluetoothDevice device) {
+        sendILMsgNoDelay(MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE, SENDMSG_QUEUE,
+                state,
+                device);
+    }
+
     /*package*/ void postDisconnectA2dp() {
         sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE);
     }
@@ -1154,7 +1202,20 @@
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.onSetHearingAidConnectionState(
                                 (BluetoothDevice) msg.obj, msg.arg1,
-                                mAudioService.getHearingAidStreamType());
+                                mAudioService.getBluetoothContextualVolumeStream());
+                    }
+                    break;
+                case MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE:
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.onSetLeAudioOutConnectionState(
+                                (BluetoothDevice) msg.obj, msg.arg1,
+                                mAudioService.getBluetoothContextualVolumeStream());
+                    }
+                    break;
+                case MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE:
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.onSetLeAudioInConnectionState(
+                                (BluetoothDevice) msg.obj, msg.arg1);
                     }
                     break;
                 case MSG_BT_HEADSET_CNCT_FAILED:
@@ -1343,6 +1404,31 @@
                     final int capturePreset = msg.arg1;
                     mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
                 } break;
+                case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT: {
+                    final LeAudioDeviceConnectionInfo info =
+                            (LeAudioDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setLeAudioDeviceOutConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " supprNoisy=" + info.mSupprNoisy
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothLeAudioOutDeviceConnectionState(
+                                info.mDevice, info.mState, info.mSupprNoisy);
+                    }
+                } break;
+                case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT: {
+                    final LeAudioDeviceConnectionInfo info =
+                            (LeAudioDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setLeAudioDeviceInConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothLeAudioInDeviceConnectionState(info.mDevice,
+                                info.mState);
+                    }
+                } break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
@@ -1424,6 +1510,11 @@
     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 final int MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE = 42;
+    private static final int MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE = 43;
+    private static final int MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT = 44;
+    private static final int MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT = 45;
+
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
             case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
@@ -1439,6 +1530,8 @@
             case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
             case MSG_CHECK_MUTE_MUSIC:
+            case MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT:
+            case MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT:
                 return true;
             default:
                 return false;
@@ -1648,10 +1741,9 @@
             return;
         }
         Log.w(TAG, "Speaker client died");
-        if (removeCommunicationRouteClient(client.getBinder(), false)
-                != null) {
-            onUpdateCommunicationRoute("onCommunicationRouteClientDied");
-        }
+        setCommunicationRouteForClient(
+                client.getBinder(), client.getPid(), null,
+                BtHelper.SCO_MODE_UNDEFINED, "onCommunicationRouteClientDied");
     }
 
     /**
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 82586b8..78daabc 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.content.Intent;
 import android.media.AudioDeviceAttributes;
@@ -423,6 +424,45 @@
         }
     }
 
+    /*package*/ void onSetLeAudioConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state, int streamType, int device) {
+        String address = btDevice.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            address = "";
+        }
+        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "onSetLeAudioConnectionState addr=" + address));
+
+        synchronized (mDevicesLock) {
+            DeviceInfo di = null;
+            boolean isConnected = false;
+
+            String key = DeviceInfo.makeDeviceListKey(device, btDevice.getAddress());
+            di = mConnectedDevices.get(key);
+            isConnected = di != null;
+
+            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
+                makeLeAudioDeviceUnavailable(address, device);
+            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
+                makeLeAudioDeviceAvailable(address, BtHelper.getName(btDevice), streamType,
+                        device, "onSetLeAudioConnectionState");
+            }
+        }
+    }
+
+    /*package*/ void onSetLeAudioOutConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state, int streamType) {
+        // TODO: b/198610537 clarify DEVICE_OUT_BLE_HEADSET vs DEVICE_OUT_BLE_SPEAKER criteria
+        onSetLeAudioConnectionState(btDevice, state, streamType,
+                AudioSystem.DEVICE_OUT_BLE_HEADSET);
+    }
+
+    /*package*/ void onSetLeAudioInConnectionState(BluetoothDevice btDevice,
+                @AudioService.BtProfileConnectionState int state) {
+        onSetLeAudioConnectionState(btDevice, state, AudioSystem.STREAM_DEFAULT,
+                AudioSystem.DEVICE_IN_BLE_HEADSET);
+    }
+
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
         /*package*/ void onBluetoothA2dpActiveDeviceChange(
             @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
@@ -943,6 +983,28 @@
         }
     }
 
+    /*package*/ int setBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
+            boolean suppressNoisyIntent) {
+        synchronized (mDevicesLock) {
+            /* Active device become null and it's previous device is not connected anymore */
+            int delay = 0;
+            if (!suppressNoisyIntent) {
+                int intState = (state == BluetoothLeAudio.STATE_CONNECTED) ? 1 : 0;
+                delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLE_HEADSET,
+                        intState, AudioSystem.DEVICE_NONE);
+            }
+            mDeviceBroker.postSetLeAudioOutConnectionState(state, device, delay);
+            return delay;
+        }
+    }
+
+    /*package*/ void setBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state) {
+        synchronized (mDevicesLock) {
+            mDeviceBroker.postSetLeAudioInConnectionState(state, device);
+        }
+    }
 
     //-------------------------------------------------------------------
     // Internal utilities
@@ -1115,6 +1177,36 @@
     }
 
     @GuardedBy("mDevicesLock")
+    private void makeLeAudioDeviceAvailable(String address, String name, int streamType, int device,
+            String eventSource) {
+        if (device != AudioSystem.DEVICE_NONE) {
+            AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE,
+                    address, name, AudioSystem.AUDIO_FORMAT_DEFAULT);
+            mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
+                    new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+            mDeviceBroker.postAccessoryPlugMediaUnmute(device);
+        }
+
+        if (streamType == AudioSystem.STREAM_DEFAULT) {
+            // No need to update volume for input devices
+            return;
+        }
+
+        mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
+    }
+
+    @GuardedBy("mDevicesLock")
+    private void makeLeAudioDeviceUnavailable(String address, int device) {
+        if (device != AudioSystem.DEVICE_NONE) {
+            AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                    address, "", AudioSystem.AUDIO_FORMAT_DEFAULT);
+            mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
+        }
+
+        setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
+    }
+
+    @GuardedBy("mDevicesLock")
     private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
         synchronized (mCurAudioRoutes) {
             if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
@@ -1150,6 +1242,7 @@
         BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
         BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
     }
 
     // must be called before removing the device from mConnectedDevices
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d0a3079..97a20c4 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -163,6 +163,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -307,6 +308,12 @@
     // retry delay in case of failure to indicate system ready to AudioFlinger
     private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
 
+    // Bits representing connected devices to monitor playback monitor voice activity
+    private static final int CONNECTED_STATE_HEARING_AID_BIT = 0;
+    private static final int CONNECTED_STATE_LE_AUDIO_BIT = 1;
+
+    private BitSet mConnectedStateBitset = new BitSet(2);
+
     /** @see AudioSystemThread */
     private AudioSystemThread mAudioSystemThread;
     /** @see AudioHandler */
@@ -2529,7 +2536,7 @@
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 // only modify the hearing aid attenuation when the stream to modify matches
                 // the one expected by the hearing aid
-                if (streamType == getHearingAidStreamType()) {
+                if (streamType == getBluetoothContextualVolumeStream()) {
                     if (DEBUG_VOL) {
                         Log.d(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index="
                                 + newIndex + " stream=" + streamType);
@@ -2872,11 +2879,11 @@
         }
     }
 
-    /*package*/ int getHearingAidStreamType() {
-        return getHearingAidStreamType(mMode);
+    /*package*/ int getBluetoothContextualVolumeStream() {
+        return getBluetoothContextualVolumeStream(mMode);
     }
 
-    private int getHearingAidStreamType(int mode) {
+    private int getBluetoothContextualVolumeStream(int mode) {
         switch (mode) {
             case AudioSystem.MODE_IN_COMMUNICATION:
             case AudioSystem.MODE_IN_CALL:
@@ -2922,7 +2929,7 @@
     }
 
     private void updateHearingAidVolumeOnVoiceActivityUpdate() {
-        final int streamType = getHearingAidStreamType();
+        final int streamType = getBluetoothContextualVolumeStream();
         final int index = getStreamVolume(streamType);
         sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_HEARING_AID,
                 mVoiceActive.get(), streamType, index));
@@ -2954,7 +2961,7 @@
                 return;
         }
 
-        int streamType = getHearingAidStreamType(newMode);
+        int streamType = getBluetoothContextualVolumeStream(newMode);
 
         final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
                 AudioSystem.getDevicesForStream(streamType));
@@ -3036,7 +3043,7 @@
             }
 
             if (device == AudioSystem.DEVICE_OUT_HEARING_AID
-                    && streamType == getHearingAidStreamType()) {
+                    && streamType == getBluetoothContextualVolumeStream()) {
                 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
                         + " stream=" + streamType);
                 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
@@ -5496,15 +5503,68 @@
             throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
                     + " (dis)connection, got " + state);
         }
-        if (state == BluetoothProfile.STATE_CONNECTED) {
-            mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
-        } else {
-            mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
+        synchronized (mConnectedStateBitset) {
+            if (state == BluetoothProfile.STATE_CONNECTED) {
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
+                }
+                mConnectedStateBitset.set(CONNECTED_STATE_HEARING_AID_BIT);
+            } else {
+                mConnectedStateBitset.clear(CONNECTED_STATE_HEARING_AID_BIT);
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
+                }
+            }
         }
         mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
                 device, state, suppressNoisyIntent, musicDevice, "AudioService");
     }
 
+    private void setBluetoothLeAudioDeviceConnectionState(@NonNull BluetoothDevice device,
+            @BtProfileConnectionState int state) {
+        if (device == null) {
+            throw new IllegalArgumentException("Illegal null device");
+        }
+        if (state != BluetoothProfile.STATE_CONNECTED
+                && state != BluetoothProfile.STATE_DISCONNECTED) {
+            throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
+                    + " (dis)connection, got " + state);
+        }
+        synchronized (mConnectedStateBitset) {
+            if (state == BluetoothProfile.STATE_CONNECTED) {
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.registerPlaybackCallback(mVoiceActivityMonitor, true);
+                }
+                mConnectedStateBitset.set(CONNECTED_STATE_LE_AUDIO_BIT);
+            } else {
+                mConnectedStateBitset.clear(CONNECTED_STATE_LE_AUDIO_BIT);
+                if (mConnectedStateBitset.isEmpty()) {
+                    mPlaybackMonitor.unregisterPlaybackCallback(mVoiceActivityMonitor);
+                }
+            }
+        }
+    }
+
+    /**
+     * See AudioManager.setBluetoothLeAudioOutDeviceConnectionState()
+     */
+    public void setBluetoothLeAudioOutDeviceConnectionState(
+            @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
+            boolean suppressNoisyIntent) {
+        setBluetoothLeAudioDeviceConnectionState(device, state);
+        mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(device, state,
+                suppressNoisyIntent, "AudioService");
+    }
+
+    /**
+     * See AudioManager.setBluetoothLeAudioInDeviceConnectionState()
+     */
+    public void setBluetoothLeAudioInDeviceConnectionState(
+            @NonNull BluetoothDevice device, @BtProfileConnectionState int state) {
+        setBluetoothLeAudioDeviceConnectionState(device, state);
+        mDeviceBroker.postBluetoothLeAudioInDeviceConnectionState(device, state, "AudioService");
+    }
+
     /**
      * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
      */
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index a90fee6..90f84ca 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -860,7 +860,7 @@
             try {
                 userId = getUserOrWorkProfileId(clientPackage, userId);
                 if (userId != mCurrentUserId) {
-                    int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
+                    int firstSdkInt = Build.VERSION.DEVICE_INITIAL_SDK_INT;
                     if (firstSdkInt < Build.VERSION_CODES.BASE) {
                         Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " +
                                 "at least VERSION_CODES.BASE");
diff --git a/services/core/java/com/android/server/broadcastradio/OWNERS b/services/core/java/com/android/server/broadcastradio/OWNERS
index ea4421e..3e360e7 100644
--- a/services/core/java/com/android/server/broadcastradio/OWNERS
+++ b/services/core/java/com/android/server/broadcastradio/OWNERS
@@ -1,2 +1,3 @@
+keunyoung@google.com
+oscarazu@google.com
 twasilczyk@google.com
-randolphs@google.com
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index f2e44ee..e7118ad 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -28,10 +28,8 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 
 class Tuner extends ITuner.Stub {
     private static final String TAG = "BroadcastRadioService.Tuner";
@@ -292,12 +290,12 @@
     }
 
     @Override
-    public Map setParameters(Map parameters) {
+    public Map<String, String> setParameters(Map<String, String> parameters) {
         throw new UnsupportedOperationException("Not supported by HAL 1.x");
     }
 
     @Override
-    public Map getParameters(List<String> keys) {
+    public Map<String, String> getParameters(List<String> keys) {
         throw new UnsupportedOperationException("Not supported by HAL 1.x");
     }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
index 7a6d964..867d5b4 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
@@ -18,12 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.radio.ITuner;
 import android.hardware.radio.ITunerCallback;
 import android.hardware.radio.ProgramList;
 import android.hardware.radio.ProgramSelector;
 import android.hardware.radio.RadioManager;
-import android.hardware.radio.RadioMetadata;
 import android.hardware.radio.RadioTuner;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -31,7 +29,6 @@
 
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
@@ -176,7 +173,7 @@
     }
 
     @Override
-    public void onParametersUpdated(Map parameters) {
+    public void onParametersUpdated(Map<String, String> parameters) {
         Slog.e(TAG, "Not applicable for HAL 1.x");
     }
 
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 7ab3bdd..7d8c6a4 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -299,7 +299,7 @@
     }
 
     @Override
-    public Map setParameters(Map parameters) {
+    public Map<String, String> setParameters(Map<String, String> parameters) {
         synchronized (mLock) {
             checkNotClosedLocked();
             return Convert.vendorInfoFromHal(Utils.maybeRethrow(
@@ -308,7 +308,7 @@
     }
 
     @Override
-    public Map getParameters(List<String> keys) {
+    public Map<String, String> getParameters(List<String> keys) {
         synchronized (mLock) {
             checkNotClosedLocked();
             return Convert.vendorInfoFromHal(Utils.maybeRethrow(
diff --git a/services/core/java/com/android/server/connectivity/PacProxyService.java b/services/core/java/com/android/server/connectivity/PacProxyService.java
index 0070339..3a97765 100644
--- a/services/core/java/com/android/server/connectivity/PacProxyService.java
+++ b/services/core/java/com/android/server/connectivity/PacProxyService.java
@@ -34,7 +34,6 @@
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteCallbackList;
@@ -42,6 +41,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -192,7 +192,7 @@
     }
 
     /**
-     * Updates the PAC Proxy Installer with current Proxy information. This is called by
+     * Updates the PAC Proxy Service with current Proxy information. This is called by
      * the ProxyTracker through PacProxyManager before a broadcast takes place to allow
      * the PacProxyService to indicate that the broadcast should not be sent and the
      * PacProxyService will trigger a new broadcast when it is ready.
@@ -357,8 +357,9 @@
                 }
             }
         };
-        mContext.bindService(intent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE);
+        mContext.bindServiceAsUser(intent, mConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
+                UserHandle.SYSTEM);
 
         intent = new Intent();
         intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE);
@@ -398,9 +399,9 @@
                 }
             }
         };
-        mContext.bindService(intent,
+        mContext.bindServiceAsUser(intent, mProxyConnection,
                 Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
-                new HandlerExecutor(mNetThreadHandler), mProxyConnection);
+                mNetThreadHandler, UserHandle.SYSTEM);
     }
 
     private void unbind() {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index c24973d..8926e20 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -242,7 +242,7 @@
         mValidationInfo.append(opcode, new ValidationInfo(validator, addrType));
     }
 
-    int isValid(HdmiCecMessage message) {
+    int isValid(HdmiCecMessage message, boolean isMessageReceived) {
         int opcode = message.getOpcode();
         ValidationInfo info = mValidationInfo.get(opcode);
         if (info == null) {
@@ -256,6 +256,22 @@
             HdmiLogger.warning("Unexpected source: " + message);
             return ERROR_SOURCE;
         }
+
+        if (isMessageReceived) {
+            // Check if the source's logical address and local device's logical
+            // address are the same.
+            for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) {
+                synchronized (device.mLock) {
+                    if (message.getSource() == device.getDeviceInfo().getLogicalAddress()
+                            && message.getSource() != Constants.ADDR_UNREGISTERED) {
+                        HdmiLogger.warning(
+                                "Unexpected source: message sent from device itself, " + message);
+                        return ERROR_SOURCE;
+                    }
+                }
+            }
+        }
+
         // Check the destination field.
         if (message.getDestination() == Constants.ADDR_BROADCAST) {
             if ((info.addressType & DEST_BROADCAST) == 0) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index cca8be8..b049d01 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -556,6 +556,12 @@
         // on boot, if device is interactive, set HDMI CEC state as powered on as well
         if (mPowerManager.isInteractive() && isPowerStandbyOrTransient()) {
             mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
+            // Start all actions that were queued because the device was in standby
+            if (mAddressAllocated) {
+                for (HdmiCecLocalDevice localDevice : getAllLocalDevices()) {
+                    localDevice.startQueuedActions();
+                }
+            }
         }
     }
 
@@ -1122,7 +1128,7 @@
     @ServiceThreadOnly
     void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) {
         assertRunOnServiceThread();
-        if (mMessageValidator.isValid(command) == HdmiCecMessageValidator.OK) {
+        if (mMessageValidator.isValid(command, false) == HdmiCecMessageValidator.OK) {
             mCecController.sendCommand(command, callback);
         } else {
             HdmiLogger.error("Invalid message type:" + command);
@@ -1153,7 +1159,7 @@
     @ServiceThreadOnly
     boolean handleCecCommand(HdmiCecMessage message) {
         assertRunOnServiceThread();
-        int errorCode = mMessageValidator.isValid(message);
+        int errorCode = mMessageValidator.isValid(message, true);
         if (errorCode != HdmiCecMessageValidator.OK) {
             // We'll not response on the messages with the invalid source or destination
             // or with parameter length shorter than specified in the standard.
@@ -3353,8 +3359,8 @@
         invokeInputChangeListener(info);
     }
 
-   void setMhlInputChangeEnabled(boolean enabled) {
-       mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
+    void setMhlInputChangeEnabled(boolean enabled) {
+        mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled));
 
         synchronized (mLock) {
             mMhlInputChangeEnabled = enabled;
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 6aefe41..a090c1a 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -285,7 +285,8 @@
                 combined.getValues(augmentStart, augmentEnd, entry);
             }
 
-            final long rawBytes = entry.rxBytes + entry.txBytes;
+            final long rawBytes = (entry.rxBytes + entry.txBytes) == 0 ? 1 :
+                    (entry.rxBytes + entry.txBytes);
             final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes;
             final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes;
             final long targetBytes = augmentPlan.getDataUsageBytes();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4ee867b..097b071 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -289,8 +289,7 @@
     private String mActiveIface;
 
     /** Set of any ifaces associated with mobile networks since boot. */
-    @GuardedBy("mStatsLock")
-    private String[] mMobileIfaces = new String[0];
+    private volatile String[] mMobileIfaces = new String[0];
 
     /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
     @GuardedBy("mStatsLock")
@@ -935,7 +934,12 @@
 
     @Override
     public String[] getMobileIfaces() {
-        return mMobileIfaces;
+        // TODO (b/192758557): Remove debug log.
+        if (ArrayUtils.contains(mMobileIfaces, null)) {
+            throw new NullPointerException(
+                    "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
+        }
+        return mMobileIfaces.clone();
     }
 
     @Override
@@ -1084,7 +1088,8 @@
     }
 
     @Override
-    public long getIfaceStats(String iface, int type) {
+    public long getIfaceStats(@NonNull String iface, int type) {
+        Objects.requireNonNull(iface);
         long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
         if (nativeIfaceStats == -1) {
             return nativeIfaceStats;
@@ -1382,7 +1387,12 @@
             }
         }
 
-        mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
+        mMobileIfaces = mobileIfaces.toArray(new String[0]);
+        // TODO (b/192758557): Remove debug log.
+        if (ArrayUtils.contains(mMobileIfaces, null)) {
+            throw new NullPointerException(
+                    "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
+        }
     }
 
     private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5babfeb..f83d059 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -123,6 +123,7 @@
 import android.app.ITransientNotification;
 import android.app.ITransientNotificationCallback;
 import android.app.IUriGrantsManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -479,6 +480,8 @@
     final ArrayMap<NotificationRecord, ArrayList<CancelNotificationRunnable>> mDelayedCancelations =
             new ArrayMap<>();
 
+    private KeyguardManager mKeyguardManager;
+
     // The last key in this list owns the hardware.
     ArrayList<String> mLights = new ArrayList<>();
 
@@ -1726,6 +1729,11 @@
     }
 
     @VisibleForTesting
+    void setKeyguardManager(KeyguardManager keyguardManager) {
+        mKeyguardManager = keyguardManager;
+    }
+
+    @VisibleForTesting
     ShortcutHelper getShortcutHelper() {
         return mShortcutHelper;
     }
@@ -2330,6 +2338,7 @@
             mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
             mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+            mKeyguardManager = getContext().getSystemService(KeyguardManager.class);
             mZenModeHelper.onSystemReady();
             mRoleObserver = new RoleObserver(getContext().getSystemService(RoleManager.class),
                     mPackageManager, getContext().getMainExecutor());
@@ -6902,7 +6911,6 @@
         boolean beep = false;
         boolean blink = false;
 
-        final Notification notification = record.getSbn().getNotification();
         final String key = record.getKey();
 
         // Should this notification make noise, vibe, or use the LED?
@@ -6924,7 +6932,7 @@
         if (!record.isUpdate
                 && record.getImportance() > IMPORTANCE_MIN
                 && !suppressedByDnd) {
-            sendAccessibilityEvent(notification, record.getSbn().getPackageName());
+            sendAccessibilityEvent(record);
             sentAccessibilityEvent = true;
         }
 
@@ -6946,7 +6954,7 @@
                 boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
                 if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
                     if (!sentAccessibilityEvent) {
-                        sendAccessibilityEvent(notification, record.getSbn().getPackageName());
+                        sendAccessibilityEvent(record);
                         sentAccessibilityEvent = true;
                     }
                     if (DBG) Slog.v(TAG, "Interrupting!");
@@ -7663,17 +7671,30 @@
         return (x < low) ? low : ((x > high) ? high : x);
     }
 
-    void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
+    void sendAccessibilityEvent(NotificationRecord record) {
         if (!mAccessibilityManager.isEnabled()) {
             return;
         }
 
-        AccessibilityEvent event =
+        final Notification notification = record.getNotification();
+        final CharSequence packageName = record.getSbn().getPackageName();
+        final AccessibilityEvent event =
             AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
         event.setPackageName(packageName);
         event.setClassName(Notification.class.getName());
-        event.setParcelableData(notification);
-        CharSequence tickerText = notification.tickerText;
+        final int visibilityOverride = record.getPackageVisibilityOverride();
+        final int notifVisibility = visibilityOverride == NotificationManager.VISIBILITY_NO_OVERRIDE
+                ? notification.visibility : visibilityOverride;
+        final int userId = record.getUser().getIdentifier();
+        final boolean needPublic = userId >= 0 && mKeyguardManager.isDeviceLocked(userId);
+        if (needPublic && notifVisibility != Notification.VISIBILITY_PUBLIC) {
+            // Emit the public version if we're on the lockscreen and this notification isn't
+            // publicly visible.
+            event.setParcelableData(notification.publicVersion);
+        } else {
+            event.setParcelableData(notification);
+        }
+        final CharSequence tickerText = notification.tickerText;
         if (!TextUtils.isEmpty(tickerText)) {
             event.getText().add(tickerText);
         }
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 378405f..f6f3db3 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -238,6 +238,14 @@
             throws PackageManagerException;
 
     /**
+     * Returns {@code ApeInfo} about apex sessions that have been marked ready via
+     * {@link #markStagedSessionReady(int)}
+     *
+     * Returns empty array if there is no staged apex session or if there is any error.
+     */
+    abstract ApexInfo[] getStagedApexInfos(ApexSessionParams params);
+
+    /**
      * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
      * applied at next reboot.
      *
@@ -707,6 +715,19 @@
         }
 
         @Override
+        ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+            try {
+                return waitForApexService().getStagedApexInfos(params);
+            } catch (RemoteException re) {
+                Slog.w(TAG, "Unable to contact apexservice" + re.getMessage());
+                throw new RuntimeException(re);
+            } catch (Exception e) {
+                Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage());
+                return new ApexInfo[0];
+            }
+        }
+
+        @Override
         void markStagedSessionReady(int sessionId) throws PackageManagerException {
             try {
                 waitForApexService().markStagedSessionReady(sessionId);
@@ -1100,6 +1121,11 @@
         }
 
         @Override
+        ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
         void markStagedSessionReady(int sessionId) {
             throw new UnsupportedOperationException();
         }
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 43c5d5e..3233819 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -42,7 +42,7 @@
 per-file KeySetManagerService.java = cbrubaker@google.com, nnk@google.com
 per-file PackageKeySetData.java = cbrubaker@google.com, nnk@google.com
 per-file PackageSignatures.java = cbrubaker@google.com, nnk@google.com
-per-file SELinuxMMAC.java = cbrubaker@google.com, jeffv@google.com, jgalenson@google.com, nnk@google.com
+per-file SELinuxMMAC* = alanstokes@google.com, cbrubaker@google.com, jeffv@google.com, jgalenson@google.com
 
 # shortcuts
 per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index f8115d3..0b07bb6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -224,6 +224,10 @@
         mStagingManager = new StagingManager(this, context, apexParserSupplier);
     }
 
+    StagingManager getStagingManager() {
+        return mStagingManager;
+    }
+
     boolean okToSendBroadcasts()  {
         return mOkToSendBroadcasts;
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e4723ad..4767823 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21,14 +21,12 @@
 import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
 import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
 import static android.Manifest.permission.QUERY_ALL_PACKAGES;
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
 import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 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;
@@ -36,8 +34,6 @@
 import static android.content.Intent.EXTRA_VERSION_CODE;
 import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
 import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
-import static android.content.Intent.CATEGORY_BROWSABLE;
-import static android.content.Intent.CATEGORY_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
@@ -181,6 +177,7 @@
 import android.content.pm.IPackageManagerNative;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IStagedApexObserver;
 import android.content.pm.InstallSourceInfo;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.InstantAppRequest;
@@ -220,6 +217,7 @@
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
+import android.content.pm.StagedApexInfo;
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
@@ -14291,9 +14289,15 @@
             return new ParceledListSlice<IntentFilter>(result) {
                 @Override
                 protected void writeElement(IntentFilter parcelable, Parcel dest, int callFlags) {
-                    // IntentFilter has final Parcelable methods, so redirect to the subclass
-                    ((ParsedIntentInfo) parcelable).writeIntentInfoToParcel(dest,
-                            callFlags);
+                    parcelable.writeToParcel(dest, callFlags);
+                }
+
+                @Override
+                protected void writeParcelableCreator(IntentFilter parcelable, Parcel dest) {
+                    // All Parcel#writeParcelableCreator does is serialize the class name to
+                    // access via reflection to grab its CREATOR. This does that manually, pointing
+                    // to the parent IntentFilter so that all of the subclass fields are ignored.
+                    dest.writeString(IntentFilter.class.getName());
                 }
             };
         }
@@ -24119,6 +24123,28 @@
         public String getModuleMetadataPackageName() throws RemoteException {
             return PackageManagerService.this.mModuleInfoProvider.getPackageName();
         }
+
+        @Override
+        public void registerStagedApexObserver(IStagedApexObserver observer) {
+            mInstallerService.getStagingManager().registerStagedApexObserver(observer);
+        }
+
+        @Override
+        public void unregisterStagedApexObserver(IStagedApexObserver observer) {
+            mInstallerService.getStagingManager().unregisterStagedApexObserver(observer);
+        }
+
+        @Override
+        public String[] getStagedApexModuleNames() {
+            return mInstallerService.getStagingManager()
+                    .getStagedApexModuleNames().toArray(new String[0]);
+        }
+
+        @Override
+        @Nullable
+        public StagedApexInfo getStagedApexInfo(String moduleName) {
+            return mInstallerService.getStagingManager().getStagedApexInfo(moduleName);
+        }
     }
 
     private class PackageManagerInternalImpl extends PackageManagerInternal {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index de0e4b5..b658fe0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -596,7 +596,7 @@
 
     /** Returns true if standard APK Verity is enabled. */
     static boolean isApkVerityEnabled() {
-        return Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.R
+        return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R
                 || SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED)
                         == FSVERITY_ENABLED;
     }
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 4038bf2..02397da 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -29,7 +29,9 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.pm.ApexStagedEvent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IStagedApexObserver;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
@@ -38,6 +40,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
+import android.content.pm.StagedApexInfo;
 import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.content.rollback.IRollbackManager;
 import android.content.rollback.RollbackInfo;
@@ -58,6 +61,7 @@
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -66,8 +70,10 @@
 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.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
@@ -84,7 +90,9 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
@@ -103,7 +111,8 @@
     private final ApexManager mApexManager;
     private final PowerManager mPowerManager;
     private final Context mContext;
-    private final PreRebootVerificationHandler mPreRebootVerificationHandler;
+    @VisibleForTesting
+    final PreRebootVerificationHandler mPreRebootVerificationHandler;
     private final Supplier<PackageParser2> mPackageParserSupplier;
 
     private final File mFailureReasonFile = new File("/metadata/staged-install/failure_reason.txt");
@@ -122,6 +131,9 @@
     @GuardedBy("mSuccessfulStagedSessionIds")
     private final List<Integer> mSuccessfulStagedSessionIds = new ArrayList<>();
 
+    @GuardedBy("mStagedApexObservers")
+    private final List<IStagedApexObserver> mStagedApexObservers = new ArrayList<>();
+
     StagingManager(PackageInstallerService pi, Context context,
             Supplier<PackageParser2> packageParserSupplier) {
         mPi = pi;
@@ -184,6 +196,35 @@
         mApexManager.markBootCompleted();
     }
 
+    void registerStagedApexObserver(IStagedApexObserver observer) {
+        if (observer == null) {
+            return;
+        }
+        if  (observer.asBinder() != null) {
+            try {
+                observer.asBinder().linkToDeath(new IBinder.DeathRecipient() {
+                    @Override
+                    public void binderDied() {
+                        synchronized (mStagedApexObservers) {
+                            mStagedApexObservers.remove(observer);
+                        }
+                    }
+                }, 0);
+            } catch (RemoteException re) {
+                Slog.w(TAG, re.getMessage());
+            }
+        }
+        synchronized (mStagedApexObservers) {
+            mStagedApexObservers.add(observer);
+        }
+    }
+
+    void unregisterStagedApexObserver(IStagedApexObserver observer) {
+        synchronized (mStagedApexObservers) {
+            mStagedApexObservers.remove(observer);
+        }
+    }
+
     /**
      * Validates the signature used to sign the container of the new apex package
      *
@@ -1075,6 +1116,9 @@
                     Slog.w(TAG, "Could not contact apexd to abort staged session " + sessionId);
                 }
             }
+            if (sessionContainsApex(session)) {
+                notifyStagedApexObservers();
+            }
         }
 
         // Session was successfully aborted from apexd (if required) and pre-reboot verification
@@ -1299,7 +1343,107 @@
         return session;
     }
 
-    private final class PreRebootVerificationHandler extends Handler {
+    /**
+     * Returns ApexInfo about APEX contained inside the session as a {@code Map<String, ApexInfo>},
+     * where the key of the map is the module name of the ApexInfo.
+     *
+     * Returns an empty map if there is any error.
+     */
+    @VisibleForTesting
+    @NonNull
+    Map<String, ApexInfo> getStagedApexInfos(@NonNull PackageInstallerSession session) {
+        Preconditions.checkArgument(session != null, "Session is null");
+        Preconditions.checkArgument(!session.hasParentSessionId(),
+                session.sessionId + " session has parent session");
+        Preconditions.checkArgument(sessionContainsApex(session),
+                session.sessionId + " session does not contain apex");
+
+        // Even if caller calls this method on ready session, the session could be abandoned
+        // right after this method is called.
+        if (!session.isStagedSessionReady() || session.isDestroyed()) {
+            return Collections.emptyMap();
+        }
+
+        ApexSessionParams params = new ApexSessionParams();
+        params.sessionId = session.sessionId;
+        final IntArray childSessionIds = new IntArray();
+        if (session.isMultiPackage()) {
+            for (int id : session.getChildSessionIds()) {
+                if (isApexSession(getStagedSession(id))) {
+                    childSessionIds.add(id);
+                }
+            }
+        }
+        params.childSessionIds = childSessionIds.toArray();
+
+        ApexInfo[] infos = mApexManager.getStagedApexInfos(params);
+        Map<String, ApexInfo> result = new ArrayMap<>();
+        for (ApexInfo info : infos) {
+            result.put(info.moduleName, info);
+        }
+        return result;
+    }
+
+    /**
+     * Returns apex module names of all packages that are staged ready
+     */
+    List<String> getStagedApexModuleNames() {
+        List<String> result = new ArrayList<>();
+        synchronized (mStagedSessions) {
+            for (int i = 0; i < mStagedSessions.size(); i++) {
+                final PackageInstallerSession session = mStagedSessions.valueAt(i);
+                if (!session.isStagedSessionReady() || session.isDestroyed()
+                        || session.hasParentSessionId() || !sessionContainsApex(session)) {
+                    continue;
+                }
+                result.addAll(getStagedApexInfos(session).keySet());
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns ApexInfo of the {@code moduleInfo} provided if it is staged, otherwise returns null.
+     */
+    @Nullable
+    StagedApexInfo getStagedApexInfo(String moduleName) {
+        synchronized (mStagedSessions) {
+            for (int i = 0; i < mStagedSessions.size(); i++) {
+                final PackageInstallerSession session = mStagedSessions.valueAt(i);
+                if (!session.isStagedSessionReady() || session.isDestroyed()
+                        || session.hasParentSessionId() || !sessionContainsApex(session)) {
+                    continue;
+                }
+                ApexInfo ai = getStagedApexInfos(session).get(moduleName);
+                if (ai != null) {
+                    StagedApexInfo info = new StagedApexInfo();
+                    info.moduleName = ai.moduleName;
+                    info.diskImagePath = ai.modulePath;
+                    info.versionCode = ai.versionCode;
+                    info.versionName = ai.versionName;
+                    return info;
+                }
+            }
+        }
+        return null;
+    }
+
+    private void notifyStagedApexObservers() {
+        synchronized (mStagedApexObservers) {
+            for (IStagedApexObserver observer : mStagedApexObservers) {
+                ApexStagedEvent event = new ApexStagedEvent();
+                event.stagedApexModuleNames = getStagedApexModuleNames().toArray(new String[0]);
+                try {
+                    observer.onApexStaged(event);
+                } catch (RemoteException re) {
+                    Slog.w(TAG, "Failed to contact the observer " + re.getMessage());
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    final class PreRebootVerificationHandler extends Handler {
         // Hold session ids before handler gets ready to do the verification.
         private IntArray mPendingSessionIds;
         private boolean mIsReady;
@@ -1327,7 +1471,8 @@
         private static final int MSG_PRE_REBOOT_VERIFICATION_START = 1;
         private static final int MSG_PRE_REBOOT_VERIFICATION_APEX = 2;
         private static final int MSG_PRE_REBOOT_VERIFICATION_APK = 3;
-        private static final int MSG_PRE_REBOOT_VERIFICATION_END = 4;
+        @VisibleForTesting
+        static final int MSG_PRE_REBOOT_VERIFICATION_END = 4;
 
         @Override
         public void handleMessage(Message msg) {
@@ -1579,6 +1724,7 @@
                 if (hasApex) {
                     try {
                         mApexManager.markStagedSessionReady(session.sessionId);
+                        notifyStagedApexObservers();
                     } catch (PackageManagerException e) {
                         session.setStagedSessionFailed(e.error, e.getMessage());
                         return;
diff --git a/services/core/java/com/android/server/policy/DisplayFoldDurationLogger.java b/services/core/java/com/android/server/policy/DisplayFoldDurationLogger.java
index bdcd2cd..3524d7f 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldDurationLogger.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldDurationLogger.java
@@ -44,8 +44,8 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface ScreenState {}
 
-    private @ScreenState int mScreenState = SCREEN_STATE_UNKNOWN;
-    private Long mLastChanged = null;
+    private volatile @ScreenState int mScreenState = SCREEN_STATE_UNKNOWN;
+    private volatile Long mLastChanged = null;
 
     private static final int LOG_SUBTYPE_UNFOLDED = 0;
     private static final int LOG_SUBTYPE_FOLDED = 1;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 836e615..ae940d0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -608,6 +608,8 @@
 
     private int mPowerButtonSuppressionDelayMillis = POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS;
 
+    private boolean mLockNowPending = false;
+
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -4941,6 +4943,7 @@
                     mKeyguardDelegate.doKeyguardTimeout(options);
                 }
                 mLockScreenTimerActive = false;
+                mLockNowPending = false;
                 options = null;
             }
         }
@@ -4950,7 +4953,7 @@
         }
     }
 
-    ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
+    final ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout();
 
     @Override
     public void lockNow(Bundle options) {
@@ -4962,6 +4965,9 @@
             mScreenLockTimeout.setLockOptions(options);
         }
         mHandler.post(mScreenLockTimeout);
+        synchronized (mScreenLockTimeout) {
+            mLockNowPending = true;
+        }
     }
 
     // TODO (b/113840485): Move this logic to DisplayPolicy when lockscreen supports multi-display.
@@ -4977,6 +4983,10 @@
 
     private void updateLockScreenTimeout() {
         synchronized (mScreenLockTimeout) {
+            if (mLockNowPending) {
+                Log.w(TAG, "lockNow pending, ignore updating lockscreen timeout");
+                return;
+            }
             final boolean enable = !mAllowLockscreenWhenOnDisplays.isEmpty()
                     && mDefaultDisplayPolicy.isAwake()
                     && mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 061fabf..e927667 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3756,7 +3756,10 @@
         if (sQuiescent) {
             // Pass the optional "quiescent" argument to the bootloader to let it know
             // that it should not turn the screen/lights on.
-            reason = reason + ",quiescent";
+            if (reason != ""){
+                reason += ",";
+            }
+            reason = reason + "quiescent";
         }
 
         SystemProperties.set("sys.powerctl", "reboot," + reason);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 392792d..b75bce8 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -662,6 +662,12 @@
 
         @Override
         public String getDefaultSmsPackage(int userId) {
+            userId = handleIncomingUser(userId, false, "getDefaultSmsPackage");
+            if (!mUserManagerInternal.exists(userId)) {
+                Slog.e(LOG_TAG, "user " + userId + " does not exist");
+                return null;
+            }
+
             long identity = Binder.clearCallingIdentity();
             try {
                 return CollectionUtils.firstOrNull(
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 225bd82..a690647 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -60,7 +60,7 @@
     private final IBinder mService = new IFileIntegrityService.Stub() {
         @Override
         public boolean isApkVeritySupported() {
-            return Build.VERSION.FIRST_SDK_INT >= Build.VERSION_CODES.R
+            return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R
                     || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
         }
 
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 5decf5e..71b3e61 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -102,6 +102,7 @@
 import android.os.IStoraged;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
+import android.os.OutcomeReceiver;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -172,6 +173,7 @@
 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;
@@ -1731,22 +1733,47 @@
     int pullModemActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
         long token = Binder.clearCallingIdentity();
         try {
-            SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
-            mTelephony.requestModemActivityInfo(modemReceiver);
-            final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver);
+            CompletableFuture<ModemActivityInfo> modemFuture = new CompletableFuture<>();
+            mTelephony.requestModemActivityInfo(Runnable::run,
+                    new OutcomeReceiver<ModemActivityInfo,
+                            TelephonyManager.ModemActivityInfoException>() {
+                        @Override
+                        public void onResult(ModemActivityInfo result) {
+                            modemFuture.complete(result);
+                        }
+
+                        @Override
+                        public void onError(TelephonyManager.ModemActivityInfoException e) {
+                            Slog.w(TAG, "error reading modem stats:" + e);
+                            modemFuture.complete(null);
+                        }
+                    });
+
+            ModemActivityInfo modemInfo;
+            try {
+                modemInfo = modemFuture.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
+                        TimeUnit.MILLISECONDS);
+            } catch (TimeoutException | InterruptedException e) {
+                Slog.w(TAG, "timeout or interrupt reading modem stats: " + e);
+                return StatsManager.PULL_SKIP;
+            } catch (ExecutionException e) {
+                Slog.w(TAG, "exception reading modem stats: " + e.getCause());
+                return StatsManager.PULL_SKIP;
+            }
+
             if (modemInfo == null) {
                 return StatsManager.PULL_SKIP;
             }
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
-                    .writeLong(modemInfo.getTimestamp())
+                    .writeLong(modemInfo.getTimestampMillis())
                     .writeLong(modemInfo.getSleepTimeMillis())
                     .writeLong(modemInfo.getIdleTimeMillis())
-                    .writeLong(modemInfo.getTransmitPowerInfo().get(0).getTimeInMillis())
-                    .writeLong(modemInfo.getTransmitPowerInfo().get(1).getTimeInMillis())
-                    .writeLong(modemInfo.getTransmitPowerInfo().get(2).getTimeInMillis())
-                    .writeLong(modemInfo.getTransmitPowerInfo().get(3).getTimeInMillis())
-                    .writeLong(modemInfo.getTransmitPowerInfo().get(4).getTimeInMillis())
+                    .writeLong(modemInfo.getTransmitDurationMillisAtPowerLevel(0))
+                    .writeLong(modemInfo.getTransmitDurationMillisAtPowerLevel(1))
+                    .writeLong(modemInfo.getTransmitDurationMillisAtPowerLevel(2))
+                    .writeLong(modemInfo.getTransmitDurationMillisAtPowerLevel(3))
+                    .writeLong(modemInfo.getTransmitDurationMillisAtPowerLevel(4))
                     .writeLong(modemInfo.getReceiveTimeMillis())
                     .build();
             pulledData.add(e);
@@ -3362,7 +3389,11 @@
     int pullFaceSettingsLocked(int atomTag, List<StatsEvent> pulledData) {
         final long callingToken = Binder.clearCallingIdentity();
         try {
-            List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
+            UserManager manager = mContext.getSystemService(UserManager.class);
+            if (manager == null) {
+                return StatsManager.PULL_SKIP;
+            }
+            List<UserInfo> users = manager.getUsers();
             int numUsers = users.size();
             FaceManager faceManager = mContext.getSystemService(FaceManager.class);
 
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index bba5dcb..630317a 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -114,6 +114,8 @@
     private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
     private final List<Message> mPendingHdmiDeviceEvents = new LinkedList<>();
 
+    private final List<Message> mPendingTvinputInfoEvents = new LinkedList<>();
+
     // Calls to mListener should happen here.
     private final Handler mHandler = new ListenerHandler();
 
@@ -229,7 +231,16 @@
                             connection.getInputStateLocked(), 0, inputId).sendToTarget();
                     }
                 }
-            }
+            } else {
+                Message msg = mHandler.obtainMessage(ListenerHandler.TVINPUT_INFO_ADDED,
+                    deviceId, cableConnectionStatus, connection);
+                for (Iterator<Message> it = mPendingTvinputInfoEvents.iterator(); it.hasNext();) {
+                    if (it.next().arg1 == deviceId) {
+                    it.remove();
+                    }
+                }
+                mPendingTvinputInfoEvents.add(msg);
+           }
             ITvInputHardwareCallback callback = connection.getCallbackLocked();
             if (callback != null) {
                 try {
@@ -288,6 +299,8 @@
             }
             mHardwareInputIdMap.put(deviceId, info.getId());
             mInputMap.put(info.getId(), info);
+            processPendingTvInputInfoEventsLocked();
+            Slog.d(TAG,"deviceId ="+ deviceId+", tvinputinfo = "+info);
 
             // Process pending state changes
 
@@ -529,6 +542,20 @@
         }
     }
 
+
+    private void processPendingTvInputInfoEventsLocked() {
+        for (Iterator<Message> it = mPendingTvinputInfoEvents.iterator(); it.hasNext(); ) {
+            Message msg = it.next();
+            int deviceId =  msg.arg1;
+            String inputId = mHardwareInputIdMap.get(deviceId);
+            if (inputId != null) {
+                msg.sendToTarget();
+                it.remove();
+            }
+        }
+    }
+
+
     private void updateVolume() {
         mCurrentMaxIndex = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
         mCurrentIndex = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
@@ -1181,6 +1208,7 @@
         private static final int HDMI_DEVICE_ADDED = 4;
         private static final int HDMI_DEVICE_REMOVED = 5;
         private static final int HDMI_DEVICE_UPDATED = 6;
+        private static final int TVINPUT_INFO_ADDED = 7;
 
         @Override
         public final void handleMessage(Message msg) {
@@ -1225,6 +1253,31 @@
                     }
                     break;
                 }
+                case TVINPUT_INFO_ADDED: {
+                    int deviceId = msg.arg1;
+                    int cableConnectionStatus = msg.arg2;
+                    Connection connection =(Connection)msg.obj;
+
+                    int previousConfigsLength = connection.getConfigsLengthLocked();
+                    int previousCableConnectionStatus = connection.getInputStateLocked();
+                    String inputId = mHardwareInputIdMap.get(deviceId);
+
+                    if (inputId != null) {
+                        if (connection.updateCableConnectionStatusLocked(cableConnectionStatus)) {
+                            if (previousCableConnectionStatus != connection.getInputStateLocked()) {
+                                mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+                                    connection.getInputStateLocked(), 0, inputId).sendToTarget();
+                            }
+                        } else {
+                            if ((previousConfigsLength == 0)
+                                    != (connection.getConfigsLengthLocked() == 0)) {
+                                mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+                                    connection.getInputStateLocked(), 0, inputId).sendToTarget();
+                            }
+                        }
+                    }
+                    break;
+                }
                 default: {
                     Slog.w(TAG, "Unhandled message: " + msg);
                     break;
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 9c3721b1..e0cc8e1 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -352,7 +352,7 @@
     }
 
     private void handleSafeModeStatusChanged() {
-        logDbg("VcnGatewayConnection safe mode status changed");
+        logVdbg("VcnGatewayConnection safe mode status changed");
         boolean hasSafeModeGatewayConnection = false;
 
         // If any VcnGatewayConnection is in safe mode, mark the entire VCN as being in safe mode
@@ -368,7 +368,7 @@
                 hasSafeModeGatewayConnection ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
         if (oldStatus != mCurrentStatus) {
             mVcnCallback.onSafeModeStatusChanged(hasSafeModeGatewayConnection);
-            logDbg(
+            logInfo(
                     "Safe mode "
                             + (mCurrentStatus == VCN_STATUS_CODE_SAFE_MODE ? "entered" : "exited"));
         }
@@ -539,6 +539,16 @@
         Slog.d(TAG, getLogPrefix() + msg, tr);
     }
 
+    private void logInfo(String msg) {
+        Slog.i(TAG, getLogPrefix() + msg);
+        LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg);
+    }
+
+    private void logInfo(String msg, Throwable tr) {
+        Slog.i(TAG, getLogPrefix() + msg, tr);
+        LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg + tr);
+    }
+
     private void logErr(String msg) {
         Slog.e(TAG, getLogPrefix() + msg);
         LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg);
@@ -596,7 +606,12 @@
     /** Retrieves the network score for a VCN Network */
     // Package visibility for use in VcnGatewayConnection and VcnNetworkProvider
     static NetworkScore getNetworkScore() {
-        return new NetworkScore.Builder().setLegacyInt(VCN_LEGACY_SCORE_INT).build();
+        // TODO(b/193687515): Stop setting TRANSPORT_PRIMARY, define a TRANSPORT_VCN, and set in
+        //                    NetworkOffer/NetworkAgent.
+        return new NetworkScore.Builder()
+                .setLegacyInt(VCN_LEGACY_SCORE_INT)
+                .setTransportPrimary(true)
+                .build();
     }
 
     /** Callback used for passing status signals from a VcnGatewayConnection to its managing Vcn. */
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 3c0a05b..7dec4e7 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -195,6 +195,7 @@
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static final int SAFEMODE_TIMEOUT_SECONDS = 30;
+    private static final int SAFEMODE_TIMEOUT_SECONDS_TEST_MODE = 10;
 
     private interface EventInfo {}
 
@@ -1082,7 +1083,9 @@
                 createScheduledAlarm(
                         SAFEMODE_TIMEOUT_ALARM,
                         delayedMessage,
-                        TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
+                        mVcnContext.isInTestMode()
+                                ? TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS_TEST_MODE)
+                                : TimeUnit.SECONDS.toMillis(SAFEMODE_TIMEOUT_SECONDS));
     }
 
     private void cancelSafeModeAlarm() {
@@ -1674,10 +1677,8 @@
             mFailedAttempts = 0;
             cancelSafeModeAlarm();
 
-            if (mIsInSafeMode) {
-                mIsInSafeMode = false;
-                mGatewayStatusCallback.onSafeModeStatusChanged();
-            }
+            mIsInSafeMode = false;
+            mGatewayStatusCallback.onSafeModeStatusChanged();
         }
 
         protected void applyTransform(
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 113797c..419a7fa 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1468,7 +1468,7 @@
         final Task targetTask = r.getTask() != null
                 ? r.getTask()
                 : mTargetTask;
-        if (startedActivityStack == null || targetTask == null) {
+        if (startedActivityStack == null || targetTask == null || !targetTask.isAttached()) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index ddad1db..eaf7693 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3372,7 +3372,7 @@
     }
 
     /**
-     * Find all task stacks containing {@param userId} and intercept them with an activity
+     * Find all visible task stacks containing {@param userId} and intercept them with an activity
      * to block out the contents and possibly start a credential-confirming intent.
      *
      * @param userId user handle for the locked managed profile.
@@ -3380,18 +3380,42 @@
     void lockAllProfileTasks(@UserIdInt int userId) {
         mService.deferWindowLayout();
         try {
-            forAllLeafTasks(task -> {
-                if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId)
-                        != null) {
-                    mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
-                            task.mTaskId, userId);
-                }
-            }, true /* traverseTopToBottom */);
+            final PooledConsumer c = PooledLambda.obtainConsumer(
+                    RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
+                    userId);
+            forAllLeafTasks(c, true /* traverseTopToBottom */);
+            c.recycle();
         } finally {
             mService.continueWindowLayout();
         }
     }
 
+    /**
+     * Detects whether we should show a lock screen in front of this task for a locked user.
+     * <p>
+     * We'll do this if either of the following holds:
+     * <ul>
+     *   <li>The top activity explicitly belongs to {@param userId}.</li>
+     *   <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
+     * </ul>
+     *
+     * @return {@code true} if the top activity looks like it belongs to {@param userId}.
+     */
+    private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
+        // To handle the case that work app is in the task but just is not the top one.
+        final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
+        final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
+
+        // Check the task for a top activity belonging to userId, or returning a
+        // result to an activity belonging to userId. Example case: a document
+        // picker for personal files, opened by a work app, should still get locked.
+        if ((activityRecord != null && activityRecord.mUserId == userId)
+                || (resultTo != null && resultTo.mUserId == userId)) {
+            mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
+                    task.mTaskId, userId);
+        }
+    }
+
     void cancelInitializingActivities() {
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             final DisplayContent display = getChildAt(displayNdx);
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index e6a35f1..1f8a437 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -908,7 +908,7 @@
                 final int displayId = r.getDisplayId();
                 final Context c = root.getDisplayUiContext(displayId);
 
-                if (r.mVisibleRequested && !displayContexts.contains(c)) {
+                if (c != null && r.mVisibleRequested && !displayContexts.contains(c)) {
                     displayContexts.add(c);
                 }
             }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index a0c96f0..f2f6b1d 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -158,7 +158,7 @@
         "android.hardware.input.classifier@1.0",
         "android.hardware.ir@1.0",
         "android.hardware.light@2.0",
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
         "android.hardware.power-V1-cpp",
@@ -176,7 +176,7 @@
         "android.frameworks.stats@1.0",
         "android.system.suspend.control-V1-cpp",
         "android.system.suspend.control.internal-cpp",
-        "android.system.suspend@1.0",
+        "android.system.suspend-V1-ndk",
         "service.incremental",
     ],
 
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 7a6d310..4922b2c 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -18,11 +18,12 @@
 
 //#define LOG_NDEBUG 0
 
+#include <aidl/android/system/suspend/ISystemSuspend.h>
+#include <aidl/android/system/suspend/IWakeLock.h>
 #include <android/hardware/power/1.1/IPower.h>
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
 #include <android/hardware/power/Mode.h>
-#include <android/system/suspend/1.0/ISystemSuspend.h>
 #include <android/system/suspend/ISuspendControlService.h>
 #include <android/system/suspend/internal/ISuspendControlServiceInternal.h>
 #include <nativehelper/JNIHelp.h>
@@ -33,6 +34,7 @@
 #include <limits.h>
 
 #include <android-base/chrono_utils.h>
+#include <android/binder_manager.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
 #include <binder/IServiceManager.h>
@@ -40,23 +42,23 @@
 #include <hardware/power.h>
 #include <hardware_legacy/power.h>
 #include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/misc.h>
-#include <utils/String8.h>
-#include <utils/Log.h>
 
 #include "com_android_server_power_PowerManagerService.h"
 
+using aidl::android::system::suspend::ISystemSuspend;
+using aidl::android::system::suspend::IWakeLock;
+using aidl::android::system::suspend::WakeLockType;
+using android::String8;
 using android::hardware::Return;
 using android::hardware::Void;
 using android::hardware::power::Boost;
 using android::hardware::power::Mode;
-using android::hardware::power::V1_0::PowerHint;
 using android::hardware::power::V1_0::Feature;
-using android::String8;
-using android::system::suspend::V1_0::ISystemSuspend;
-using android::system::suspend::V1_0::IWakeLock;
-using android::system::suspend::V1_0::WakeLockType;
+using android::hardware::power::V1_0::PowerHint;
 using android::system::suspend::ISuspendControlService;
 using IPowerV1_1 = android::hardware::power::V1_1::IPower;
 using IPowerV1_0 = android::hardware::power::V1_0::IPower;
@@ -352,20 +354,21 @@
     }
 }
 
-static sp<ISystemSuspend> gSuspendHal = nullptr;
+static std::shared_ptr<ISystemSuspend> gSuspendHal = nullptr;
 static sp<ISuspendControlService> gSuspendControl = nullptr;
 static sp<system::suspend::internal::ISuspendControlServiceInternal> gSuspendControlInternal =
         nullptr;
-static sp<IWakeLock> gSuspendBlocker = nullptr;
+static std::shared_ptr<IWakeLock> gSuspendBlocker = nullptr;
 static std::mutex gSuspendMutex;
 
 // Assume SystemSuspend HAL is always alive.
 // TODO: Force device to restart if SystemSuspend HAL dies.
-sp<ISystemSuspend> getSuspendHal() {
+std::shared_ptr<ISystemSuspend> getSuspendHal() {
     static std::once_flag suspendHalFlag;
-    std::call_once(suspendHalFlag, [](){
-        ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
-        gSuspendHal = ISystemSuspend::getService();
+    std::call_once(suspendHalFlag, []() {
+        const std::string suspendInstance = std::string() + ISystemSuspend::descriptor + "/default";
+        gSuspendHal = ISystemSuspend::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(suspendInstance.c_str())));
         assert(gSuspendHal != nullptr);
     });
     return gSuspendHal;
@@ -403,7 +406,7 @@
         std::lock_guard<std::mutex> lock(gSuspendMutex);
         if (gSuspendBlocker) {
             gSuspendBlocker->release();
-            gSuspendBlocker.clear();
+            gSuspendBlocker = nullptr;
         }
     }
 }
@@ -411,9 +414,10 @@
 void disableAutoSuspend() {
     std::lock_guard<std::mutex> lock(gSuspendMutex);
     if (!gSuspendBlocker) {
-        sp<ISystemSuspend> suspendHal = getSuspendHal();
-        gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
-                "PowerManager.SuspendLockout");
+        std::shared_ptr<ISystemSuspend> suspendHal = getSuspendHal();
+        suspendHal->acquireWakeLock(WakeLockType::PARTIAL, "PowerManager.SuspendLockout",
+                                    &gSuspendBlocker);
+        assert(gSuspendBlocker != nullptr);
     }
 }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d908945..5dfa86e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -10314,7 +10314,7 @@
     }
 
     @Override
-    public boolean setPermittedAccessibilityServices(ComponentName who, List packageList) {
+    public boolean setPermittedAccessibilityServices(ComponentName who, List<String> packageList) {
         if (!mHasFeature) {
             return false;
         }
@@ -10367,7 +10367,7 @@
     }
 
     @Override
-    public List getPermittedAccessibilityServices(ComponentName who) {
+    public List<String> getPermittedAccessibilityServices(ComponentName who) {
         if (!mHasFeature) {
             return null;
         }
@@ -10381,7 +10381,7 @@
     }
 
     @Override
-    public List getPermittedAccessibilityServicesForUser(int userId) {
+    public List<String> getPermittedAccessibilityServicesForUser(int userId) {
         if (!mHasFeature) {
             return null;
         }
@@ -10465,7 +10465,7 @@
     }
 
     @Override
-    public boolean setPermittedInputMethods(ComponentName who, List packageList) {
+    public boolean setPermittedInputMethods(ComponentName who, List<String> packageList) {
         if (!mHasFeature) {
             return false;
         }
@@ -10505,7 +10505,7 @@
     }
 
     @Override
-    public List getPermittedInputMethods(ComponentName who) {
+    public List<String> getPermittedInputMethods(ComponentName who) {
         if (!mHasFeature) {
             return null;
         }
@@ -10519,7 +10519,7 @@
     }
 
     @Override
-    public List getPermittedInputMethodsForCurrentUser() {
+    public List<String> getPermittedInputMethodsForCurrentUser() {
         enforceManageUsers();
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index 1a96048..bf1a64e 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -65,7 +65,6 @@
         "libincremental_manager_aidl-cpp",
         "libprotobuf-cpp-lite",
         "service.incremental.proto",
-        "libutils",
         "libvold_binder",
         "libc++fs",
     ],
@@ -77,6 +76,7 @@
         "libincfs",
         "liblog",
         "libpermission",
+        "libutils",
         "libz",
         "libziparchive",
     ],
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 99a35ad..2b5f98b 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -132,7 +132,7 @@
     } mLooper;
 };
 
-class RealIncFs : public IncFsWrapper {
+class RealIncFs final : public IncFsWrapper {
 public:
     RealIncFs() = default;
     ~RealIncFs() final = default;
@@ -185,7 +185,7 @@
 
 static JNIEnv* getOrAttachJniEnv(JavaVM* jvm);
 
-class RealTimedQueueWrapper : public TimedQueueWrapper {
+class RealTimedQueueWrapper final : public TimedQueueWrapper {
 public:
     RealTimedQueueWrapper(JavaVM* jvm) {
         mThread = std::thread([this, jvm]() {
diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java
index a2768c6..3a9b2dc 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.content.Context;
 import android.os.ISystemConfig;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
@@ -84,6 +85,21 @@
             }
             return ArrayUtils.convertToIntArray(uids);
         }
+
+        @Override
+        public List<String> getEnabledComponentOverrides(String packageName) {
+            ArrayMap<String, Boolean> systemComponents = SystemConfig.getInstance()
+                    .getComponentsEnabledStates(packageName);
+            List<String> enabledComponent = new ArrayList<>();
+            if (systemComponents != null) {
+                for (Map.Entry<String, Boolean> entry : systemComponents.entrySet()) {
+                    if (Boolean.TRUE.equals(entry.getValue())) {
+                        enabledComponent.add(entry.getKey());
+                    }
+                }
+            }
+            return enabledComponent;
+        }
     };
 
     public SystemConfigService(Context context) {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 5a5f504..ad445f1 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -52,7 +52,6 @@
         // classes generated by netd_aidl_interfaces-platform-java above.
         "netd_aidl_interface-V3-java",
         "networkstack-client",
-        "modules-utils-build_system",
     ],
     apex_available: [
         "com.android.wifi",
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 9706d7f..fdf23d3 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -37,6 +37,7 @@
 import android.provider.DeviceConfig;
 import android.util.Log;
 
+import com.android.internal.R;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -58,9 +59,7 @@
 
     private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
 
-    private static final long BG_PROCESS_PERIOD = DEBUG
-            ? TimeUnit.MINUTES.toMillis(1)
-            : TimeUnit.DAYS.toMillis(1);
+    private static final long BG_PROCESS_PERIOD = TimeUnit.DAYS.toMillis(1); // every 1 day.
 
     private IProfCollectd mIProfcollect;
     private static ProfcollectForwardingService sSelfService;
@@ -285,6 +284,11 @@
         updateEngine.bind(new UpdateEngineCallback() {
             @Override
             public void onStatusUpdate(int status, float percent) {
+                if (DEBUG) {
+                    Log.d(LOG_TAG, "Received OTA status update, status: " + status + ", percent: "
+                            + percent);
+                }
+
                 if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
                     packProfileReport();
                 }
@@ -302,8 +306,15 @@
             return;
         }
 
+        if (!getUploaderEnabledConfig(getContext())) {
+            return;
+        }
+
         new Thread(() -> {
             try {
+                Context context = getContext();
+                final String uploaderPkg = getUploaderPackageName(context);
+                final String uploaderAction = getUploaderActionName(context);
                 String reportUuid = mIProfcollect.report();
 
                 final int profileId = getBBProfileId();
@@ -317,13 +328,12 @@
                 }
 
                 Intent uploadIntent =
-                        new Intent("com.google.android.apps.betterbug.intent.action.UPLOAD_PROFILE")
-                        .setPackage("com.google.android.apps.internal.betterbug")
+                        new Intent(uploaderAction)
+                        .setPackage(uploaderPkg)
                         .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
                         .putExtra("EXTRA_PACKAGE_NAME", getContext().getPackageName())
                         .putExtra("EXTRA_PROFILE_PATH", reportPath)
                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                Context context = getContext();
 
                 List<ResolveInfo> receivers =
                         context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
@@ -356,4 +366,19 @@
         }
         return UserHandle.USER_SYSTEM;
     }
+
+    private boolean getUploaderEnabledConfig(Context context) {
+        return context.getResources().getBoolean(
+            R.bool.config_profcollectReportUploaderEnabled);
+    }
+
+    private String getUploaderPackageName(Context context) {
+        return context.getResources().getString(
+            R.string.config_defaultProfcollectReportUploaderApp);
+    }
+
+    private String getUploaderActionName(Context context) {
+        return context.getResources().getString(
+            R.string.config_defaultProfcollectReportUploaderAction);
+    }
 }
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 5ecf6bb..6e01f69 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -79,7 +79,6 @@
 
     // These are not normally accessible from apps so they must be explicitly included.
     jni_libs: [
-        "libbacktrace",
         "libbase",
         "libbinder",
         "libc++",
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 3e5cbea..c45d084 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -125,7 +125,7 @@
         mMessageValidator =
                 new HdmiCecMessageValidator(mHdmiControlService) {
                     @Override
-                    int isValid(HdmiCecMessage message) {
+                    int isValid(HdmiCecMessage message, boolean isMessageReceived) {
                         return HdmiCecMessageValidator.OK;
                     }
                 };
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageTest.java
new file mode 100755
index 0000000..036d084
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.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 HdmiCecMessage} class. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class HdmiCecMessageTest {
+
+    @Test
+    public void testEqualsHdmiCecMessage() {
+        int source = 0;
+        int destination = 1;
+        int opcode = 0x7f;
+        byte[] params1 = {0x00, 0x1a, 0x2b, 0x3c};
+        byte[] params2 = {0x00, 0x1a, 0x2b, 0x3c, 0x4d};
+
+        new EqualsTester()
+                .addEqualityGroup(
+                        new HdmiCecMessage(source, destination, opcode, params1),
+                        new HdmiCecMessage(source, destination, opcode, params1))
+                .addEqualityGroup(new HdmiCecMessage(source, destination, opcode, params2))
+                .addEqualityGroup(new HdmiCecMessage(source + 1, destination, opcode, params1))
+                .addEqualityGroup(new HdmiCecMessage(source, destination + 1, opcode, params1))
+                .addEqualityGroup(new HdmiCecMessage(source, destination, opcode + 1, params1))
+                .testEquals();
+    }
+}
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 ae7f422..ae99dab 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -629,7 +629,7 @@
     }
 
     private IntegerSubject assertMessageValidity(String message) {
-        return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
+        return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message), false));
     }
 
     /**
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 51b513f..7bcfeb6 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
@@ -126,6 +126,35 @@
     }
 
     @Test
+    public void testEqualsDeviceConfig() {
+        String name = "Name";
+
+        CodecSad expectedCodec1 = new CodecSad(Constants.AUDIO_CODEC_LPCM, "011a03");
+        CodecSad expectedCodec2 = new CodecSad(Constants.AUDIO_CODEC_DD, "0d0506");
+        CodecSad expectedCodec3 = new CodecSad(Constants.AUDIO_CODEC_LPCM, "010203");
+        CodecSad expectedCodec4 = new CodecSad(Constants.AUDIO_CODEC_DD, "040506");
+
+        List<CodecSad> list1 = new ArrayList();
+        list1.add(expectedCodec1);
+        list1.add(expectedCodec2);
+        list1.add(expectedCodec3);
+
+        List<CodecSad> list1Duplicate = new ArrayList(list1);
+
+        List<CodecSad> list2 = new ArrayList(list1);
+        list2.add(expectedCodec4);
+
+        new EqualsTester()
+                .addEqualityGroup(
+                        new HdmiUtils.DeviceConfig(name, list1),
+                        new HdmiUtils.DeviceConfig(name, list1Duplicate))
+                .addEqualityGroup(new HdmiUtils.DeviceConfig(name, list2))
+                .addEqualityGroup(new HdmiUtils.DeviceConfig("my" + name, list1))
+                .addEqualityGroup(new HdmiUtils.DeviceConfig("my" + name, list2))
+                .testEquals();
+    }
+
+    @Test
     public void parseSampleXML() {
         List<DeviceConfig> config = new ArrayList<>();
         try {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 72afca0..b6f7922 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -37,6 +37,7 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -228,6 +229,21 @@
     }
 
     @Test
+    public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException {
+        doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any());
+
+        assertThrows(RuntimeException.class,
+                () -> mApexManager.getStagedApexInfos(testParamsWithChildren()));
+    }
+
+    @Test
+    public void testGetStagedApexInfos_returnsEmptyArrayOnError() throws RemoteException {
+        doThrow(ServiceSpecificException.class).when(mApexService).getStagedApexInfos(any());
+
+        assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0);
+    }
+
+    @Test
     public void testMarkStagedSessionReady_throwPackageManagerException() throws RemoteException {
         doAnswer(invocation -> {
             throw new Exception();
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
index e15b5f5..2f51994 100644
--- a/services/tests/servicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -1,3 +1,7 @@
 include /services/core/java/com/android/server/pm/OWNERS
 
 per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+
+# apex support
+per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
+
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 541fc63..2448026 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -55,7 +55,6 @@
     jni_libs: [
         "libdexmakerjvmtiagent",
         "libmultiplejvmtiagentsinterferenceagent",
-        "libbacktrace",
         "libbase",
         "libbinder",
         "libc++",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index ad15a99..11ea4a4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -46,6 +46,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.Notification.Builder;
 import android.app.NotificationChannel;
@@ -103,6 +104,8 @@
     NotificationUsageStats mUsageStats;
     @Mock
     IAccessibilityManager mAccessibilityService;
+    @Mock
+    KeyguardManager mKeyguardManager;
     NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
     private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
             1 << 30);
@@ -147,6 +150,7 @@
         when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
+        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);
 
         long serviceReturnValue = IntPair.of(
                 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
@@ -168,6 +172,7 @@
         mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
         mService.setUsageStats(mUsageStats);
         mService.setAccessibilityManager(accessibilityManager);
+        mService.setKeyguardManager(mKeyguardManager);
         mService.mScreenOn = false;
         mService.mInCallStateOffHook = false;
         mService.mNotificationPulseEnabled = true;
@@ -484,6 +489,94 @@
     }
 
     @Test
+    public void testLockedPrivateA11yRedaction() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
+        r.getNotification().visibility = Notification.VISIBILITY_PRIVATE;
+        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
+        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+        when(accessibilityManager.isEnabled()).thenReturn(true);
+        mService.setAccessibilityManager(accessibilityManager);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        ArgumentCaptor<AccessibilityEvent> eventCaptor =
+                ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+        verify(accessibilityManager, times(1))
+                .sendAccessibilityEvent(eventCaptor.capture());
+
+        AccessibilityEvent event = eventCaptor.getValue();
+        assertEquals(r.getNotification().publicVersion, event.getParcelableData());
+    }
+
+    @Test
+    public void testLockedOverridePrivateA11yRedaction() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        r.setPackageVisibilityOverride(Notification.VISIBILITY_PRIVATE);
+        r.getNotification().visibility = Notification.VISIBILITY_PUBLIC;
+        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
+        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+        when(accessibilityManager.isEnabled()).thenReturn(true);
+        mService.setAccessibilityManager(accessibilityManager);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        ArgumentCaptor<AccessibilityEvent> eventCaptor =
+                ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+        verify(accessibilityManager, times(1))
+                .sendAccessibilityEvent(eventCaptor.capture());
+
+        AccessibilityEvent event = eventCaptor.getValue();
+        assertEquals(r.getNotification().publicVersion, event.getParcelableData());
+    }
+
+    @Test
+    public void testLockedPublicA11yNoRedaction() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
+        r.getNotification().visibility = Notification.VISIBILITY_PUBLIC;
+        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
+        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+        when(accessibilityManager.isEnabled()).thenReturn(true);
+        mService.setAccessibilityManager(accessibilityManager);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        ArgumentCaptor<AccessibilityEvent> eventCaptor =
+                ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+        verify(accessibilityManager, times(1))
+                .sendAccessibilityEvent(eventCaptor.capture());
+
+        AccessibilityEvent event = eventCaptor.getValue();
+        assertEquals(r.getNotification(), event.getParcelableData());
+    }
+
+    @Test
+    public void testUnlockedPrivateA11yNoRedaction() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
+        r.getNotification().visibility = Notification.VISIBILITY_PRIVATE;
+        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);
+        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
+        when(accessibilityManager.isEnabled()).thenReturn(true);
+        mService.setAccessibilityManager(accessibilityManager);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        ArgumentCaptor<AccessibilityEvent> eventCaptor =
+                ArgumentCaptor.forClass(AccessibilityEvent.class);
+
+        verify(accessibilityManager, times(1))
+                .sendAccessibilityEvent(eventCaptor.capture());
+
+        AccessibilityEvent event = eventCaptor.getValue();
+        assertEquals(r.getNotification(), event.getParcelableData());
+    }
+
+    @Test
     public void testBeepInsistently() throws Exception {
         NotificationRecord r = getInsistentBeepyNotification();
 
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 1aff8a7..35d1b17 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -25,7 +25,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
@@ -37,13 +36,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
 
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
-import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -173,34 +169,5 @@
         activity.setState(FINISHING, "test FINISHING");
         assertThat(mWm.mRoot.allPausedActivitiesComplete()).isTrue();
     }
-
-    @Test
-    public void testLockAllProfileTasks() {
-        // Make an activity visible with the user id set to 0
-        DisplayContent displayContent = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
-        TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(0);
-        final ActivityStack stack = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_STANDARD, displayContent);
-        final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(stack.mAtmService)
-                .setStack(stack)
-                .setUid(0)
-                .setCreateTask(true)
-                .build();
-
-        // Create another activity on top and the user id is 1
-        Task task = activity.getTask();
-        final ActivityRecord topActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
-                .setStack(stack)
-                .setUid(UserHandle.PER_USER_RANGE + 1)
-                .setTask(task)
-                .build();
-
-        // Make sure the listeners will be notified for putting the task to locked state
-        TaskChangeNotificationController controller =
-                mWm.mAtmService.getTaskChangeNotificationController();
-        spyOn(controller);
-        mWm.mRoot.lockAllProfileTasks(0);
-        verify(controller).notifyTaskProfileLocked(eq(task.mTaskId), eq(0));
-    }
 }
 
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
index c832f53..8dcae39 100644
--- a/telecomm/java/android/telecom/CallRedirectionService.java
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -89,6 +89,13 @@
                                      boolean allowInteractiveResponse);
 
     /**
+     * Telecom calls this method when times out waiting for the {@link CallRedirectionService} to
+     * call {@link #placeCallUnmodified()}, {@link #redirectCall(Uri, PhoneAccountHandle, boolean)},
+     * or {@link #cancelCall()}
+     */
+    public void onRedirectionTimeout() {}
+
+    /**
      * The implemented {@link CallRedirectionService} calls this method to response a request
      * received via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} to inform Telecom that
      * no changes are required to the outgoing call, and that the call should be placed as-is.
@@ -158,6 +165,12 @@
     private static final int MSG_PLACE_CALL = 1;
 
     /**
+     * A handler message to process the attempt to notify the operation of redirection service timed
+     * out from Telecom
+     */
+    private static final int MSG_TIMEOUT = 2;
+
+    /**
      * A handler to process the attempt to place call with redirection service from Telecom
      */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -174,6 +187,9 @@
                         args.recycle();
                     }
                     break;
+                case MSG_TIMEOUT:
+                    onRedirectionTimeout();
+                    break;
             }
         }
     };
@@ -200,6 +216,15 @@
             args.arg4 = allowInteractiveResponse;
             mHandler.obtainMessage(MSG_PLACE_CALL, args).sendToTarget();
         }
+
+        /**
+         * Telecom calls this method to inform the CallRedirectionService of the timeout waiting for
+         * it to complete its operation.
+         */
+        @Override
+        public void notifyTimeout() {
+            mHandler.obtainMessage(MSG_TIMEOUT).sendToTarget();
+        }
     }
 
     @Override
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 5e3d26a..705b491 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -81,7 +81,8 @@
  * <pre>
  * {@code
  * <service android:name="your.package.YourInCallServiceImplementation"
- *          android:permission="android.permission.BIND_INCALL_SERVICE">
+ *          android:permission="android.permission.BIND_INCALL_SERVICE"
+ *          android:exported="true">
  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
  *          android:value="true" />
@@ -91,6 +92,10 @@
  * </service>
  * }
  * </pre>
+ *
+ * <em>Note: You should NOT mark your {@link InCallService} with the attribute
+ * {@code android:exported="false"}; doing so can result in a failure to bind to your implementation
+ * during calls.</em>
  * <p>
  * In addition to implementing the {@link InCallService} API, you must also declare an activity in
  * your manifest which handles the {@link Intent#ACTION_DIAL} intent.  The example below illustrates
diff --git a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
index c1bc440..ce1938b 100644
--- a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
@@ -31,4 +31,6 @@
 oneway interface ICallRedirectionService {
     void placeCall(in ICallRedirectionAdapter adapter, in Uri handle,
             in PhoneAccountHandle initialPhoneAccount, boolean allowInteractiveResponse);
+
+    void notifyTimeout();
 }
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 628c480..4df8a4b 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -4,13 +4,14 @@
 breadley@google.com
 fionaxu@google.com
 jackyu@google.com
-hallliu@google.com
 rgreenwalt@google.com
 tgunn@google.com
 jminjie@google.com
 shuoq@google.com
-refuhoo@google.com
 nazaninb@google.com
 sarahchin@google.com
-dbright@google.com
 xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
diff --git a/telephony/common/Android.bp b/telephony/common/Android.bp
index 201ab53..1cacc036 100644
--- a/telephony/common/Android.bp
+++ b/telephony/common/Android.bp
@@ -19,6 +19,14 @@
     ],
 }
 
+filegroup {
+    name: "framework-mms-shared-srcs",
+    visibility: ["//packages/apps/Bluetooth"],
+    srcs: [
+        "com/google/android/mms/**/*.java",
+    ],
+}
+
 genrule {
     name: "statslog-telephony-common-java-gen",
     tools: ["stats-log-api-gen"],
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
index 6b82045..b5d97ab 100644
--- a/telephony/java/android/telephony/AccessNetworkUtils.java
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -567,6 +567,10 @@
      */
     public static int getFrequencyFromNrArfcn(int nrArfcn) {
 
+        if (nrArfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) {
+            return PhysicalChannelConfig.FREQUENCY_UNKNOWN;
+        }
+
         int globalKhz = 0;
         int rangeOffset = 0;
         int arfcnOffset = 0;
@@ -632,6 +636,10 @@
      */
     public static int getFrequencyFromUarfcn(int band, int uarfcn, boolean isUplink) {
 
+        if (uarfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) {
+            return PhysicalChannelConfig.FREQUENCY_UNKNOWN;
+        }
+
         int offsetKhz = 0;
         for (UtranBandArfcnFrequency uarfcnFrequency : AccessNetworkConstants.
                 UtranBandArfcnFrequency.values()) {
@@ -702,6 +710,10 @@
      */
     public static int getFrequencyFromArfcn(int band, int arfcn, boolean isUplink) {
 
+        if (arfcn == PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN) {
+            return PhysicalChannelConfig.FREQUENCY_UNKNOWN;
+        }
+
         int uplinkFrequencyFirst = 0;
         int arfcnOffset = 0;
         int downlinkOffset = 0;
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java
index a1c5bbe..ae597e0 100644
--- a/telephony/java/android/telephony/AvailableNetworkInfo.java
+++ b/telephony/java/android/telephony/AvailableNetworkInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.RadioAccessSpecifier;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -76,13 +77,28 @@
      * Opportunistic network service will use these bands to scan.
      *
      * When no specific bands are specified (empty array or null) CBRS band
-     * {@link AccessNetworkConstants.EutranBand.BAND_48} will be used for network scan.
+     * {@link AccessNetworkConstants.EutranBand.BAND_48
+     * } will be used for network scan.
      *
      * See {@link AccessNetworkConstants} for details.
+     *
+     * @deprecated use {@link #mRadioAccessSpecifiers} instead
      */
+    @Deprecated
     private ArrayList<Integer> mBands;
 
     /**
+     * Returns a list of {@link RadioAccessSpecifier} associated with the available network.
+     * Opportunistic network service will use this to determine which bands to scan for.
+     *
+     * If this entry is left empty, {@link RadioAcccessSpecifier}s with {@link AccessNetworkType}s
+     * of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link
+     * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed
+     * by Opportunistic network service.
+     */
+    private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers;
+
+    /**
      * Return subscription Id of the available network.
      * This value must be one of the entry retrieved from
      * {@link SubscriptionManager#getOpportunisticSubscriptions}
@@ -129,6 +145,22 @@
         return (List<Integer>) mBands.clone();
     }
 
+    /**
+     * Returns a list of {@link RadioAccessSpecifier} associated with the available network.
+     * Opportunistic network service will use this to determine which bands to scan for.
+     *
+     * the returned value is one of {@link AccessNetworkConstants.AccessNetworkType}. When no
+     * specific access network type is specified, {@link RadioAccessSpecifier}s with {@link
+     * AccessNetworkType}s of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link
+     * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed
+     * by Opportunistic network service.
+     * @return the access network type associated with the available network.
+     * @hide
+     */
+    public List<RadioAccessSpecifier>  getRadioAccessSpecifiers() {
+        return (List<RadioAccessSpecifier>) mRadioAccessSpecifiers.clone();
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -140,6 +172,7 @@
         dest.writeInt(mPriority);
         dest.writeStringList(mMccMncs);
         dest.writeList(mBands);
+        dest.writeList(mRadioAccessSpecifiers);
     }
 
     private AvailableNetworkInfo(Parcel in) {
@@ -149,14 +182,25 @@
         in.readStringList(mMccMncs);
         mBands = new ArrayList<>();
         in.readList(mBands, Integer.class.getClassLoader());
+        mRadioAccessSpecifiers = new ArrayList<>();
+        in.readList(mRadioAccessSpecifiers, RadioAccessSpecifier.class.getClassLoader());
     }
 
     public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
             @NonNull List<Integer> bands) {
+        this(subId, priority, mccMncs, bands,
+                new ArrayList<RadioAccessSpecifier>());
+    }
+
+    /** @hide */
+    private AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
+            @NonNull List<Integer> bands, @NonNull List<RadioAccessSpecifier>
+            radioAccessSpecifiers) {
         mSubId = subId;
         mPriority = priority;
         mMccMncs = new ArrayList<String>(mccMncs);
         mBands = new ArrayList<Integer>(bands);
+        mRadioAccessSpecifiers = new ArrayList<RadioAccessSpecifier>(radioAccessSpecifiers);
     }
 
     @Override
@@ -177,12 +221,13 @@
             && mPriority == ani.mPriority
             && (((mMccMncs != null)
             && mMccMncs.equals(ani.mMccMncs)))
-            && mBands.equals(ani.mBands));
+            && mBands.equals(ani.mBands))
+            && mRadioAccessSpecifiers.equals(ani.getRadioAccessSpecifiers());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSubId, mPriority, mMccMncs, mBands);
+        return Objects.hash(mSubId, mPriority, mMccMncs, mBands, mRadioAccessSpecifiers);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<AvailableNetworkInfo> CREATOR =
@@ -204,6 +249,72 @@
             + " mSubId: " + mSubId
             + " mPriority: " + mPriority
             + " mMccMncs: " + Arrays.toString(mMccMncs.toArray())
-            + " mBands: " + Arrays.toString(mBands.toArray()));
+            + " mBands: " + Arrays.toString(mBands.toArray())
+            + " mRadioAccessSpecifiers: " + Arrays.toString(mRadioAccessSpecifiers.toArray()));
+    }
+
+    /**
+     * Provides a convenient way to set the fields of a {@link AvailableNetworkInfo} when
+     * creating a new instance.
+     *
+     * <p>The example below shows how you might create a new {@code AvailableNetworkInfo}:
+     *
+     * <pre><code>
+     *
+     * AvailableNetworkInfo aNI = new AvailableNetworkInfo.Builder()
+     *     .setSubId(1)
+     *     .setPriority(AvailableNetworkInfo.PRIORITY_MED)
+     *     .build();
+     * </code></pre>
+     *
+     * @hide
+     */
+    public static final class Builder {
+        private int mSubId = Integer.MIN_VALUE;
+        private int mPriority = AvailableNetworkInfo.PRIORITY_LOW;
+        private ArrayList<String> mMccMncs = new ArrayList<>();
+        private ArrayList<Integer> mBands = new ArrayList<>();
+        private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers = new ArrayList<>();
+
+        public @NonNull Builder setSubId(int subId) {
+            mSubId = subId;
+            return this;
+        }
+
+        public @NonNull Builder setPriority(int priority) {
+            if (priority > AvailableNetworkInfo.PRIORITY_LOW
+                    || priority < AvailableNetworkInfo.PRIORITY_HIGH) {
+                throw new IllegalArgumentException("A valid priority must be set");
+            }
+            mPriority = priority;
+            return this;
+        }
+
+        public @NonNull Builder setMccMncs(@NonNull ArrayList<String> mccMncs) {
+            Objects.requireNonNull(mccMncs, "A non-null ArrayList of mccmncs must be set. An empty "
+                    + "list is still accepted. Please read documentation in "
+                    + "AvailableNetworkService to see consequences of an empty Arraylist.");
+            mMccMncs = mccMncs;
+            return this;
+        }
+
+        public @NonNull Builder setRadioAccessSpecifiers(
+                @NonNull ArrayList<RadioAccessSpecifier> radioAccessSpecifiers) {
+            Objects.requireNonNull(radioAccessSpecifiers, "A non-null ArrayList of "
+                    + "RadioAccessSpecifiers must be set. An empty list is still accepted. Please "
+                    + "read documentation in AvailableNetworkService to see consequences of an "
+                    + "empty Arraylist.");
+            mRadioAccessSpecifiers = radioAccessSpecifiers;
+            return this;
+        }
+
+        public @NonNull AvailableNetworkInfo build() {
+            if (mSubId == Integer.MIN_VALUE) {
+                throw new IllegalArgumentException("A valid subId must be set");
+            }
+
+            return new AvailableNetworkInfo(mSubId, mPriority, mMccMncs, mBands,
+                    mRadioAccessSpecifiers);
+        }
     }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5ddc7d8..2467b12 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3613,6 +3613,109 @@
             "opportunistic_network_max_backoff_time_long";
 
     /**
+    * Controls SS-RSRP threshold in dBm at which 5G opportunistic network will be considered good
+    * enough for internet data.
+    *
+    * @hide
+    */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT =
+            "opportunistic_network_entry_threshold_ss_rsrp_int";
+
+    /**
+    * Controls SS-RSRQ threshold in dB at which 5G opportunistic network will be considered good
+    * enough for internet data.
+    *
+    * @hide
+    */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE =
+            "opportunistic_network_entry_threshold_ss_rsrq_double";
+
+    /**
+    * Controls SS-RSRP threshold in dBm below which 5G opportunistic network available will not
+    * be considered good enough for internet data.
+    *
+    * @hide
+    */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT =
+            "opportunistic_network_exit_threshold_ss_rsrp_int";
+
+    /**
+    * Controls SS-RSRQ threshold in dB below which 5G opportunistic network available will not
+    * be considered good enough for internet data.
+    *
+    * @hide
+    */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE =
+            "opportunistic_network_exit_threshold_ss_rsrq_double";
+
+    /**
+     * Controls back off time in milliseconds for switching back to
+     * 5G opportunistic subscription. This time will be added to
+     * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} to
+     * determine hysteresis time if there is ping pong situation
+     * (determined by system app or 1st party app) between primary and 5G opportunistic
+     * subscription. Ping ping situation is defined in
+     * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG.
+     * If ping pong situation continuous #KEY_OPPORTUNISTIC_5G_NETWORK_BACKOFF_TIME_LONG
+     * will be added to previously determined hysteresis time.
+     *
+     * @hide
+     */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG =
+            "opportunistic_network_5g_backoff_time_long";
+
+    /**
+     * Controls the max back off time in milliseconds for switching back to
+     * 5G opportunistic subscription.
+     * This time will be the max hysteresis that can be determined irrespective of there is
+     * continuous ping pong situation or not as described in
+     * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG and
+     * #KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG.
+     *
+     * @hide
+     */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG =
+            "opportunistic_network_5g_max_backoff_time_long";
+
+    /**
+    * Controls the ping pong determination of 5G opportunistic network.
+    * If opportunistic network is determined as out of service or below
+    * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT or
+    * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_INT within
+    * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG of switching to opportunistic network,
+    * it will be determined as ping pong situation by system app or 1st party app.
+     *
+    * @hide
+    */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG =
+            "opportunistic_network_5g_ping_pong_time_long";
+
+    /**
+     * Controls hysteresis time in milliseconds for which will be waited before switching
+     * data to a 5G opportunistic network.
+     *
+     * @hide
+     */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG =
+            "opportunistic_network_5g_data_switch_hysteresis_time_long";
+
+    /**
+     * Controls hysteresis time in milliseconds for which will be waited before switching from
+     * 5G opportunistic network to primary network.
+     *
+     * @hide
+     */
+    public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG =
+            "opportunistic_network_5g_data_switch_exit_hysteresis_time_long";
+    /**
+     * Controls whether 4G opportunistic networks should be scanned for possible data switch.
+     *
+     * @hide
+     */
+    public static final String KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL =
+            "enabled_4g_opportunistic_network_scan_bool";
+
+    /**
      * Indicates zero or more emergency number prefix(es), because some carrier requires
      * if users dial an emergency number address with a specific prefix, the combination of the
      * prefix and the address is also a valid emergency number to dial. For example, an emergency
@@ -4958,6 +5061,25 @@
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000);
         /* Default value is 60 seconds. */
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000);
+        /* Default value is -111 dBm. */
+        sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT, -111);
+        /* Default value is -18.5 dB. */
+        sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
+        /* Default value is -120 dBm. */
+        sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT, -120);
+        /* Default value is -18.5 dB. */
+        sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
+        /* Default value is 10 seconds. */
+        sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG, 10000);
+        /* Default value is 60 seconds. */
+        sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG, 60000);
+        /* Default value is 60 seconds. */
+        sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG, 60000);
+        /* Default value is 2 seconds. */
+        sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG, 2000);
+        /* Default value is 2 seconds. */
+        sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000);
+        sDefaults.putBoolean(KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL, true);
         sDefaults.putAll(Gps.getDefaults());
         sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
                 new int[] {
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 72150dd..6ada32e 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -178,7 +178,7 @@
         mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23);
         mCsiCqiTableIndex = inRangeOrUnavailable(csiCqiTableIndex, 1, 3);
         mCsiCqiReport = csiCqiReport.stream()
-                .map(cqi -> new Integer(inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 1, 3)))
+                .map(cqi -> new Integer(inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 0, 15)))
                 .collect(Collectors.toList());
         mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44);
         mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20);
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index debb119..0bf8ce6 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -16,8 +16,12 @@
 
 package android.telephony;
 
+import android.annotation.DurationMillisLong;
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -25,46 +29,50 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
- * Reports modem activity information.
+ * Contains information about the modem's activity. May be useful for power stats reporting.
  * @hide
  */
+@SystemApi
+@TestApi
 public final class ModemActivityInfo implements Parcelable {
+    private static final int TX_POWER_LEVELS = 5;
+
     /**
-     * Tx(transmit) power level. see power index below
-     * <ul>
-     *   <li> index 0 = tx_power < 0dBm. </li>
-     *   <li> index 1 = 0dBm < tx_power < 5dBm. </li>
-     *   <li> index 2 = 5dBm < tx_power < 15dBm. </li>
-     *   <li> index 3 = 15dBm < tx_power < 20dBm. </li>
-     *   <li> index 4 = tx_power > 20dBm. </li>
-     * </ul>
-     */
-    public static final int TX_POWER_LEVELS = 5;
-    /**
-     * Tx(transmit) power level 0: tx_power < 0dBm
+     * Corresponds to transmit power of less than 0dBm.
      */
     public static final int TX_POWER_LEVEL_0 = 0;
+
     /**
-     * Tx(transmit) power level 1: 0dBm < tx_power < 5dBm
+     * Corresponds to transmit power between 0dBm and 5dBm.
      */
     public static final int TX_POWER_LEVEL_1 = 1;
+
     /**
-     * Tx(transmit) power level 2: 5dBm < tx_power < 15dBm
+     * Corresponds to transmit power between 5dBm and 15dBm.
      */
     public static final int TX_POWER_LEVEL_2 = 2;
+
     /**
-     * Tx(transmit) power level 3: 15dBm < tx_power < 20dBm.
+     * Corresponds to transmit power between 15dBm and 20dBm.
      */
     public static final int TX_POWER_LEVEL_3 = 3;
+
     /**
-     * Tx(transmit) power level 4: tx_power > 20dBm
+     * Corresponds to transmit power above 20dBm.
      */
     public static final int TX_POWER_LEVEL_4 = 4;
 
+    /**
+     * The number of transmit power levels. Fixed by HAL definition.
+     */
+    public static int getNumTxPowerLevels() {
+        return TX_POWER_LEVELS;
+    }
+
     /** @hide */
     @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = {
             TX_POWER_LEVEL_0,
@@ -82,34 +90,39 @@
         new Range<>(5, 15),
         new Range<>(15, 20),
         new Range<>(20, Integer.MAX_VALUE)
-
     };
 
     private long mTimestamp;
     private int mSleepTimeMs;
     private int mIdleTimeMs;
-    private List<TransmitPower> mTransmitPowerInfo = new ArrayList<>(TX_POWER_LEVELS);
+    private int[] mTxTimeMs;
     private int mRxTimeMs;
 
+    /**
+     * @hide
+     */
+    @TestApi
     public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
                         @NonNull int[] txTimeMs, int rxTimeMs) {
+        Objects.requireNonNull(txTimeMs);
+        if (txTimeMs.length != TX_POWER_LEVELS) {
+            throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS");
+        }
         mTimestamp = timestamp;
         mSleepTimeMs = sleepTimeMs;
         mIdleTimeMs = idleTimeMs;
-        populateTransmitPowerRange(txTimeMs);
+        mTxTimeMs = txTimeMs;
         mRxTimeMs = rxTimeMs;
     }
 
-    /** helper API to populate tx power range for each bucket **/
-    private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) {
-        int i = 0;
-        for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
-            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
-        }
-        // Make sure that mTransmitPowerInfo is fully initialized.
-        for ( ; i < TX_POWER_LEVELS; i++) {
-            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], 0));
-        }
+    /**
+     * Provided for convenience in manipulation since the API exposes long values but internal
+     * representations are ints.
+     * @hide
+     */
+    public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs,
+            @NonNull int[] txTimeMs, long rxTimeMs) {
+        this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs);
     }
 
     @Override
@@ -118,7 +131,7 @@
             + " mTimestamp=" + mTimestamp
             + " mSleepTimeMs=" + mSleepTimeMs
             + " mIdleTimeMs=" + mIdleTimeMs
-            + " mTransmitPowerInfo[]=" + mTransmitPowerInfo.toString()
+            + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
             + " mRxTimeMs=" + mRxTimeMs
             + "}";
     }
@@ -129,14 +142,12 @@
 
     public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
             new Parcelable.Creator<ModemActivityInfo>() {
-        public ModemActivityInfo createFromParcel(Parcel in) {
+        public ModemActivityInfo createFromParcel(@NonNull Parcel in) {
             long timestamp = in.readLong();
             int sleepTimeMs = in.readInt();
             int idleTimeMs = in.readInt();
             int[] txTimeMs = new int[TX_POWER_LEVELS];
-            for (int i = 0; i < TX_POWER_LEVELS; i++) {
-                txTimeMs[i] = in.readInt();
-            }
+            in.readIntArray(txTimeMs);
             int rxTimeMs = in.readInt();
             return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
                                 txTimeMs, rxTimeMs);
@@ -147,21 +158,25 @@
         }
     };
 
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * @param dest The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(mTimestamp);
         dest.writeInt(mSleepTimeMs);
         dest.writeInt(mIdleTimeMs);
-        for (int i = 0; i < TX_POWER_LEVELS; i++) {
-            dest.writeInt(mTransmitPowerInfo.get(i).getTimeInMillis());
-        }
+        dest.writeIntArray(mTxTimeMs);
         dest.writeInt(mRxTimeMs);
     }
 
     /**
-     * @return milliseconds since boot, including mTimeInMillis spent in sleep.
-     * @see SystemClock#elapsedRealtime()
+     * Gets the timestamp at which this modem activity info was recorded.
+     *
+     * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this
+     * {@link ModemActivityInfo} was recorded.
      */
-    public long getTimestamp() {
+    public @ElapsedRealtimeLong long getTimestampMillis() {
         return mTimestamp;
     }
 
@@ -171,35 +186,48 @@
     }
 
     /**
-     * @return an arrayList of {@link TransmitPower} with each element representing the total time where
-     * transmitter is awake time (in ms) for a given power range (in dbm).
+     * Gets the amount of time the modem spent transmitting at a certain power level.
      *
-     * @see #TX_POWER_LEVELS
+     * @param powerLevel The power level to query.
+     * @return The amount of time, in milliseconds, that the modem spent transmitting at the
+     * given power level.
      */
-    @NonNull
-    public List<TransmitPower> getTransmitPowerInfo() {
-        return mTransmitPowerInfo;
+    public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel(
+            @TxPowerLevel int powerLevel) {
+        return mTxTimeMs[powerLevel];
+    }
+
+    /**
+     * Gets the range of transmit powers corresponding to a certain power level.
+     *
+     * @param powerLevel The power level to query
+     * @return A {@link Range} object representing the range of intensities (in dBm) to which this
+     * power level corresponds.
+     */
+    public @NonNull Range<Integer> getTransmitPowerRange(@TxPowerLevel int powerLevel) {
+        return TX_POWER_RANGES[powerLevel];
     }
 
     /** @hide */
     public void setTransmitTimeMillis(int[] txTimeMs) {
-        populateTransmitPowerRange(txTimeMs);
-    }
-
-    /** @hide */
-    @NonNull
-    public int[] getTransmitTimeMillis() {
-        int[] transmitTimeMillis = new int[TX_POWER_LEVELS];
-        for (int i = 0; i < transmitTimeMillis.length; i++) {
-            transmitTimeMillis[i] = mTransmitPowerInfo.get(i).getTimeInMillis();
-        }
-        return transmitTimeMillis;
+        mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS);
     }
 
     /**
-     * @return total mTimeInMillis (in ms) when modem is in a low power or sleep state.
+     * @return The raw array of transmit power durations
+     * @hide
      */
-    public int getSleepTimeMillis() {
+    @NonNull
+    public int[] getTransmitTimeMillis() {
+        return mTxTimeMs;
+    }
+
+    /**
+     * Gets the amount of time (in milliseconds) when the modem is in a low power or sleep state.
+     *
+     * @return Time in milliseconds.
+     */
+    public @DurationMillisLong long getSleepTimeMillis() {
         return mSleepTimeMs;
     }
 
@@ -209,10 +237,44 @@
     }
 
     /**
-     * @return total mTimeInMillis (in ms) when modem is awake but neither the transmitter nor receiver are
-     * active.
+     * Provided for convenience, since the API surface needs to return longs but internal
+     * representations are ints.
+     * @hide
      */
-    public int getIdleTimeMillis() {
+    public void setSleepTimeMillis(long sleepTimeMillis) {
+        mSleepTimeMs = (int) sleepTimeMillis;
+    }
+
+    /**
+     * Computes the difference between this instance of {@link ModemActivityInfo} and another
+     * instance.
+     *
+     * This method should be used to compute the amount of activity that has happened between two
+     * samples of modem activity taken at separate times. The sample passed in as an argument to
+     * this method should be the one that's taken later in time (and therefore has more activity).
+     * @param other The other instance of {@link ModemActivityInfo} to diff against.
+     * @return An instance of {@link ModemActivityInfo} representing the difference in modem
+     * activity.
+     */
+    public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) {
+        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
+        for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
+            txTimeMs[i] = other.mTxTimeMs[i] - mTxTimeMs[i];
+        }
+        return new ModemActivityInfo(other.getTimestampMillis(),
+                other.getSleepTimeMillis() - getSleepTimeMillis(),
+                other.getIdleTimeMillis() - getIdleTimeMillis(),
+                txTimeMs,
+                other.getReceiveTimeMillis() - getReceiveTimeMillis());
+    }
+
+    /**
+     * Gets the amount of time (in milliseconds) when the modem is awake but neither transmitting
+     * nor receiving.
+     *
+     * @return Time in milliseconds.
+     */
+    public @DurationMillisLong long getIdleTimeMillis() {
         return mIdleTimeMs;
     }
 
@@ -222,9 +284,20 @@
     }
 
     /**
-     * @return rx(receive) mTimeInMillis in ms.
+     * Provided for convenience, since the API surface needs to return longs but internal
+     * representations are ints.
+     * @hide
      */
-    public int getReceiveTimeMillis() {
+    public void setIdleTimeMillis(long idleTimeMillis) {
+        mIdleTimeMs = (int) idleTimeMillis;
+    }
+
+    /**
+     * Gets the amount of time (in milliseconds) when the modem is awake and receiving data.
+     *
+     * @return Time in milliseconds.
+     */
+    public @DurationMillisLong long getReceiveTimeMillis() {
         return mRxTimeMs;
     }
 
@@ -234,71 +307,56 @@
     }
 
     /**
+     * Provided for convenience, since the API surface needs to return longs but internal
+     * representations are ints.
+     * @hide
+     */
+    public void setReceiveTimeMillis(long receiveTimeMillis) {
+        mRxTimeMs = (int) receiveTimeMillis;
+    }
+
+    /**
      * Indicates if the modem has reported valid {@link ModemActivityInfo}.
      *
      * @return {@code true} if this {@link ModemActivityInfo} record is valid,
      * {@code false} otherwise.
+     * @hide
      */
+    @TestApi
     public boolean isValid() {
-        for (TransmitPower powerInfo : getTransmitPowerInfo()) {
-            if(powerInfo.getTimeInMillis() < 0) {
-                return false;
-            }
-        }
+        boolean isTxPowerValid = Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0);
 
-        return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
+        return isTxPowerValid && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
                 && (getReceiveTimeMillis() >= 0) && !isEmpty());
     }
 
-    private boolean isEmpty() {
-        for (TransmitPower txVal : getTransmitPowerInfo()) {
-            if(txVal.getTimeInMillis() != 0) {
-                return false;
-            }
-        }
+    /** @hide */
+    @TestApi
+    public boolean isEmpty() {
+        boolean isTxPowerEmpty = mTxTimeMs == null || mTxTimeMs.length == 0
+                || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0);
 
-        return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
+        return isTxPowerEmpty && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
                 && (getReceiveTimeMillis() == 0));
     }
 
-    /**
-     * Transmit power Information, including the power range in dbm and the total time (in ms) where
-     * the transmitter is active/awake for this power range.
-     * e.g, range: 0dbm(lower) ~ 5dbm(upper)
-     *      time: 5ms
-     */
-    public class TransmitPower {
-        private int mTimeInMillis;
-        private Range<Integer> mPowerRangeInDbm;
-        /** @hide */
-        public TransmitPower(@NonNull Range<Integer> range, int time) {
-            this.mTimeInMillis = time;
-            this.mPowerRangeInDbm = range;
-        }
 
-        /**
-         * @return the total time in ms where the transmitter is active/wake for this power range
-         * {@link #getPowerRangeInDbm()}.
-         */
-        public int getTimeInMillis() {
-            return mTimeInMillis;
-        }
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ModemActivityInfo that = (ModemActivityInfo) o;
+        return mTimestamp == that.mTimestamp
+                && mSleepTimeMs == that.mSleepTimeMs
+                && mIdleTimeMs == that.mIdleTimeMs
+                && mRxTimeMs == that.mRxTimeMs
+                && Arrays.equals(mTxTimeMs, that.mTxTimeMs);
+    }
 
-        /**
-         * @return the power range in dbm. e.g, range: 0dbm(lower) ~ 5dbm(upper)
-         */
-        @NonNull
-        public Range<Integer> getPowerRangeInDbm() {
-            return mPowerRangeInDbm;
-        }
-
-        @Override
-        public String toString() {
-            return "TransmitPower{"
-                + " mTimeInMillis=" + mTimeInMillis
-                + " mPowerRangeInDbm={" + mPowerRangeInDbm.getLower()
-                + "," + mPowerRangeInDbm.getUpper()
-                + "}}";
-        }
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mRxTimeMs);
+        result = 31 * result + Arrays.hashCode(mTxTimeMs);
+        return result;
     }
 }
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 6571858..a3aaf61 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -16,19 +16,27 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
+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.Arrays;
 import java.util.List;
 import java.util.Objects;
 
 /**
- * Define capability of a modem group. That is, the capabilities
- * are shared between those modems defined by list of modem IDs.
+ * Phone capability which describes the data connection capability of modem.
+ * It's used to evaluate possible phone config change, for example from single
+ * SIM device to multi-SIM device.
+ * @hide
  */
+@SystemApi
 public final class PhoneCapability implements Parcelable {
     // Hardcoded default DSDS capability.
     /** @hide */
@@ -37,6 +45,30 @@
     /** @hide */
     public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "DEVICE_NR_CAPABILITY_" }, value = {
+            DEVICE_NR_CAPABILITY_NSA,
+            DEVICE_NR_CAPABILITY_SA,
+    })
+    public @interface DeviceNrCapability {}
+
+    /**
+     * Indicates DEVICE_NR_CAPABILITY_NSA determine that the device enable the non-standalone
+     * (NSA) mode of 5G NR.
+     * @hide
+     */
+    @SystemApi
+    public static final int DEVICE_NR_CAPABILITY_NSA = 1;
+
+    /**
+     * Indicates DEVICE_NR_CAPABILITY_SA determine that the device enable the standalone (SA)
+     * mode of 5G NR.
+     * @hide
+     */
+    @SystemApi
+    public static final int DEVICE_NR_CAPABILITY_SA = 2;
+
     static {
         ModemInfo modemInfo1 = new ModemInfo(0, 0, true, true);
         ModemInfo modemInfo2 = new ModemInfo(1, 0, true, true);
@@ -44,55 +76,91 @@
         List<ModemInfo> logicalModemList = new ArrayList<>();
         logicalModemList.add(modemInfo1);
         logicalModemList.add(modemInfo2);
-        DEFAULT_DSDS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
+        int[] deviceNrCapabilities = new int[0];
+
+        DEFAULT_DSDS_CAPABILITY = new PhoneCapability(1, 1, logicalModemList, false,
+                deviceNrCapabilities);
 
         logicalModemList = new ArrayList<>();
         logicalModemList.add(modemInfo1);
-        DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
+        DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, logicalModemList, false,
+                deviceNrCapabilities);
     }
 
-    /** @hide */
-    public final int maxActiveVoiceCalls;
-    /** @hide */
-    public final int maxActiveData;
-    /** @hide */
-    public final int max5G;
-    /** @hide */
-    public final boolean validationBeforeSwitchSupported;
-    /** @hide */
-    public final List<ModemInfo> logicalModemList;
+    /**
+     * mMaxActiveVoiceSubscriptions defines the maximum subscriptions that can support
+     * simultaneous voice calls. For a dual sim dual standby (DSDS) device it would be one, but
+     * for a dual sim dual active device it would be 2.
+     *
+     * @hide
+     */
+    private final int mMaxActiveVoiceSubscriptions;
+
+    /**
+     * mMaxActiveDataSubscriptions defines the maximum subscriptions that can support
+     * simultaneous data connections.
+     * For example, for L+L device it should be 2.
+     *
+     * @hide
+     */
+    private final int mMaxActiveDataSubscriptions;
+
+    /**
+     * Whether modem supports both internet PDN up so
+     * that we can do ping test before tearing down the
+     * other one.
+     *
+     * @hide
+     */
+    private final boolean mNetworkValidationBeforeSwitchSupported;
 
     /** @hide */
-    public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
-            List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) {
-        this.maxActiveVoiceCalls = maxActiveVoiceCalls;
-        this.maxActiveData = maxActiveData;
-        this.max5G = max5G;
+    private final List<ModemInfo> mLogicalModemList;
+
+    /**
+     * List of logical modem information.
+     *
+     * @hide
+     */
+    private final int[] mDeviceNrCapabilities;
+
+    /** @hide */
+    public PhoneCapability(int maxActiveVoiceSubscriptions, int maxActiveDataSubscriptions,
+            List<ModemInfo> logicalModemList, boolean networkValidationBeforeSwitchSupported,
+            int[] deviceNrCapabilities) {
+        this.mMaxActiveVoiceSubscriptions = maxActiveVoiceSubscriptions;
+        this.mMaxActiveDataSubscriptions = maxActiveDataSubscriptions;
         // Make sure it's not null.
-        this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
-        this.validationBeforeSwitchSupported = validationBeforeSwitchSupported;
+        this.mLogicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
+        this.mNetworkValidationBeforeSwitchSupported = networkValidationBeforeSwitchSupported;
+        this.mDeviceNrCapabilities = deviceNrCapabilities;
     }
 
     @Override
     public String toString() {
-        return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData
-                + " max5G=" + max5G + "logicalModemList:"
-                + Arrays.toString(logicalModemList.toArray());
+        return "mMaxActiveVoiceSubscriptions=" + mMaxActiveVoiceSubscriptions
+                + " mMaxActiveDataSubscriptions=" + mMaxActiveDataSubscriptions
+                + " mNetworkValidationBeforeSwitchSupported="
+                + mNetworkValidationBeforeSwitchSupported
+                + " mDeviceNrCapability " + Arrays.toString(mDeviceNrCapabilities);
     }
 
     private PhoneCapability(Parcel in) {
-        maxActiveVoiceCalls = in.readInt();
-        maxActiveData = in.readInt();
-        max5G = in.readInt();
-        validationBeforeSwitchSupported = in.readBoolean();
-        logicalModemList = new ArrayList<>();
-        in.readList(logicalModemList, ModemInfo.class.getClassLoader());
+        mMaxActiveVoiceSubscriptions = in.readInt();
+        mMaxActiveDataSubscriptions = in.readInt();
+        mNetworkValidationBeforeSwitchSupported = in.readBoolean();
+        mLogicalModemList = new ArrayList<>();
+        in.readList(mLogicalModemList, ModemInfo.class.getClassLoader());
+        mDeviceNrCapabilities = in.createIntArray();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList,
-                validationBeforeSwitchSupported);
+        return Objects.hash(mMaxActiveVoiceSubscriptions,
+                mMaxActiveDataSubscriptions,
+                mLogicalModemList,
+                mNetworkValidationBeforeSwitchSupported,
+                Arrays.hashCode(mDeviceNrCapabilities));
     }
 
     @Override
@@ -107,11 +175,12 @@
 
         PhoneCapability s = (PhoneCapability) o;
 
-        return (maxActiveVoiceCalls == s.maxActiveVoiceCalls
-                && maxActiveData == s.maxActiveData
-                && max5G == s.max5G
-                && validationBeforeSwitchSupported == s.validationBeforeSwitchSupported
-                && logicalModemList.equals(s.logicalModemList));
+        return (mMaxActiveVoiceSubscriptions == s.mMaxActiveVoiceSubscriptions
+                && mMaxActiveDataSubscriptions == s.mMaxActiveDataSubscriptions
+                && mNetworkValidationBeforeSwitchSupported
+                == s.mNetworkValidationBeforeSwitchSupported
+                && mLogicalModemList.equals(s.mLogicalModemList)
+                && Arrays.equals(mDeviceNrCapabilities, s.mDeviceNrCapabilities));
     }
 
     /**
@@ -125,14 +194,15 @@
      * {@link Parcelable#writeToParcel}
      */
     public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
-        dest.writeInt(maxActiveVoiceCalls);
-        dest.writeInt(maxActiveData);
-        dest.writeInt(max5G);
-        dest.writeBoolean(validationBeforeSwitchSupported);
-        dest.writeList(logicalModemList);
+        dest.writeInt(mMaxActiveVoiceSubscriptions);
+        dest.writeInt(mMaxActiveDataSubscriptions);
+        dest.writeBoolean(mNetworkValidationBeforeSwitchSupported);
+        dest.writeList(mLogicalModemList);
+        dest.writeIntArray(mDeviceNrCapabilities);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() {
+    public static final @android.annotation.NonNull Parcelable.Creator<PhoneCapability> CREATOR =
+            new Parcelable.Creator() {
         public PhoneCapability createFromParcel(Parcel in) {
             return new PhoneCapability(in);
         }
@@ -141,4 +211,57 @@
             return new PhoneCapability[size];
         }
     };
+
+    /**
+     * @return the maximum subscriptions that can support simultaneous voice calls. For a dual
+     * sim dual standby (DSDS) device it would be one, but for a dual sim dual active device it
+     * would be 2.
+     * @hide
+     */
+    @SystemApi
+    public @IntRange(from = 1) int getMaxActiveVoiceSubscriptions() {
+        return mMaxActiveVoiceSubscriptions;
+    }
+
+    /**
+     * @return the maximum subscriptions that can support simultaneous data connections.
+     * For example, for L+L device it should be 2.
+     * @hide
+     */
+    @SystemApi
+    public @IntRange(from = 1) int getMaxActiveDataSubscriptions() {
+        return mMaxActiveDataSubscriptions;
+    }
+
+    /**
+     * @return Check whether the Citizens Broadband Radio Service(CBRS) network validation before
+     * CBRS switch is supported or not.
+     *
+     * @hide
+     */
+    public boolean isNetworkValidationBeforeSwitchSupported() {
+        return mNetworkValidationBeforeSwitchSupported;
+    }
+
+    /**
+     * @return The list of logical modem information.
+     * @hide
+     */
+    public List<ModemInfo> getLogicalModemList() {
+        return mLogicalModemList;
+    }
+
+    /**
+     * Return List of the device's NR capability. If the device doesn't support NR capability,
+     * then this api return empty array.
+     * @see DEVICE_NR_CAPABILITY_NSA
+     * @see DEVICE_NR_CAPABILITY_SA
+     *
+     * @return List of the device's NR capability.
+     * @hide
+     */
+    @SystemApi
+    public @NonNull @DeviceNrCapability int[] getDeviceNrCapabilities() {
+        return mDeviceNrCapabilities == null ? (new int[0]) : mDeviceNrCapabilities;
+    }
 }
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 8a4bb46..59eac6a 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -337,7 +337,8 @@
     private void setUplinkFrequency() {
         switch (mNetworkType){
             case TelephonyManager.NETWORK_TYPE_NR:
-                mUplinkFrequency = mDownlinkFrequency;
+                mUplinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
+                        mUplinkChannelNumber);
                 break;
             case TelephonyManager.NETWORK_TYPE_LTE:
                 mUplinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 6da61b7..1677c61 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -444,7 +444,9 @@
         mArfcnRsrpBoost = s.mArfcnRsrpBoost;
         synchronized (mNetworkRegistrationInfos) {
             mNetworkRegistrationInfos.clear();
-            mNetworkRegistrationInfos.addAll(s.getNetworkRegistrationInfoList());
+            for (NetworkRegistrationInfo nri : s.getNetworkRegistrationInfoList()) {
+                mNetworkRegistrationInfos.add(new NetworkRegistrationInfo(nri));
+            }
         }
         mNrFrequencyRange = s.mNrFrequencyRange;
         mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw;
diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
index fe7e5976..41e24dd 100644
--- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
+++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
@@ -26,8 +26,10 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -101,9 +103,11 @@
             }
 
             mSignalThresholdInfos = new ArrayList<>(signalThresholdInfos);
-            // Sort the collection with RAN ascending order, make the ordering not matter for equals
+            // Sort the collection with RAN and then SignalMeasurementType ascending order, make the
+            // ordering not matter for equals
             mSignalThresholdInfos.sort(
-                    Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType));
+                    Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType)
+                            .thenComparing(SignalThresholdInfo::getSignalMeasurementType));
             return this;
         }
 
@@ -144,7 +148,7 @@
          * @return the SignalStrengthUpdateRequest object
          *
          * @throws IllegalArgumentException if the SignalThresholdInfo collection is empty size, the
-         * radio access network type in the collection is not unique
+         * signal measurement type for the same RAN in the collection is not unique
          */
         public @NonNull SignalStrengthUpdateRequest build() {
             return new SignalStrengthUpdateRequest(mSignalThresholdInfos,
@@ -258,14 +262,23 @@
     }
 
     /**
-     * Throw IAE when the RAN in the collection is not unique.
+     * Throw IAE if SignalThresholdInfo collection is null or empty,
+     * or the SignalMeasurementType for the same RAN in the collection is not unique.
      */
     private static void validate(Collection<SignalThresholdInfo> infos) {
-        Set<Integer> uniqueRan = new HashSet<>(infos.size());
+        if (infos == null || infos.isEmpty()) {
+            throw new IllegalArgumentException("SignalThresholdInfo collection is null or empty");
+        }
+
+        // Map from RAN to set of SignalMeasurementTypes
+        Map<Integer, Set<Integer>> ranToTypes = new HashMap<>(infos.size());
         for (SignalThresholdInfo info : infos) {
             final int ran = info.getRadioAccessNetworkType();
-            if (!uniqueRan.add(ran)) {
-                throw new IllegalArgumentException("RAN: " + ran + " is not unique");
+            final int type = info.getSignalMeasurementType();
+            ranToTypes.putIfAbsent(ran, new HashSet<>());
+            if (!ranToTypes.get(ran).add(type)) {
+                throw new IllegalArgumentException(
+                        "SignalMeasurementType " + type + " for RAN " + ran + " is not unique");
             }
         }
     }
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 104cc75..c86bedb 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -23,6 +23,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -113,9 +114,9 @@
     private int mDataRoaming;
 
     /**
-     * SIM Icon bitmap
+     * SIM icon bitmap cache
      */
-    private Bitmap mIconBitmap;
+    @Nullable private Bitmap mIconBitmap;
 
     /**
      * Mobile Country Code
@@ -403,6 +404,10 @@
      * @return A bitmap icon for this {@code SubscriptionInfo}.
      */
     public Bitmap createIconBitmap(Context context) {
+        if (mIconBitmap == null) {
+            mIconBitmap = BitmapFactory.decodeResource(context.getResources(),
+                    com.android.internal.R.drawable.ic_sim_card_multi_24px_clr);
+        }
         int width = mIconBitmap.getWidth();
         int height = mIconBitmap.getHeight();
         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
@@ -570,6 +575,13 @@
     /**
      * @hide
      */
+    public void clearGroupUuid() {
+        this.mGroupUUID = null;
+    }
+
+    /**
+     * @hide
+     */
     public List<String> getEhplmns() {
         return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns);
     }
@@ -765,7 +777,6 @@
             String mcc = source.readString();
             String mnc = source.readString();
             String countryIso = source.readString();
-            Bitmap iconBitmap = source.readParcelable(Bitmap.class.getClassLoader());
             boolean isEmbedded = source.readBoolean();
             UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR);
             String cardString = source.readString();
@@ -784,10 +795,10 @@
             boolean areUiccApplicationsEnabled = source.readBoolean();
 
             SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
-                    carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
-                    countryIso, isEmbedded, nativeAccessRules, cardString, cardId, isOpportunistic,
-                    groupUUID, isGroupDisabled, carrierid, profileClass, subType, groupOwner,
-                    carrierConfigAccessRules, areUiccApplicationsEnabled);
+                    carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null,
+                    mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId,
+                    isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType,
+                    groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled);
             info.setAssociatedPlmns(ehplmns, hplmns);
             return info;
         }
@@ -812,7 +823,7 @@
         dest.writeString(mMcc);
         dest.writeString(mMnc);
         dest.writeString(mCountryIso);
-        dest.writeParcelable(mIconBitmap, flags);
+        // Do not write mIconBitmap since it should be lazily loaded on first usage
         dest.writeBoolean(mIsEmbedded);
         dest.writeTypedArray(mNativeAccessRules, flags);
         dest.writeString(mCardString);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 9d4db17..98f9dfd 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1827,8 +1827,9 @@
      * @param subscriptionType the {@link #SUBSCRIPTION_TYPE}
      * @hide
      */
-    public void addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex,
-            int subscriptionType) {
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public void addSubscriptionInfoRecord(@NonNull String uniqueId, @Nullable String displayName,
+            int slotIndex, int subscriptionType) {
         if (VDBG) {
             logd("[addSubscriptionInfoRecord]+ uniqueId:" + uniqueId
                     + ", displayName:" + displayName + ", slotIndex:" + slotIndex
@@ -1863,7 +1864,8 @@
      * @param subscriptionType the {@link #SUBSCRIPTION_TYPE}
      * @hide
      */
-    public void removeSubscriptionInfoRecord(String uniqueId, int subscriptionType) {
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public void removeSubscriptionInfoRecord(@NonNull String uniqueId, int subscriptionType) {
         if (VDBG) {
             logd("[removeSubscriptionInfoRecord]+ uniqueId:" + uniqueId
                     + ", subscriptionType: " + subscriptionType);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 93b70ae..f55dc8b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -57,7 +57,9 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.OutcomeReceiver;
 import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -84,6 +86,7 @@
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.ApnSetting.MvnoType;
+import android.telephony.data.SlicingConfig;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
 import android.telephony.gba.UaSecurityProtocolIdentifier;
@@ -176,6 +179,9 @@
      */
     public static final String MODEM_ACTIVITY_RESULT_KEY = "controller_activity";
 
+    /** @hide */
+    public static final String EXCEPTION_RESULT_KEY = "exception";
+
     /**
      * The process name of the Phone app as well as many other apps that use this process name, such
      * as settings and vendor components.
@@ -10855,26 +10861,149 @@
         return null;
     }
 
-
     /**
-     * Requests the modem activity info. The recipient will place the result
-     * in `result`.
-     * @param result The object on which the recipient will send the resulting
-     * {@link android.telephony.ModemActivityInfo} object with key of
-     * {@link #MODEM_ACTIVITY_RESULT_KEY}.
+     * Exception that may be supplied to the callback provided in {@link #requestModemActivityInfo}.
      * @hide
      */
-    public void requestModemActivityInfo(@NonNull ResultReceiver result) {
+    @SystemApi
+    public static class ModemActivityInfoException extends Exception {
+        /** Indicates that an unknown error occurred */
+        public static final int ERROR_UNKNOWN = 0;
+
+        /**
+         * Indicates that the modem or phone processes are not available (such as when the device
+         * is in airplane mode).
+         */
+        public static final int ERROR_PHONE_NOT_AVAILABLE = 1;
+
+        /**
+         * Indicates that the modem supplied an invalid instance of {@link ModemActivityInfo}
+         */
+        public static final int ERROR_INVALID_INFO_RECEIVED = 2;
+
+        /**
+         * Indicates that the modem encountered an internal failure when processing the request
+         * for activity info.
+         */
+        public static final int ERROR_MODEM_RESPONSE_ERROR = 3;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(prefix = {"ERROR_"},
+                value = {
+                        ERROR_UNKNOWN,
+                        ERROR_PHONE_NOT_AVAILABLE,
+                        ERROR_INVALID_INFO_RECEIVED,
+                        ERROR_MODEM_RESPONSE_ERROR,
+                })
+        public @interface ModemActivityInfoError {}
+
+        private final int mErrorCode;
+
+        /** @hide */
+        public ModemActivityInfoException(@ModemActivityInfoError int errorCode) {
+            mErrorCode = errorCode;
+        }
+
+        public @ModemActivityInfoError int getErrorCode() {
+            return mErrorCode;
+        }
+
+        @Override
+        public String toString() {
+            switch (mErrorCode) {
+                case ERROR_UNKNOWN: return "ERROR_UNKNOWN";
+                case ERROR_PHONE_NOT_AVAILABLE: return "ERROR_PHONE_NOT_AVAILABLE";
+                case ERROR_INVALID_INFO_RECEIVED: return "ERROR_INVALID_INFO_RECEIVED";
+                case ERROR_MODEM_RESPONSE_ERROR: return "ERROR_MODEM_RESPONSE_ERROR";
+                default: return "UNDEFINED";
+            }
+        }
+    }
+
+    /**
+     * Requests the current modem activity info.
+     *
+     * The provided instance of {@link ModemActivityInfo} represents the cumulative activity since
+     * the last restart of the phone process.
+     *
+     * @param callback A callback object to which the result will be delivered. If there was an
+     *                 error processing the request, {@link OutcomeReceiver#onError} will be called
+     *                 with more details about the error.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void requestModemActivityInfo(@NonNull @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<ModemActivityInfo, ModemActivityInfoException> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        // Pass no handler into the receiver, since we're going to be trampolining the call to the
+        // listener onto the provided executor.
+        ResultReceiver wrapperResultReceiver = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle data) {
+                if (data == null) {
+                    Log.w(TAG, "requestModemActivityInfo: received null bundle");
+                    sendErrorToListener(ModemActivityInfoException.ERROR_UNKNOWN);
+                    return;
+                }
+                data.setDefusable(true);
+                if (data.containsKey(EXCEPTION_RESULT_KEY)) {
+                    int receivedErrorCode = data.getInt(EXCEPTION_RESULT_KEY);
+                    sendErrorToListener(receivedErrorCode);
+                    return;
+                }
+
+                if (!data.containsKey(MODEM_ACTIVITY_RESULT_KEY)) {
+                    Log.w(TAG, "requestModemActivityInfo: Bundle did not contain expected key");
+                    sendErrorToListener(ModemActivityInfoException.ERROR_UNKNOWN);
+                    return;
+                }
+                Parcelable receivedResult = data.getParcelable(MODEM_ACTIVITY_RESULT_KEY);
+                if (!(receivedResult instanceof ModemActivityInfo)) {
+                    Log.w(TAG, "requestModemActivityInfo: Bundle contained something that wasn't "
+                            + "a ModemActivityInfo.");
+                    sendErrorToListener(ModemActivityInfoException.ERROR_UNKNOWN);
+                    return;
+                }
+                ModemActivityInfo modemActivityInfo = (ModemActivityInfo) receivedResult;
+                if (!modemActivityInfo.isValid()) {
+                    Log.w(TAG, "requestModemActivityInfo: Received an invalid ModemActivityInfo");
+                    sendErrorToListener(ModemActivityInfoException.ERROR_INVALID_INFO_RECEIVED);
+                    return;
+                }
+                Log.d(TAG, "requestModemActivityInfo: Sending result to app: " + modemActivityInfo);
+                sendResultToListener(modemActivityInfo);
+            }
+
+            private void sendResultToListener(ModemActivityInfo info) {
+                Binder.withCleanCallingIdentity(() ->
+                        executor.execute(() ->
+                                callback.onResult(info)));
+            }
+
+            private void sendErrorToListener(int code) {
+                ModemActivityInfoException e = new ModemActivityInfoException(code);
+                Binder.withCleanCallingIdentity(() ->
+                        executor.execute(() ->
+                                callback.onError(e)));
+            }
+        };
+
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                service.requestModemActivityInfo(result);
+                service.requestModemActivityInfo(wrapperResultReceiver);
                 return;
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#getModemActivityInfo", e);
         }
-        result.send(0, null);
+        executor.execute(() -> callback.onError(
+                new ModemActivityInfoException(
+                        ModemActivityInfoException.ERROR_PHONE_NOT_AVAILABLE)));
     }
 
     /**
@@ -13425,7 +13554,12 @@
         IBooleanConsumer aidlConsumer = callback == null ? null : new IBooleanConsumer.Stub() {
             @Override
             public void accept(boolean result) {
-                executor.execute(() -> callback.accept(result));
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(() -> callback.accept(result));
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
         };
 
@@ -15060,4 +15194,124 @@
         }
         return PREPARE_UNATTENDED_REBOOT_ERROR;
     }
+
+    /**
+     * Gets the current phone capability.
+     *
+     * @return the PhoneCapability which describes the data connection capability of modem.
+     * It's used to evaluate possible phone config change, for example from single
+     * SIM device to multi-SIM device.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @NonNull PhoneCapability getPhoneCapability() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getPhoneCapability();
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            ex.rethrowAsRuntimeException();
+        }
+        if (getActiveModemCount() > 1) {
+            return PhoneCapability.DEFAULT_DSDS_CAPABILITY;
+        } else {
+            return PhoneCapability.DEFAULT_SSSS_CAPABILITY;
+        }
+    }
+
+    /**
+     * Exception that may be supplied to the callback in {@link #getNetworkSlicingConfiguration} if
+     * something goes awry.
+     */
+    public static class SlicingException extends Exception {
+        /**
+         * Getting the current slicing configuration successfully. Used internally only.
+         * @hide
+         */
+        public static final int SUCCESS = 0;
+
+        /**
+         * The system timed out waiting for a response from the Radio.
+         */
+        public static final int ERROR_TIMEOUT = 1;
+
+        /**
+         * The modem returned a failure.
+         */
+        public static final int ERROR_MODEM_ERROR = 2;
+
+        /** @hide */
+        @IntDef(prefix = {"ERROR_"}, value = {
+                ERROR_TIMEOUT,
+                ERROR_MODEM_ERROR,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface SlicingError {}
+
+        private final int mErrorCode;
+
+        public SlicingException(@SlicingError int errorCode) {
+            mErrorCode = errorCode;
+        }
+
+        /**
+         * Fetches the error code associated with this exception.
+         * @return An error code.
+         */
+        public @SlicingError int getErrorCode() {
+            return mErrorCode;
+        }
+    }
+
+    /** @hide */
+    public static final String KEY_SLICING_CONFIG_HANDLE = "slicing_config_handle";
+
+    /**
+     * Request to get the current slicing configuration including URSP rules and
+     * NSSAIs (configured, allowed and rejected).
+     *
+     * 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 has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * </ul>
+     *
+     * @param executor the executor on which callback will be invoked.
+     * @param callback a callback to receive the current slicing configuration.
+     */
+    @SuppressAutoDoc // No support for carrier privileges (b/72967236).
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void getNetworkSlicingConfiguration(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<SlicingConfig, SlicingException> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) {
+                throw new IllegalStateException("telephony service is null.");
+            }
+            telephony.getSlicingConfig(new ResultReceiver(null) {
+                    @Override
+                    protected void onReceiveResult(int resultCode, Bundle result) {
+                        if (resultCode != SlicingException.SUCCESS) {
+                            executor.execute(() -> callback.onError(
+                                    new SlicingException(resultCode)));
+                            return;
+                        }
+                        SlicingConfig slicingConfig =
+                                result.getParcelable(KEY_SLICING_CONFIG_HANDLE);
+                        executor.execute(() -> callback.onResult(slicingConfig));
+                    }
+            });
+        } catch (RemoteException ex) {
+            ex.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index ad57b91..5008307 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -138,7 +138,7 @@
     private final int mPduSessionId;
     private final Qos mDefaultQos;
     private final List<QosBearerSession> mQosBearerSessions;
-    private final SliceInfo mSliceInfo;
+    private final NetworkSliceInfo mSliceInfo;
     private final List<TrafficDescriptor> mTrafficDescriptors;
 
     /**
@@ -201,7 +201,8 @@
             @Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
             @HandoverFailureMode int handoverFailureMode, int pduSessionId,
             @Nullable Qos defaultQos, @Nullable List<QosBearerSession> qosBearerSessions,
-            @Nullable SliceInfo sliceInfo, @Nullable List<TrafficDescriptor> trafficDescriptors) {
+            @Nullable NetworkSliceInfo sliceInfo,
+            @Nullable List<TrafficDescriptor> trafficDescriptors) {
         mCause = cause;
         mSuggestedRetryTime = suggestedRetryTime;
         mId = id;
@@ -254,7 +255,7 @@
         mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
         mQosBearerSessions = new ArrayList<>();
         source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader());
-        mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
+        mSliceInfo = source.readParcelable(NetworkSliceInfo.class.getClassLoader());
         mTrafficDescriptors = new ArrayList<>();
         source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader());
     }
@@ -408,7 +409,7 @@
      * @return The slice info related to this data connection.
      */
     @Nullable
-    public SliceInfo getSliceInfo() {
+    public NetworkSliceInfo getSliceInfo() {
         return mSliceInfo;
     }
 
@@ -620,7 +621,7 @@
 
         private List<QosBearerSession> mQosBearerSessions = new ArrayList<>();
 
-        private SliceInfo mSliceInfo;
+        private NetworkSliceInfo mSliceInfo;
 
         private List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>();
 
@@ -851,13 +852,13 @@
          * The Slice used for this data connection.
          * <p/>
          * If a handover occurs from EPDG to 5G,
-         * this is the {@link SliceInfo} used in {@link DataService#setupDataCall}.
+         * this is the {@link NetworkSliceInfo} used in {@link DataService#setupDataCall}.
          *
          * @param sliceInfo the slice info for the data call
          *
          * @return The same instance of the builder.
          */
-        public @NonNull Builder setSliceInfo(@Nullable SliceInfo sliceInfo) {
+        public @NonNull Builder setSliceInfo(@Nullable NetworkSliceInfo sliceInfo) {
             mSliceInfo = sliceInfo;
             return this;
         }
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index f5f29c6..17e6f32 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -217,7 +217,7 @@
                 boolean isRoaming, boolean allowRoaming,
                 @SetupDataReason int reason,
                 @Nullable LinkProperties linkProperties,
-                @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
+                @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo,
                 @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                 @NonNull DataServiceCallback callback) {
             /* Call the old version since the new version isn't supported */
@@ -414,13 +414,13 @@
         public final int reason;
         public final LinkProperties linkProperties;
         public final int pduSessionId;
-        public final SliceInfo sliceInfo;
+        public final NetworkSliceInfo sliceInfo;
         public final TrafficDescriptor trafficDescriptor;
         public final boolean matchAllRuleAllowed;
         public final IDataServiceCallback callback;
         SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                 boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId,
-                SliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
+                NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
                 boolean matchAllRuleAllowed, IDataServiceCallback callback) {
             this.accessNetworkType = accessNetworkType;
             this.dataProfile = dataProfile;
@@ -707,7 +707,7 @@
         @Override
         public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
                 boolean isRoaming, boolean allowRoaming, int reason,
-                LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+                LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo,
                 TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                 IDataServiceCallback callback) {
             mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 81f5fd3..1346946 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -19,7 +19,7 @@
 import android.net.LinkProperties;
 import android.telephony.data.DataProfile;
 import android.telephony.data.IDataServiceCallback;
-import android.telephony.data.SliceInfo;
+import android.telephony.data.NetworkSliceInfo;
 import android.telephony.data.TrafficDescriptor;
 
 /**
@@ -31,7 +31,7 @@
     void removeDataServiceProvider(int slotId);
     void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
                        boolean allowRoaming, int reason, in LinkProperties linkProperties,
-                       int pduSessionId, in SliceInfo sliceInfo,
+                       int pduSessionId, in NetworkSliceInfo sliceInfo,
                        in TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
                        IDataServiceCallback callback);
     void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/NetworkSliceInfo.aidl
similarity index 95%
rename from telephony/java/android/telephony/data/SliceInfo.aidl
rename to telephony/java/android/telephony/data/NetworkSliceInfo.aidl
index 286ea5e..e1a11f2 100644
--- a/telephony/java/android/telephony/data/SliceInfo.aidl
+++ b/telephony/java/android/telephony/data/NetworkSliceInfo.aidl
@@ -17,4 +17,4 @@
 /** @hide */
 package android.telephony.data;
 
-parcelable SliceInfo;
+parcelable NetworkSliceInfo;
diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/NetworkSliceInfo.java
similarity index 68%
rename from telephony/java/android/telephony/data/SliceInfo.java
rename to telephony/java/android/telephony/data/NetworkSliceInfo.java
index 609d111..232a930 100644
--- a/telephony/java/android/telephony/data/SliceInfo.java
+++ b/telephony/java/android/telephony/data/NetworkSliceInfo.java
@@ -19,8 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -35,11 +33,8 @@
  * SliceServiceType defines the type of service provided by the slice, and SliceDifferentiator is
  * used to differentiate between multiple slices of the same type. If the devices is not on HPLMN,
  * the mappedHplmn versions of these 2 fields indicate the corresponding values in HPLMN.
- *
- * @hide
  */
-@SystemApi
-public final class SliceInfo implements Parcelable {
+public final class NetworkSliceInfo implements Parcelable {
     /**
      * When set on a Slice Differentiator, this value indicates that there is no corresponding
      * Slice.
@@ -68,14 +63,14 @@
 
     /**
      * The min acceptable value for a Slice Differentiator
+     * @hide
      */
-    @SuppressLint("MinMaxConstant")
     public static final int MIN_SLICE_DIFFERENTIATOR = -1;
 
     /**
      * The max acceptable value for a Slice Differentiator
+     * @hide
      */
-    @SuppressLint("MinMaxConstant")
     public static final int MAX_SLICE_DIFFERENTIATOR = 0xFFFFFE;
 
     /** @hide */
@@ -88,6 +83,62 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface SliceServiceType {}
 
+    /**
+     * The slice status is unknown. This can happen during IWLAN->cellular handover when the
+     * NetworkSliceInfo is received over IWLAN.
+     */
+    public static final int SLICE_STATUS_UNKNOWN = 0;
+
+    /**
+     * The slice is configured but not allowed or rejected yet.
+     */
+    public static final int SLICE_STATUS_CONFIGURED = 1;
+
+    /**
+     * The slice is allowed to be used.
+     */
+    public static final int SLICE_STATUS_ALLOWED = 2;
+
+    /**
+     * The slice is rejected because not available in PLMN.
+     */
+    public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3;
+
+    /**
+     * The slice is rejected because not available in registered area.
+     */
+    public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA = 4;
+
+    /**
+     * The slice is configured by home operator(HPLMN) in default and is used if configured/allowed
+     * slices are not available for the serving PLMN.
+     */
+    public static final int SLICE_STATUS_DEFAULT_CONFIGURED = 5;
+
+    /**
+     * The min acceptable value for a slice status.
+     * @hide
+     */
+    public static final int MIN_SLICE_STATUS = SLICE_STATUS_UNKNOWN;
+
+    /**
+     * The max acceptable value for a slice status.
+     * @hide
+     */
+    public static final int MAX_SLICE_STATUS = SLICE_STATUS_DEFAULT_CONFIGURED;
+
+    /** @hide */
+    @IntDef(prefix = { "SLICE_STATUS_" }, value = {
+            SLICE_STATUS_UNKNOWN,
+            SLICE_STATUS_CONFIGURED,
+            SLICE_STATUS_ALLOWED,
+            SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN,
+            SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA,
+            SLICE_STATUS_DEFAULT_CONFIGURED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SliceStatus {}
+
 
     @SliceServiceType
     private final int mSliceServiceType;
@@ -97,14 +148,18 @@
     private final int mMappedHplmnSliceServiceType;
     @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
     private final int mMappedHplmnSliceDifferentiator;
+    @SliceStatus
+    @IntRange(from = MIN_SLICE_STATUS, to = MAX_SLICE_STATUS)
+    private final int mStatus;
 
-    private SliceInfo(@SliceServiceType int sliceServiceType,
+    private NetworkSliceInfo(@SliceServiceType int sliceServiceType,
             int sliceDifferentiator, int mappedHplmnSliceServiceType,
-            int mappedHplmnSliceDifferentiator) {
+            int mappedHplmnSliceDifferentiator, int status) {
         mSliceServiceType = sliceServiceType;
         mSliceDifferentiator = sliceDifferentiator;
         mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
         mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+        mStatus = status;
     }
 
     /**
@@ -141,7 +196,7 @@
     }
 
     /**
-     * This Slice Differentiator corresponds to a {@link SliceInfo} (S-NSSAI) of the HPLMN;
+     * This Slice Differentiator corresponds to a {@link NetworkSliceInfo} (S-NSSAI) of the HPLMN;
      * {@link #getSliceDifferentiator()} is mapped to this value.
      * <p/>
      * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true:
@@ -157,11 +212,21 @@
         return mMappedHplmnSliceDifferentiator;
     }
 
-    private SliceInfo(@NonNull Parcel in) {
+    /**
+     * Field to indicate the current status of the slice.
+     * @return the current status for this slice info.
+     */
+    @SliceStatus
+    public int getStatus() {
+        return mStatus;
+    }
+
+    private NetworkSliceInfo(@NonNull Parcel in) {
         mSliceServiceType = in.readInt();
         mSliceDifferentiator = in.readInt();
         mMappedHplmnSliceServiceType = in.readInt();
         mMappedHplmnSliceDifferentiator = in.readInt();
+        mStatus = in.readInt();
     }
 
     @Override
@@ -175,20 +240,21 @@
         dest.writeInt(mSliceDifferentiator);
         dest.writeInt(mMappedHplmnSliceServiceType);
         dest.writeInt(mMappedHplmnSliceDifferentiator);
+        dest.writeInt(mStatus);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<SliceInfo> CREATOR =
-            new Parcelable.Creator<SliceInfo>() {
+    public static final @android.annotation.NonNull Parcelable.Creator<NetworkSliceInfo> CREATOR =
+            new Parcelable.Creator<NetworkSliceInfo>() {
                 @Override
                 @NonNull
-                public SliceInfo createFromParcel(@NonNull Parcel source) {
-                    return new SliceInfo(source);
+                public NetworkSliceInfo createFromParcel(@NonNull Parcel source) {
+                    return new NetworkSliceInfo(source);
                 }
 
                 @Override
                 @NonNull
-                public SliceInfo[] newArray(int size) {
-                    return new SliceInfo[size];
+                public NetworkSliceInfo[] newArray(int size) {
+                    return new NetworkSliceInfo[size];
                 }
             };
 
@@ -200,6 +266,7 @@
                 + ", mMappedHplmnSliceServiceType="
                 + sliceServiceTypeToString(mMappedHplmnSliceServiceType)
                 + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator
+                + ", mStatus=" + sliceStatusToString(mStatus)
                 + '}';
     }
 
@@ -218,25 +285,45 @@
         }
     }
 
+    private static String sliceStatusToString(@SliceStatus int sliceStatus) {
+        switch(sliceStatus) {
+            case SLICE_STATUS_UNKNOWN:
+                return "UNKNOWN";
+            case SLICE_STATUS_CONFIGURED:
+                return "CONFIGURED";
+            case SLICE_STATUS_ALLOWED:
+                return "ALLOWED";
+            case SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN:
+                return "REJECTED_NOT_AVAILABLE_IN_PLMN";
+            case SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA:
+                return "REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA";
+            case SLICE_STATUS_DEFAULT_CONFIGURED:
+                return "DEFAULT_CONFIGURED";
+            default:
+                return Integer.toString(sliceStatus);
+        }
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-        SliceInfo sliceInfo = (SliceInfo) o;
+        NetworkSliceInfo sliceInfo = (NetworkSliceInfo) o;
         return mSliceServiceType == sliceInfo.mSliceServiceType
                 && mSliceDifferentiator == sliceInfo.mSliceDifferentiator
                 && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType
-                && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator;
+                && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator
+                && mStatus == sliceInfo.mStatus;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType,
-                mMappedHplmnSliceDifferentiator);
+                mMappedHplmnSliceDifferentiator, mStatus);
     }
 
     /**
-     * Provides a convenient way to set the fields of a {@link SliceInfo} when creating a
+     * Provides a convenient way to set the fields of a {@link NetworkSliceInfo} when creating a
      * new instance.
      *
      * <p>The example below shows how you might create a new {@code SliceInfo}:
@@ -257,6 +344,9 @@
         private int mMappedHplmnSliceServiceType = SLICE_SERVICE_TYPE_NONE;
         @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
         private int mMappedHplmnSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE;
+        @SliceStatus
+        @IntRange(from = MIN_SLICE_STATUS, to = MAX_SLICE_STATUS)
+        private int mStatus = SLICE_STATUS_UNKNOWN;
 
         /**
          * Default constructor for Builder.
@@ -281,8 +371,7 @@
          * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
          * corresponding Slice.
          *
-         * @throws IllegalArgumentException if the parameter is not between
-         * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+         * @throws IllegalArgumentException if the parameter is not in the expected range.
          *
          * @return The same instance of the builder.
          */
@@ -316,8 +405,7 @@
          * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
          * corresponding Slice of the HPLMN.
          *
-         * @throws IllegalArgumentException if the parameter is not between
-         * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+         * @throws IllegalArgumentException if the parameter is not in the expected range.
          *
          * @return The same instance of the builder.
          */
@@ -334,14 +422,31 @@
         }
 
         /**
-         * Build the {@link SliceInfo}.
+         * Set the slice status.
          *
-         * @return the {@link SliceInfo} object.
+         * @throws IllegalArgumentException if the status is invalid.
+         *
+         * @return The same instance of the builder.
          */
         @NonNull
-        public SliceInfo build() {
-            return new SliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
-                    this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator);
+        public Builder setStatus(@SliceStatus int status) {
+            if (status < MIN_SLICE_STATUS || status > MAX_SLICE_STATUS) {
+                throw new IllegalArgumentException("The slice status is not valid");
+            }
+            this.mStatus = status;
+            return this;
+        }
+
+        /**
+         * Build the {@link NetworkSliceInfo}.
+         *
+         * @return the {@link NetworkSliceInfo} object.
+         */
+        @NonNull
+        public NetworkSliceInfo build() {
+            return new NetworkSliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
+                    this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator,
+                    this.mStatus);
         }
     }
 }
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/RouteSelectionDescriptor.aidl
similarity index 87%
copy from telephony/java/android/telephony/data/SliceInfo.aidl
copy to telephony/java/android/telephony/data/RouteSelectionDescriptor.aidl
index 286ea5e..563a00e 100644
--- a/telephony/java/android/telephony/data/SliceInfo.aidl
+++ b/telephony/java/android/telephony/data/RouteSelectionDescriptor.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-/** @hide */
 package android.telephony.data;
 
-parcelable SliceInfo;
+parcelable RouteSelectionDescriptor;
diff --git a/telephony/java/android/telephony/data/RouteSelectionDescriptor.java b/telephony/java/android/telephony/data/RouteSelectionDescriptor.java
new file mode 100644
index 0000000..c2457f2
--- /dev/null
+++ b/telephony/java/android/telephony/data/RouteSelectionDescriptor.java
@@ -0,0 +1,263 @@
+/**
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+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;
+
+/**
+ * Represents a single route selection descriptor as defined in
+ * 3GPP TS 24.526.
+ */
+public final class RouteSelectionDescriptor implements Parcelable {
+    /**
+     * The min acceptable value for the precedence of a route selection descriptor.
+     * @hide
+     */
+    public static final int MIN_ROUTE_PRECEDENCE = 0;
+
+    /**
+     * The max acceptable value for the precedence of a route selection descriptor.
+     * @hide
+     */
+    public static final int MAX_ROUTE_PRECEDENCE = 255;
+
+    /**
+     * The route selection descriptor is for the session with IPV4 type.
+     */
+    public static final int SESSION_TYPE_IPV4 = 0;
+
+    /**
+     * The route selection descriptor is for the session with IPV6 type.
+     */
+    public static final int SESSION_TYPE_IPV6 = 1;
+
+    /**
+     * The route selection descriptor is for the session with both IP and IPV6 types.
+     */
+    public static final int SESSION_TYPE_IPV4V6 = 2;
+
+    /** @hide */
+    @IntDef(prefix = { "SESSION_TYPE_" }, value = {
+            SESSION_TYPE_IPV4,
+            SESSION_TYPE_IPV6,
+            SESSION_TYPE_IPV4V6,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RouteSessionType {}
+
+    /**
+     * The route selection descriptor is using SSC mode 1. The session will provide continual
+     * support when UE's location is updated.
+     */
+    public static final int ROUTE_SSC_MODE_1 = 1;
+
+    /**
+     * The route selection descriptor is using SSC mode 2. The new session for the same network
+     * will be established after releasing the old session when UE's location is updated.
+     */
+    public static final int ROUTE_SSC_MODE_2 = 2;
+
+    /**
+     * The route selection descriptor is using SSC mode 3. The new session for the same network is
+     * allowed to be established before releasing the old session when UE's location is updated.
+     */
+    public static final int ROUTE_SSC_MODE_3 = 3;
+
+    /**
+     * The min acceptable value for the SSC mode of a route selection descriptor.
+     * @hide
+     */
+    public static final int MIN_ROUTE_SSC_MODE = ROUTE_SSC_MODE_1;
+
+    /**
+     * The max acceptable value for the SSC mode of a route selection descriptor.
+     * @hide
+     */
+    public static final int MAX_ROUTE_SSC_MODE = ROUTE_SSC_MODE_3;
+
+    /** @hide */
+    @IntDef(prefix = { "ROUTE_SSC_MODE_" }, value = {
+            ROUTE_SSC_MODE_1,
+            ROUTE_SSC_MODE_2,
+            ROUTE_SSC_MODE_3,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RouteSscMode {}
+
+    @IntRange(from = MIN_ROUTE_PRECEDENCE, to = MAX_ROUTE_PRECEDENCE)
+    private final int mPrecedence;
+    @RouteSessionType
+    private final int mSessionType;
+    @RouteSscMode
+    @IntRange(from = MIN_ROUTE_SSC_MODE, to = MAX_ROUTE_SSC_MODE)
+    private final int mSscMode;
+    private final List<NetworkSliceInfo> mSliceInfo;
+    private final List<String> mDnn;
+
+    /** @hide */
+    RouteSelectionDescriptor(android.hardware.radio.V1_6.RouteSelectionDescriptor rsd) {
+        this(rsd.precedence, rsd.sessionType.value(), rsd.sscMode.value(), rsd.sliceInfo,
+                rsd.dnn);
+    }
+
+    /** @hide */
+    public RouteSelectionDescriptor(int precedence, int sessionType, int sscMode,
+            List<android.hardware.radio.V1_6.SliceInfo> sliceInfo, List<String> dnn) {
+        mPrecedence = precedence;
+        mSessionType = sessionType;
+        mSscMode = sscMode;
+        mSliceInfo = new ArrayList<NetworkSliceInfo>();
+        for (android.hardware.radio.V1_6.SliceInfo si : sliceInfo) {
+            mSliceInfo.add(sliceInfoBuilder(si));
+        }
+        mDnn = new ArrayList<String>();
+        mDnn.addAll(dnn);
+    }
+
+    private NetworkSliceInfo sliceInfoBuilder(android.hardware.radio.V1_6.SliceInfo si) {
+        NetworkSliceInfo.Builder builder = new NetworkSliceInfo.Builder()
+                .setSliceServiceType(si.sst)
+                .setMappedHplmnSliceServiceType(si.mappedHplmnSst);
+        if (si.sliceDifferentiator != NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE) {
+            builder
+                .setSliceDifferentiator(si.sliceDifferentiator)
+                .setMappedHplmnSliceDifferentiator(si.mappedHplmnSD);
+        }
+        return builder.build();
+    }
+
+    private RouteSelectionDescriptor(Parcel p) {
+        mPrecedence = p.readInt();
+        mSessionType = p.readInt();
+        mSscMode = p.readInt();
+        mSliceInfo = p.createTypedArrayList(NetworkSliceInfo.CREATOR);
+        mDnn = new ArrayList<String>();
+        p.readStringList(mDnn);
+    }
+
+    /**
+     * Precedence value in the range of 0 to 255. Higher value has lower precedence.
+     * @return the precedence value for this route selection descriptor.
+     */
+    @IntRange(from = MIN_ROUTE_PRECEDENCE, to = MAX_ROUTE_PRECEDENCE)
+    public int getPrecedence() {
+        return mPrecedence;
+    }
+
+    /**
+     * This is used for checking which session type defined in 3GPP TS 23.501 is allowed for the
+     * route in a route selection descriptor.
+     * @return the session type for this route selection descriptor.
+     */
+    @RouteSessionType
+    public int getSessionType() {
+        return mSessionType;
+    }
+
+    /**
+     * SSC mode stands for Session and Service Continuity mode (which specifies the IP continuity
+     * mode) as defined in 3GPP TS 23.501.
+     * @return the SSC mode for this route selection descriptor.
+     */
+    @RouteSscMode
+    public int getSscMode() {
+        return mSscMode;
+    }
+
+    /**
+     * This is the list of all the slices available in the route selection descriptor as indicated
+     * by the network. These are the slices that can be used by the device if this route selection
+     * descriptor is used based the traffic (see 3GPP TS 23.501 for details).
+     * @return the list of all the slices available in the route selection descriptor.
+     */
+    public @NonNull List<NetworkSliceInfo> getSliceInfo() {
+        return mSliceInfo;
+    }
+
+    /**
+     * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003. There
+     * can be 0 or more DNNs specified in a route selection descriptor.
+     * @return the list of DNN for this route selection descriptor.
+     */
+    public @NonNull List<String> getDataNetworkName() {
+        return mDnn;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mPrecedence);
+        dest.writeInt(mSessionType);
+        dest.writeInt(mSscMode);
+        dest.writeTypedList(mSliceInfo, flags);
+        dest.writeStringList(mDnn);
+    }
+
+    public static final @NonNull Parcelable.Creator<RouteSelectionDescriptor> CREATOR =
+            new Parcelable.Creator<RouteSelectionDescriptor>() {
+                @Override
+                public RouteSelectionDescriptor createFromParcel(Parcel source) {
+                    return new RouteSelectionDescriptor(source);
+                }
+
+                @Override
+                public RouteSelectionDescriptor[] newArray(int size) {
+                    return new RouteSelectionDescriptor[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        RouteSelectionDescriptor that = (RouteSelectionDescriptor) o;
+        return mPrecedence == that.mPrecedence
+                && mSessionType == that.mSessionType
+                && mSscMode == that.mSscMode
+                && mSliceInfo.size() == that.mSliceInfo.size()
+                && mSliceInfo.containsAll(that.mSliceInfo)
+                && mDnn.size() == that.mDnn.size()
+                && mDnn.containsAll(that.mDnn);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPrecedence, mSessionType, mSscMode, mSliceInfo, mDnn);
+    }
+
+    @Override
+    public String toString() {
+        return "{.precedence = " + mPrecedence + ", .sessionType = " + mSessionType
+                + ", .sscMode = " + mSscMode + ", .sliceInfo = " + mSliceInfo
+                + ", .dnn = " + mDnn + "}";
+    }
+}
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/SlicingConfig.aidl
similarity index 87%
copy from telephony/java/android/telephony/data/SliceInfo.aidl
copy to telephony/java/android/telephony/data/SlicingConfig.aidl
index 286ea5e..ad93d8c 100644
--- a/telephony/java/android/telephony/data/SliceInfo.aidl
+++ b/telephony/java/android/telephony/data/SlicingConfig.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-/** @hide */
 package android.telephony.data;
 
-parcelable SliceInfo;
+parcelable SlicingConfig;
diff --git a/telephony/java/android/telephony/data/SlicingConfig.java b/telephony/java/android/telephony/data/SlicingConfig.java
new file mode 100644
index 0000000..990e4d2
--- /dev/null
+++ b/telephony/java/android/telephony/data/SlicingConfig.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a slicing configuration
+ */
+public final class SlicingConfig implements Parcelable {
+    private final List<UrspRule> mUrspRules;
+    private final List<NetworkSliceInfo> mSliceInfo;
+
+    public SlicingConfig() {
+        mUrspRules = new ArrayList<UrspRule>();
+        mSliceInfo = new ArrayList<NetworkSliceInfo>();
+    }
+
+    /** @hide */
+    public SlicingConfig(android.hardware.radio.V1_6.SlicingConfig sc) {
+        this(sc.urspRules, sc.sliceInfo);
+    }
+
+    /** @hide */
+    public SlicingConfig(List<android.hardware.radio.V1_6.UrspRule> urspRules,
+            List<android.hardware.radio.V1_6.SliceInfo> sliceInfo) {
+        mUrspRules = new ArrayList<UrspRule>();
+        for (android.hardware.radio.V1_6.UrspRule ur : urspRules) {
+            mUrspRules.add(new UrspRule(ur.precedence, ur.trafficDescriptors,
+                    ur.routeSelectionDescriptor));
+        }
+        mSliceInfo = new ArrayList<NetworkSliceInfo>();
+        for (android.hardware.radio.V1_6.SliceInfo si : sliceInfo) {
+            mSliceInfo.add(sliceInfoBuilder(si));
+        }
+    }
+
+    private NetworkSliceInfo sliceInfoBuilder(android.hardware.radio.V1_6.SliceInfo si) {
+        NetworkSliceInfo.Builder builder = new NetworkSliceInfo.Builder()
+                .setSliceServiceType(si.sst)
+                .setMappedHplmnSliceServiceType(si.mappedHplmnSst);
+        if (si.sliceDifferentiator != NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE) {
+            builder
+                .setSliceDifferentiator(si.sliceDifferentiator)
+                .setMappedHplmnSliceDifferentiator(si.mappedHplmnSD);
+        }
+        return builder.build();
+    }
+
+    /** @hide */
+    public SlicingConfig(Parcel p) {
+        mUrspRules = p.createTypedArrayList(UrspRule.CREATOR);
+        mSliceInfo = p.createTypedArrayList(NetworkSliceInfo.CREATOR);
+    }
+
+    /**
+     * This list contains the current URSP rules. Empty list represents that no rules are
+     * configured.
+     * @return the current URSP rules for this slicing configuration.
+     */
+    public @NonNull List<UrspRule> getUrspRules() {
+        return mUrspRules;
+    }
+
+    /**
+     * @return the list of all slices for this slicing configuration.
+     */
+    public @NonNull List<NetworkSliceInfo> getSliceInfo() {
+        return mSliceInfo;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedList(mUrspRules, flags);
+        dest.writeTypedList(mSliceInfo, flags);
+    }
+
+    public static final @NonNull Parcelable.Creator<SlicingConfig> CREATOR =
+            new Parcelable.Creator<SlicingConfig>() {
+                @Override
+                public SlicingConfig createFromParcel(Parcel source) {
+                    return new SlicingConfig(source);
+                }
+
+                @Override
+                public SlicingConfig[] newArray(int size) {
+                    return new SlicingConfig[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SlicingConfig that = (SlicingConfig) o;
+        return mUrspRules.size() == that.mUrspRules.size()
+                && mUrspRules.containsAll(that.mUrspRules)
+                && mSliceInfo.size() == that.mSliceInfo.size()
+                && mSliceInfo.containsAll(that.mSliceInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mUrspRules, mSliceInfo);
+    }
+
+    @Override
+    public String toString() {
+        return "{.urspRules = " + mUrspRules + ", .sliceInfo = " + mSliceInfo + "}";
+    }
+}
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
index 480379d..d813bc5 100644
--- a/telephony/java/android/telephony/data/TrafficDescriptor.java
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -18,20 +18,17 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import java.util.Objects;
 
 /**
- * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for URSP traffic
- * matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an optional DNN, which,
- * if present, must be used for traffic matching; it does not specify the end point to be used for
- * the data call.
- * @hide
+ * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for UE Route Selection
+ * Policy(URSP) traffic matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an
+ * optional Data Network Name(DNN), which, if present, must be used for traffic matching; it does
+ * not specify the end point to be used for the data call.
  */
-@SystemApi
 public final class TrafficDescriptor implements Parcelable {
     private final String mDnn;
     private final String mOsAppId;
@@ -45,8 +42,10 @@
      * Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
      * @param dnn optional DNN, which must be used for traffic matching, if present
      * @param osAppId OsId + osAppId of the traffic descriptor
+     *
+     * @hide
      */
-    public TrafficDescriptor(@Nullable String dnn, @Nullable String osAppId) {
+    public TrafficDescriptor(String dnn, String osAppId) {
         mDnn = dnn;
         mOsAppId = osAppId;
     }
@@ -55,12 +54,13 @@
      * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
      * @return the DNN of this traffic descriptor.
      */
-    public @Nullable String getDnn() {
+    public @Nullable String getDataNetworkName() {
         return mDnn;
     }
 
     /**
-     * OsAppId represents the OsId + OsAppId as defined in 3GPP TS 24.526 Section 5.2.
+     * OsAppId is the app id as defined in 3GPP TS 24.526 Section 5.2, and it identifies a traffic
+     * category.
      * @return the OS App ID of this traffic descriptor.
      */
     public @Nullable String getOsAppId() {
@@ -108,4 +108,65 @@
     public int hashCode() {
         return Objects.hash(mDnn, mOsAppId);
     }
+
+    /**
+     * Provides a convenient way to set the fields of a {@link TrafficDescriptor} when creating a
+     * new instance.
+     *
+     * <p>The example below shows how you might create a new {@code TrafficDescriptor}:
+     *
+     * <pre><code>
+     *
+     * TrafficDescriptor response = new TrafficDescriptor.Builder()
+     *     .setDnn("")
+     *     .build();
+     * </code></pre>
+     */
+    public static final class Builder {
+        private String mDnn = null;
+        private String mOsAppId = null;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Set the Data Network Name(DNN).
+         *
+         * @return The same instance of the builder.
+         */
+        @NonNull
+        public Builder setDataNetworkName(@NonNull String dnn) {
+            this.mDnn = dnn;
+            return this;
+        }
+
+        /**
+         * Set the OS App ID.
+         *
+         * @return The same instance of the builder.
+         */
+        @NonNull
+        public Builder setOsAppId(@NonNull String osAppId) {
+            this.mOsAppId = osAppId;
+            return this;
+        }
+
+        /**
+         * Build the {@link TrafficDescriptor}.
+         *
+         * @throws IllegalArgumentException if DNN and OS App ID are null.
+         *
+         * @return the {@link TrafficDescriptor} object.
+         */
+        @NonNull
+        public TrafficDescriptor build() {
+            if (this.mDnn == null && this.mOsAppId == null) {
+                throw new IllegalArgumentException("DNN and OS App ID are null");
+            }
+            return new TrafficDescriptor(this.mDnn, this.mOsAppId);
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/UrspRule.aidl
similarity index 87%
copy from telephony/java/android/telephony/data/SliceInfo.aidl
copy to telephony/java/android/telephony/data/UrspRule.aidl
index 286ea5e..2bed583 100644
--- a/telephony/java/android/telephony/data/SliceInfo.aidl
+++ b/telephony/java/android/telephony/data/UrspRule.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-/** @hide */
 package android.telephony.data;
 
-parcelable SliceInfo;
+parcelable UrspRule;
diff --git a/telephony/java/android/telephony/data/UrspRule.java b/telephony/java/android/telephony/data/UrspRule.java
new file mode 100644
index 0000000..e2c47fd
--- /dev/null
+++ b/telephony/java/android/telephony/data/UrspRule.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.radio.V1_6.OptionalDnn;
+import android.hardware.radio.V1_6.OptionalOsAppId;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a single URSP rule as defined in 3GPP TS 24.526. URSP stands for UE Route Selection
+ * Policy. In 5G, network can provide URSP information to devices which provides information on
+ * what connection parameters should be used for what traffic.
+ */
+public final class UrspRule implements Parcelable {
+    /**
+     * The min acceptable value for the precedence of a URSP rule.
+     * @hide
+     */
+    public static final int MIN_URSP_PRECEDENCE = 0;
+
+    /**
+     * The max acceptable value for the precedence of a URSP rule.
+     * @hide
+     */
+    public static final int MAX_URSP_PRECEDENCE = 255;
+
+    @IntRange(from = MIN_URSP_PRECEDENCE, to = MAX_URSP_PRECEDENCE)
+    private final int mPrecedence;
+    private final List<TrafficDescriptor> mTrafficDescriptors;
+    private final List<RouteSelectionDescriptor> mRouteSelectionDescriptor;
+
+    UrspRule(android.hardware.radio.V1_6.UrspRule ur) {
+        this(ur.precedence, ur.trafficDescriptors, ur.routeSelectionDescriptor);
+    }
+
+    /** @hide */
+    public UrspRule(int precedence,
+            List<android.hardware.radio.V1_6.TrafficDescriptor> trafficDescriptors,
+            List<android.hardware.radio.V1_6.RouteSelectionDescriptor> routeSelectionDescriptor) {
+        mPrecedence = precedence;
+        mTrafficDescriptors = new ArrayList<TrafficDescriptor>();
+        for (android.hardware.radio.V1_6.TrafficDescriptor td : trafficDescriptors) {
+            mTrafficDescriptors.add(convertToTrafficDescriptor(td));
+        }
+        mRouteSelectionDescriptor = new ArrayList<RouteSelectionDescriptor>();
+        for (android.hardware.radio.V1_6.RouteSelectionDescriptor rsd : routeSelectionDescriptor) {
+            mRouteSelectionDescriptor.add(new RouteSelectionDescriptor(rsd));
+        }
+    }
+
+    /** Convert an ArrayList of Bytes to an exactly-sized primitive array */
+    private byte[] arrayListToPrimitiveArray(ArrayList<Byte> bytes) {
+        byte[] ret = new byte[bytes.size()];
+        for (int i = 0; i < ret.length; i++) {
+            ret[i] = bytes.get(i);
+        }
+        return ret;
+    }
+
+    private TrafficDescriptor convertToTrafficDescriptor(
+            android.hardware.radio.V1_6.TrafficDescriptor td) {
+        String dnn = td.dnn.getDiscriminator() == OptionalDnn.hidl_discriminator.noinit
+                ? null : td.dnn.value();
+        String osAppId = td.osAppId.getDiscriminator() == OptionalOsAppId.hidl_discriminator.noinit
+                ? null : new String(arrayListToPrimitiveArray(td.osAppId.value().osAppId));
+        TrafficDescriptor.Builder builder = new TrafficDescriptor.Builder();
+        if (dnn != null) {
+            builder.setDataNetworkName(dnn);
+        }
+        if (osAppId != null) {
+            builder.setOsAppId(osAppId);
+        }
+        return builder.build();
+    }
+
+    private UrspRule(Parcel p) {
+        mPrecedence = p.readInt();
+        mTrafficDescriptors = p.createTypedArrayList(TrafficDescriptor.CREATOR);
+        mRouteSelectionDescriptor = p.createTypedArrayList(RouteSelectionDescriptor.CREATOR);
+    }
+
+    /**
+     * Precedence value in the range of 0 to 255. Higher value has lower precedence.
+     * @return the precedence value for this URSP rule.
+     */
+    @IntRange(from = MIN_URSP_PRECEDENCE, to = MAX_URSP_PRECEDENCE)
+    public int getPrecedence() {
+        return mPrecedence;
+    }
+
+    /**
+     * These traffic descriptors are used as a matcher for network requests.
+     * @return the traffic descriptors which are associated to this URSP rule.
+     */
+    public @NonNull List<TrafficDescriptor> getTrafficDescriptors() {
+        return mTrafficDescriptors;
+    }
+
+    /**
+     * List of routes (connection parameters) that must be used by the device for requests matching
+     * a traffic descriptor.
+     * @return the route selection descriptors which are associated to this URSP rule.
+     */
+    public @NonNull List<RouteSelectionDescriptor> getRouteSelectionDescriptor() {
+        return mRouteSelectionDescriptor;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mPrecedence);
+        dest.writeTypedList(mTrafficDescriptors, flags);
+        dest.writeTypedList(mRouteSelectionDescriptor, flags);
+    }
+
+    public static final @NonNull Parcelable.Creator<UrspRule> CREATOR =
+            new Parcelable.Creator<UrspRule>() {
+                @Override
+                public UrspRule createFromParcel(Parcel source) {
+                    return new UrspRule(source);
+                }
+
+                @Override
+                public UrspRule[] newArray(int size) {
+                    return new UrspRule[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        UrspRule that = (UrspRule) o;
+        return mPrecedence == that.mPrecedence
+                && mTrafficDescriptors.size() == that.mTrafficDescriptors.size()
+                && mTrafficDescriptors.containsAll(that.mTrafficDescriptors)
+                && mRouteSelectionDescriptor.size() == that.mRouteSelectionDescriptor.size()
+                && mRouteSelectionDescriptor.containsAll(that.mRouteSelectionDescriptor);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPrecedence, mTrafficDescriptors, mRouteSelectionDescriptor);
+    }
+
+    @Override
+    public String toString() {
+        return "{.precedence = " + mPrecedence + ", .trafficDescriptors = " + mTrafficDescriptors
+                + ", .routeSelectionDescriptor = " + mRouteSelectionDescriptor + "}";
+    }
+}
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 0aff997..dfe5e6c9 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -766,7 +766,10 @@
      * The method is only valid to call when the session state is in
      * {@link ImsCallSession.State#IDLE}.
      *
-     * @param callee dialed string to make the call to
+     * @param callee dial string to make the call to.  The platform passes the dialed number
+     *               entered by the user as-is.  The {@link ImsService} should ensure that the
+     *               number is formatted in SIP messages appropriately (e.g. using
+     *               {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}).
      * @param profile call profile to make the call with the specified service type,
      *      call type and media information
      * @see Listener#callSessionStarted, Listener#callSessionStartFailed
@@ -788,7 +791,10 @@
      * The method is only valid to call when the session state is in
      * {@link ImsCallSession.State#IDLE}.
      *
-     * @param participants participant list to initiate an IMS conference call
+     * @param participants participant list to initiate an IMS conference call.  The platform passes
+     *               the dialed numbers entered by the user as-is.  The {@link ImsService} should
+     *               ensure that the number is formatted in SIP messages appropriately (e.g. using
+     *               {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}).
      * @param profile call profile to make the call with the specified service type,
      *      call type and media information
      * @see Listener#callSessionStarted, Listener#callSessionStartFailed
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 7403327..ac1033a 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -444,7 +444,12 @@
             iTelephony.getImsMmTelRegistrationState(mSubId, new IIntegerConsumer.Stub() {
                 @Override
                 public void accept(int result) {
-                    executor.execute(() -> stateCallback.accept(result));
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(() -> stateCallback.accept(result));
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
                 }
             });
         } catch (RemoteException e) {
@@ -485,7 +490,12 @@
                     new IIntegerConsumer.Stub() {
                         @Override
                         public void accept(int result) {
-                            executor.execute(() -> transportTypeCallback.accept(result));
+                            final long identity = Binder.clearCallingIdentity();
+                            try {
+                                executor.execute(() -> transportTypeCallback.accept(result));
+                            } finally {
+                                Binder.restoreCallingIdentity(identity);
+                            }
                         }
                     });
         } catch (RemoteException e) {
@@ -802,7 +812,12 @@
             iTelephony.isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
                 @Override
                 public void accept(int result) {
-                    executor.execute(() -> callback.accept(result == 1));
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(() -> callback.accept(result == 1));
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
                 }
             }, capability, transportType);
         } catch (ServiceSpecificException sse) {
@@ -1348,7 +1363,12 @@
             iTelephony.getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() {
                 @Override
                 public void accept(int result) {
-                    executor.execute(() -> callback.accept(result));
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(() -> callback.accept(result));
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
                 }
             });
         } catch (ServiceSpecificException sse) {
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 81d8207..1c7fbc4 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -299,7 +299,12 @@
             imsRcsController.getImsRcsRegistrationState(mSubId, new IIntegerConsumer.Stub() {
                 @Override
                 public void accept(int result) {
-                    executor.execute(() -> stateCallback.accept(result));
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(() -> stateCallback.accept(result));
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
                 }
             });
         } catch (RemoteException e) {
@@ -343,7 +348,12 @@
                     new IIntegerConsumer.Stub() {
                         @Override
                         public void accept(int result) {
-                            executor.execute(() -> transportTypeCallback.accept(result));
+                            final long identity = Binder.clearCallingIdentity();
+                            try {
+                                executor.execute(() -> transportTypeCallback.accept(result));
+                            } finally {
+                                Binder.restoreCallingIdentity(identity);
+                            }
                         }
                     });
         } catch (RemoteException e) {
diff --git a/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl b/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
index 1a1c7f8..43273a4 100755
--- a/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
+++ b/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
@@ -25,6 +25,7 @@
 {
     void onError(int errorCode, String message);
 
+    @SuppressWarnings(value={"untyped-collection"})
     void onAvailableSaisUpdated(in List currentSai, in List availableSais);
 
     void onServiceInterfaceAvailable(String interfaceName, int index);
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
index 44cc24a..6e139ac 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
@@ -29,9 +29,11 @@
 
     void stopGroupCall(int subId, long tmgi);
 
+    @SuppressWarnings(value={"untyped-collection"})
     void updateGroupCall(int subscriptionId, long tmgi, in List saiList,
         in List frequencyList);
 
+    @SuppressWarnings(value={"untyped-collection"})
     int startGroupCall(int subscriptionId, long tmgi, in List saiList,
         in List frequencyList, IGroupCallCallback callback);
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 374aeda..d812b46 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -43,6 +43,7 @@
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.NetworkScanRequest;
+import android.telephony.PhoneCapability;
 import android.telephony.PhoneNumberRange;
 import android.telephony.RadioAccessFamily;
 import android.telephony.RadioAccessSpecifier;
@@ -1960,6 +1961,7 @@
     /**
      * Return the emergency number list from all the active subscriptions.
      */
+    @SuppressWarnings(value={"untyped-collection"})
     Map getEmergencyNumberList(String callingPackage, String callingFeatureId);
 
     /**
@@ -2440,4 +2442,15 @@
      * of error.
      */
     int prepareForUnattendedReboot();
+
+    /**
+     * Gets the current phone capability.
+     */
+    PhoneCapability getPhoneCapability();
+
+    /**
+     * Request to get the current slicing configuration including URSP rules and
+     * NSSAIs (configured, allowed and rejected).
+     */
+    void getSlicingConfig(in ResultReceiver callback);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 822fc44..fe8e671 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -527,6 +527,7 @@
     int RIL_REQUEST_SET_DATA_THROTTLING = 221;
     int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP = 222;
     int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP = 223;
+    int RIL_REQUEST_GET_SLICING_CONFIG = 224;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 460a26d..0bb6198 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -32,7 +32,9 @@
         ":android-test-mock-sources",
         // Note: Below are NOT APIs of this library. We only take APIs under
         // the android.test.mock package. They however provide private APIs that
-        // android.test.mock APIs references to.
+        // android.test.mock APIs references to. We need to have the classes in
+        // source code form to have access to the @hide comment which disappears
+        // when the classes are compiled into a Jar library.
         ":framework-core-sources-for-test-mock",
         ":framework_native_aidl",
     ],
@@ -46,6 +48,14 @@
     api_packages: [
         "android.test.mock",
     ],
+    // Only include android.test.mock.* classes. Jarjar rules below removes
+    // classes in other packages like android.content. In order to keep the
+    // list up-to-date, permitted_packages ensures that the library contains
+    // clases under android.test.mock after the jarjar rules are applied.
+    jarjar_rules: "jarjar-rules.txt",
+    permitted_packages: [
+        "android.test.mock",
+    ],
     compile_dex: true,
     default_to_stubs: true,
     dist_group: "android",
diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt
new file mode 100644
index 0000000..4420a44
--- /dev/null
+++ b/test-mock/jarjar-rules.txt
@@ -0,0 +1,7 @@
+zap android.accounts.**
+zap android.app.**
+zap android.content.**
+zap android.database.**
+zap android.os.**
+zap android.util.**
+zap android.view.**
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
index 4ecca2d..cf56586 100644
--- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -31,6 +31,8 @@
     private static final String SYSTEM_SERVER_PROFILE =
             "/data/misc/profiles/cur/0/android/primary.prof";
     private static final boolean USE_PHENOTYPE = false;
+    private static final String DALVIK_VM_EXTRA_OPTS =
+            "-Xusejit:false -Xint -Xjitsaveprofilinginfo";
 
     @Override
     public void setDevice(ITestDevice testDevice) {
@@ -54,10 +56,10 @@
     private String setProperty(String property, String value) throws Exception {
         if (USE_PHENOTYPE) {
             return mTestDevice.executeShellCommand(
-                "device_config put runtime_native_boot " + property + " " + value);
+                String.format("device_config put runtime_native_boot %s '%s'", property, value));
         } else {
             return mTestDevice.executeShellCommand(
-                "setprop dalvik.vm." + property + " " + value);
+                String.format("setprop dalvik.vm.%s '%s'", property, value));
         }
     }
 
@@ -69,6 +71,8 @@
         assertTrue("profile boot class path not enabled: " + res, "true".equals(res));
         res = getProperty("profilesystemserver");
         assertTrue("profile system server not enabled: " + res, "true".equals(res));
+        res = getProperty("extra-opts");
+        assertTrue("extra options not set: " + res, DALVIK_VM_EXTRA_OPTS.equals(res));
     }
 
     private boolean forceSaveProfile(String pkg) throws Exception {
@@ -91,16 +95,20 @@
             boolean profileBootClassPath = "true".equals(pbcp);
             String pss = getProperty("profilesystemserver");
             boolean profileSystemServer = "true".equals(pss);
-            if (profileBootClassPath && profileSystemServer) {
+            String extraOpts = getProperty("extra-opts");
+            boolean extraOptsOk = DALVIK_VM_EXTRA_OPTS.equals(extraOpts);
+            if (profileBootClassPath && profileSystemServer && extraOptsOk) {
                 break;
             }
             if (i == numIterations) {
                 assertTrue("profile system server not enabled: " + pss, profileSystemServer);
                 assertTrue("profile boot class path not enabled: " + pbcp, profileBootClassPath);
+                assertTrue("extra options not set: " + extraOpts, extraOptsOk);
             }
 
             setProperty("profilebootclasspath", "true");
             setProperty("profilesystemserver", "true");
+            setProperty("extra-opts", DALVIK_VM_EXTRA_OPTS);
             Thread.sleep(1000);
         }
 
@@ -114,12 +122,15 @@
             boolean profileBootClassPath = "true".equals(pbcp);
             String pss = getProperty("profilesystemserver");
             boolean profileSystemServer = "true".equals(pss);
+            String extraOpts = getProperty("extra-opts");
+            boolean extraOptsOk = DALVIK_VM_EXTRA_OPTS.equals(extraOpts);
             if (profileBootClassPath && profileSystemServer) {
                 break;
             }
             if (i == numIterations) {
                 assertTrue("profile system server not enabled: " + pss, profileSystemServer);
                 assertTrue("profile boot class path not enabled: " + pbcp, profileBootClassPath);
+                assertTrue("extra options not set: " + extraOpts, extraOptsOk);
             }
             Thread.sleep(1000);
         }
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 243c301..086ef95 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -25,14 +25,24 @@
     name: "StagedInstallInternalTestApp",
     manifest: "app/AndroidManifest.xml",
     srcs: ["app/src/**/*.java"],
-    static_libs: ["androidx.test.rules", "cts-install-lib"],
+    static_libs: [
+        "androidx.test.rules",
+        "cts-install-lib",
+    ],
     test_suites: ["general-tests"],
+    java_resources: [
+        ":StagedInstallTestApexV2",
+    ],
+    platform_apis: true,
 }
 
 java_test_host {
     name: "StagedInstallInternalTest",
     srcs: ["src/**/*.java"],
-    libs: ["tradefed", "cts-shim-host-lib"],
+    libs: [
+        "tradefed",
+        "cts-shim-host-lib",
+    ],
     static_libs: [
         "testng",
         "compatibility-tradefed",
@@ -40,7 +50,7 @@
         "cts-install-lib-host",
     ],
     data: [
-        ":com.android.apex.cts.shim.v2_prebuilt",
+        ":StagedInstallTestApexV2",
         ":TestAppAv1",
     ],
     test_suites: ["general-tests"],
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index e673549..a0f4e0a 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -17,12 +17,24 @@
 package com.android.tests.stagedinstallinternal;
 
 import static com.android.cts.install.lib.InstallUtils.getPackageInstaller;
+import static com.android.cts.install.lib.InstallUtils.waitForSessionReady;
+import static com.android.cts.shim.lib.ShimPackage.SHIM_APEX_PACKAGE_NAME;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
 import android.Manifest;
+import android.content.pm.ApexStagedEvent;
+import android.content.pm.IPackageManagerNative;
+import android.content.pm.IStagedApexObserver;
 import android.content.pm.PackageInstaller;
+import android.content.pm.StagedApexInfo;
+import android.os.IBinder;
+import android.os.ServiceManager;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
@@ -35,6 +47,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -50,6 +64,10 @@
 
     private static final String TAG = StagedInstallInternalTest.class.getSimpleName();
 
+    private static final TestApp APEX_V2 = new TestApp(
+            "ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
+            "com.android.apex.cts.shim.v2.apex");
+
     private File mTestStateFile = new File(
             InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
             "stagedinstall_state");
@@ -109,6 +127,72 @@
                 Install.multi(TestApp.AIncompleteSplit, TestApp.B1, TestApp.Apex1).setStaged());
     }
 
+    @Test
+    public void testGetStagedModuleNames() throws Exception {
+        // Before staging a session
+        String[] result = getPackageManagerNative().getStagedApexModuleNames();
+        assertThat(result).hasLength(0);
+        // Stage an apex
+        int sessionId = Install.single(APEX_V2).setStaged().commit();
+        waitForSessionReady(sessionId);
+        result = getPackageManagerNative().getStagedApexModuleNames();
+        assertThat(result).hasLength(1);
+        assertThat(result).isEqualTo(new String[]{SHIM_APEX_PACKAGE_NAME});
+        // Abandon the session
+        InstallUtils.openPackageInstallerSession(sessionId).abandon();
+        result = getPackageManagerNative().getStagedApexModuleNames();
+        assertThat(result).hasLength(0);
+    }
+
+    @Test
+    public void testGetStagedApexInfo() throws Exception {
+        // Ask for non-existing module
+        StagedApexInfo result = getPackageManagerNative().getStagedApexInfo("not found");
+        assertThat(result).isNull();
+        // Stage an apex
+        int sessionId = Install.single(APEX_V2).setStaged().commit();
+        waitForSessionReady(sessionId);
+        // Query proper module name
+        result = getPackageManagerNative().getStagedApexInfo(SHIM_APEX_PACKAGE_NAME);
+        assertThat(result.moduleName).isEqualTo(SHIM_APEX_PACKAGE_NAME);
+        InstallUtils.openPackageInstallerSession(sessionId).abandon();
+    }
+
+    public static class MockStagedApexObserver extends IStagedApexObserver.Stub {
+        @Override
+        public void onApexStaged(ApexStagedEvent event) {
+            assertThat(event).isNotNull();
+        }
+    }
+
+    @Test
+    public void testStagedApexObserver() throws Exception {
+        MockStagedApexObserver realObserver = new MockStagedApexObserver();
+        IStagedApexObserver observer = spy(realObserver);
+        assertThat(observer).isNotNull();
+        getPackageManagerNative().registerStagedApexObserver(observer);
+
+        // Stage an apex and verify observer was called
+        int sessionId = Install.single(APEX_V2).setStaged().commit();
+        waitForSessionReady(sessionId);
+        ArgumentCaptor<ApexStagedEvent> captor = ArgumentCaptor.forClass(ApexStagedEvent.class);
+        verify(observer, timeout(5000)).onApexStaged(captor.capture());
+        assertThat(captor.getValue().stagedApexModuleNames).isEqualTo(
+                new String[] {SHIM_APEX_PACKAGE_NAME});
+
+        // Abandon and verify observer is called
+        Mockito.clearInvocations(observer);
+        InstallUtils.openPackageInstallerSession(sessionId).abandon();
+        verify(observer, timeout(5000)).onApexStaged(captor.capture());
+        assertThat(captor.getValue().stagedApexModuleNames).hasLength(0);
+    }
+
+    private IPackageManagerNative getPackageManagerNative() {
+        IBinder binder = ServiceManager.waitForService("package_native");
+        assertThat(binder).isNotNull();
+        return IPackageManagerNative.Stub.asInterface(binder);
+    }
+
     private static void assertSessionReady(int sessionId) {
         assertSessionState(sessionId,
                 (session) -> assertThat(session.isStagedSessionReady()).isTrue());
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index dddb317..f92c31c 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -216,6 +216,21 @@
         assertThat(getStagingDirectories()).isEmpty();
     }
 
+    @Test
+    public void testGetStagedModuleNames() throws Exception {
+        runPhase("testGetStagedModuleNames");
+    }
+
+    @Test
+    public void testGetStagedApexInfo() throws Exception {
+        runPhase("testGetStagedApexInfo");
+    }
+
+    @Test
+    public void testStagedApexObserver() throws Exception {
+        runPhase("testStagedApexObserver");
+    }
+
     private List<String> getStagingDirectories() throws DeviceNotAvailableException {
         String baseDir = "/data/app-staging";
         try {
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 0f84f6e..c9a8947a 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -322,6 +322,7 @@
         triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
         verify(mSafeModeTimeoutAlarm).cancel();
         assertFalse(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
     }
 
     @Test
@@ -391,6 +392,7 @@
 
         triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
 
+        verifySafeModeStateAndCallbackFired(2 /* invocationCount */, false /* isInSafeMode */);
         assertFalse(mGatewayConnection.isInSafeMode());
     }
 
@@ -400,7 +402,7 @@
         mTestLooper.dispatchAll();
 
         triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
-        assertFalse(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
 
         // Trigger a failed validation, and the subsequent safemode timeout.
         triggerValidation(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
@@ -416,7 +418,7 @@
         runnableCaptor.getValue().run();
         mTestLooper.dispatchAll();
 
-        assertTrue(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(2 /* invocationCount */, true /* isInSafeMode */);
     }
 
     private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() {
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index a696b3a..64d0bca 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -23,7 +23,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -301,6 +300,11 @@
                 expectCanceled);
     }
 
+    protected void verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode) {
+        verify(mGatewayStatusCallback, times(invocationCount)).onSafeModeStatusChanged();
+        assertEquals(isInSafeMode, mGatewayConnection.isInSafeMode());
+    }
+
     protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
             @NonNull State expectedState) {
         // Set a VcnNetworkAgent, and expect it to be unregistered and cleared
@@ -314,9 +318,8 @@
         delayedEvent.run();
         mTestLooper.dispatchAll();
 
-        verify(mGatewayStatusCallback).onSafeModeStatusChanged();
         assertEquals(expectedState, mGatewayConnection.getCurrentState());
-        assertTrue(mGatewayConnection.isInSafeMode());
+        verifySafeModeStateAndCallbackFired(1, true);
 
         verify(mockNetworkAgent).unregister();
         assertNull(mGatewayConnection.getNetworkAgent());
diff --git a/tests/vcn/java/com/android/server/vcn/VcnNetworkProviderTest.java b/tests/vcn/java/com/android/server/vcn/VcnNetworkProviderTest.java
index 72db55b..e9026e2 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnNetworkProviderTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnNetworkProviderTest.java
@@ -87,8 +87,8 @@
                         eq(mVcnNetworkProvider),
                         argThat(
                                 score ->
-                                        score.getLegacyInt()
-                                                == Vcn.getNetworkScore().getLegacyInt()),
+                                        score.getLegacyInt() == Vcn.getNetworkScore().getLegacyInt()
+                                                && score.isTransportPrimary()),
                         any(),
                         any(),
                         cbCaptor.capture());
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 672731c..899d268 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -319,12 +319,10 @@
 
             // The second subtag can either be a script or a region code.
             // If its size is 4, it's a script code, else it's a region code.
-            bool hasRegion = false;
             if (subtags[1].size() == 4) {
                 setScript(subtags[1]);
             } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
                 setRegion(subtags[1]);
-                hasRegion = true;
             } else {
                 fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n", part.string());
                 return -1;
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
index c75ba71..cf5f313 100644
--- a/tools/aapt/Android.bp
+++ b/tools/aapt/Android.bp
@@ -50,7 +50,6 @@
         "libbase",
         "libz",
     ],
-    group_static_libs: true,
 
     cflags: [
         "-Wall",
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 257e96b..b9de11b 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2475,11 +2475,10 @@
 {
     if (accessorCookie != NULL && fmt != NULL) {
         AccessorCookie* ac = (AccessorCookie*)accessorCookie;
-        int retval=0;
         char buf[1024];
         va_list ap;
         va_start(ap, fmt);
-        retval = vsnprintf(buf, sizeof(buf), fmt, ap);
+        vsnprintf(buf, sizeof(buf), fmt, ap);
         va_end(ap);
         ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n",
                             buf, ac->attr.string(), ac->value.string());
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 5c5b3c3..5de0a63 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -72,7 +72,6 @@
         "libidmap2_policies",
     ],
     stl: "libc++_static",
-    group_static_libs: true,
 }
 
 // ==========================================================
@@ -196,9 +195,9 @@
     ],
     defaults: ["aapt2_defaults"],
     data: [
-         "integration-tests/CompileTest/**/*",
-         "integration-tests/CommandTests/**/*",
-         "integration-tests/ConvertTest/**/*"
+        "integration-tests/CompileTest/**/*",
+        "integration-tests/CommandTests/**/*",
+        "integration-tests/ConvertTest/**/*",
     ],
 }
 
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 7546e41..ca1c1c2 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -26,9 +26,8 @@
 namespace aapt {
 
 static ApiVersion sDevelopmentSdkLevel = 10000;
-static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>({
-    "Q", "R", "S", "T"
-});
+static const auto sDevelopmentSdkCodeNames =
+    std::unordered_set<StringPiece>({"Q", "R", "S", "Tiramisu"});
 
 static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
     {0x021c, 1},
diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp
index d56994e..97e4436 100644
--- a/tools/aapt2/cmd/Diff.cpp
+++ b/tools/aapt2/cmd/Diff.cpp
@@ -148,7 +148,7 @@
       diff = true;
     }
   }
-  return false;
+  return diff;
 }
 
 static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a,
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index 3960856f..d345422 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -35,6 +35,7 @@
         echo
         echo "If your change contains no confidential details (such as security fixes), please"
         echo "upload and merge this change at https://android-review.googlesource.com/."
+        echo "Else add a tag 'Ignore-AOSP-First:' with the reason to bypass AOSP."
         echo
         exit 1
     fi
diff --git a/tools/bit/print.cpp b/tools/bit/print.cpp
index 35feda1..8bc6f16 100644
--- a/tools/bit/print.cpp
+++ b/tools/bit/print.cpp
@@ -17,6 +17,7 @@
 #include "print.h"
 
 #include <sys/ioctl.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
 
diff --git a/tools/bit/util.h b/tools/bit/util.h
index 7ccdab1..8c66911 100644
--- a/tools/bit/util.h
+++ b/tools/bit/util.h
@@ -17,6 +17,8 @@
 #ifndef UTIL_H
 #define UTIL_H
 
+#include <sys/types.h>
+
 #include <map>
 #include <string>
 #include <vector>
diff --git a/tools/lint/OWNERS b/tools/lint/OWNERS
new file mode 100644
index 0000000..7c04519
--- /dev/null
+++ b/tools/lint/OWNERS
@@ -0,0 +1,5 @@
+brufino@google.com
+jsharkey@google.com
+
+per-file *CallingSettingsNonUserGetterMethods* = file:/packages/SettingsProvider/OWNERS
+
diff --git a/tools/split-select/Android.bp b/tools/split-select/Android.bp
index c12fc6a..5402657 100644
--- a/tools/split-select/Android.bp
+++ b/tools/split-select/Android.bp
@@ -48,7 +48,6 @@
         "libbase",
         "libz",
     ],
-    group_static_libs: true,
 
     target: {
         windows: {
diff --git a/tools/streaming_proto/Errors.cpp b/tools/streaming_proto/Errors.cpp
index 0cd9037..6890d99 100644
--- a/tools/streaming_proto/Errors.cpp
+++ b/tools/streaming_proto/Errors.cpp
@@ -1,5 +1,6 @@
 #include "Errors.h"
 
+#include <stdarg.h>
 #include <stdlib.h>
 
 namespace android {