Merge "Check iface by TextUtils.equals"
diff --git a/Android.bp b/Android.bp
index 36ed865..b69fa63 100644
--- a/Android.bp
+++ b/Android.bp
@@ -50,12 +50,8 @@
         "SPDX-license-identifier-Apache-2.0",
         "SPDX-license-identifier-BSD",
         "SPDX-license-identifier-CC-BY",
-        "SPDX-license-identifier-CPL-1.0",
-        "SPDX-license-identifier-GPL",
-        "SPDX-license-identifier-GPL-2.0",
         "SPDX-license-identifier-MIT",
         "SPDX-license-identifier-Unicode-DFS",
-        "SPDX-license-identifier-W3C",
         "legacy_unencumbered",
     ],
     license_text: [
@@ -81,7 +77,7 @@
         ":framework-mca-effect-sources",
         ":framework-mca-filterfw-sources",
         ":framework-mca-filterpacks-sources",
-        ":framework-media-sources",
+        ":framework-media-non-updatable-sources",
         ":framework-mms-sources",
         ":framework-omapi-sources",
         ":framework-opengl-sources",
@@ -101,7 +97,7 @@
         ":platform-compat-native-aidl",
 
         // AIDL sources from external directories
-        ":android.hardware.security.keymint-V1-java-source",
+        ":android.hardware.security.keymint-V2-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
         ":android.security.apc-java-source",
         ":android.security.authorization-java-source",
@@ -141,44 +137,11 @@
 }
 
 java_library {
-    name: "framework-updatable-stubs-module_libs_api",
-    static_libs: [
-        "android.net.ipsec.ike.stubs.module_lib",
-        "framework-appsearch.stubs.module_lib",
-        "framework-connectivity.stubs.module_lib",
-        "framework-graphics.stubs.module_lib",
-        "framework-media.stubs.module_lib",
-        "framework-mediaprovider.stubs.module_lib",
-        "framework-permission.stubs.module_lib",
-        "framework-permission-s.stubs.module_lib",
-        "framework-scheduling.stubs.module_lib",
-        "framework-sdkextensions.stubs.module_lib",
-        "framework-statsd.stubs.module_lib",
-        "framework-tethering.stubs.module_lib",
-        "framework-wifi.stubs.module_lib",
-    ],
-    sdk_version: "module_current",
-    visibility: ["//visibility:private"],
-}
-
-java_library {
     name: "framework-all",
     installable: false,
     static_libs: [
-        "android.net.ipsec.ike.impl",
+        "all-framework-module-impl",
         "framework-minus-apex",
-        "framework-appsearch.impl",
-        "framework-connectivity.impl",
-        "framework-graphics.impl",
-        "framework-mediaprovider.impl",
-        "framework-permission.impl",
-        "framework-permission-s.impl",
-        "framework-scheduling.impl",
-        "framework-sdkextensions.impl",
-        "framework-statsd.impl",
-        "framework-tethering.impl",
-        "framework-wifi.impl",
-        "updatable-media",
     ],
     apex_available: ["//apex_available:platform"],
     sdk_version: "core_platform",
@@ -212,7 +175,6 @@
             "sax/java",
             "telecomm/java",
 
-            "apex/media/aidl/stable",
             // TODO(b/147699819): remove this
             "telephony/java",
         ],
@@ -296,6 +258,7 @@
     defaults: ["framework-aidl-export-defaults"],
     srcs: [
         ":framework-non-updatable-sources",
+        ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
         "core/java/**/*.logtags",
         ":apex-info-list",
     ],
@@ -307,7 +270,10 @@
         include_dirs: [
             "frameworks/av/aidl",
             "frameworks/native/libs/permission/aidl",
+            // TODO: remove when moved to the below package
+            "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
+            "packages/modules/Media/apex/aidl/stable",
         ],
     },
     dxflags: [
@@ -419,7 +385,6 @@
     name: "framework-ike-shared-srcs",
     visibility: ["//packages/modules/IPsec"],
     srcs: [
-        "core/java/android/net/annotations/PolicyDirection.java",
         "core/java/com/android/internal/util/HexDump.java",
         "core/java/com/android/internal/util/WakeupMessage.java",
         "services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java",
@@ -433,7 +398,6 @@
         // TODO: remove these annotations as soon as we can use andoid.support.annotations.*
         ":framework-annotations",
         ":modules-utils-preconditions-srcs",
-        "core/java/android/net/DhcpResults.java",
         "core/java/android/util/IndentingPrintWriter.java",
         "core/java/android/util/LocalLog.java",
         "core/java/com/android/internal/util/HexDump.java",
@@ -485,21 +449,28 @@
 }
 
 // TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
-    "--hide-package com.android.server " +
-    "--hide-package android.audio.policy.configuration.V7_0 " +
-    "--error UnhiddenSystemApi " +
-    "--hide RequiresPermission " +
-    "--hide CallbackInterface " +
-    "--hide MissingPermission --hide BroadcastBehavior " +
-    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
-    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
-    "--error NoSettingsProvider " +
-    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
+metalava_framework_docs_args = "" +
     "--api-lint-ignore-prefix android.icu. " +
     "--api-lint-ignore-prefix java. " +
     "--api-lint-ignore-prefix junit. " +
-    "--api-lint-ignore-prefix org. "
+    "--api-lint-ignore-prefix org. " +
+    "--error NoSettingsProvider " +
+    "--error UnhiddenSystemApi " +
+    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
+    "--hide BroadcastBehavior " +
+    "--hide CallbackInterface " +
+    "--hide DeprecationMismatch " +
+    "--hide HiddenSuperclass " +
+    "--hide HiddenTypeParameter " +
+    "--hide MissingPermission " +
+    "--hide-package android.audio.policy.configuration.V7_0 " +
+    "--hide-package com.android.server " +
+    "--hide RequiresPermission " +
+    "--hide SdkConstant " +
+    "--hide Todo " +
+    "--hide Typo " +
+    "--hide UnavailableSymbol " +
+    "--manifest $(location core/res/AndroidManifest.xml) "
 
 packages_to_document = [
     "android",
@@ -527,7 +498,9 @@
     visibility: ["//visibility:private"],
 }
 
-// These defaults are used for both the jar stubs and the doc stubs.
+// Defaults for all stubs that include the non-updatable framework. These defaults do not include
+// module symbols, so will not compile correctly on their own. Users must add module APIs to the
+// classpath (or sources) somehow.
 stubs_defaults {
     name: "android-non-updatable-stubs-defaults",
     srcs: [":android-non-updatable-stub-sources"],
@@ -535,16 +508,16 @@
     system_modules: "none",
     java_version: "1.8",
     arg_files: ["core/res/AndroidManifest.xml"],
-    // TODO(b/147699819): remove below aidl includes.
     aidl: {
         local_include_dirs: [
-            "apex/media/aidl/stable",
             "media/aidl",
             "telephony/java",
         ],
         include_dirs: [
             "frameworks/av/aidl",
             "frameworks/native/libs/permission/aidl",
+            // TODO: remove when moved to the below package
+            "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
         ],
     },
@@ -567,15 +540,6 @@
         "android.hardware.usb.gadget-V1.0-java",
         "android.hardware.vibrator-V1.3-java",
         "framework-protos",
-        "art.module.public.api",
-        "sdk_module-lib_current_framework-tethering",
-        // There are a few classes from modules used by the core that
-        // need to be resolved by metalava. We use a prebuilt stub of the
-        // full sdk to ensure we can resolve them. If a new class gets added,
-        // the prebuilts/sdk/current needs to be updated.
-        "sdk_system_current_android",
-        // NOTE: The below can be removed once the prebuilt stub contains IKE.
-        "sdk_system_current_android.net.ipsec.ike",
     ],
     filter_packages: packages_to_document,
     high_mem: true, // Lots of sources => high memory use, see b/170701554
@@ -587,6 +551,31 @@
     visibility: ["//frameworks/base/api"],
 }
 
+// Defaults with module APIs in the classpath (mostly from prebuilts).
+// Suitable for compiling android-non-updatable.
+stubs_defaults {
+    name: "module-classpath-stubs-defaults",
+    aidl: {
+        include_dirs: [
+            "packages/modules/Connectivity/framework/aidl-export",
+            "packages/modules/Media/apex/aidl/stable",
+        ],
+    },
+    libs: [
+        "art.module.public.api",
+        "sdk_module-lib_current_framework-tethering",
+        "sdk_public_current_framework-bluetooth",
+        // There are a few classes from modules used by the core that
+        // need to be resolved by metalava. We use a prebuilt stub of the
+        // full sdk to ensure we can resolve them. If a new class gets added,
+        // the prebuilts/sdk/current needs to be updated.
+        "sdk_system_current_android",
+        // NOTE: The below can be removed once the prebuilt stub contains IKE.
+        "sdk_system_current_android.net.ipsec.ike",
+    ],
+    defaults_visibility: ["//visibility:private"],
+}
+
 build = [
     "StubLibraries.bp",
     "ApiDocs.bp",
diff --git a/Android.mk b/Android.mk
index 46529eb..d9e202c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,6 +15,14 @@
 #
 LOCAL_PATH := $(call my-dir)
 
+$(eval $(call declare-1p-copy-files,frameworks/base,.ogg))
+$(eval $(call declare-1p-copy-files,frameworks/base,.kl))
+$(eval $(call declare-1p-copy-files,frameworks/base,.kcm))
+$(eval $(call declare-1p-copy-files,frameworks/base,.idc))
+$(eval $(call declare-1p-copy-files,frameworks/base,dirty-image-objects))
+$(eval $(call declare-1p-copy-files,frameworks/base/config,))
+$(eval $(call declare-1p-copy-files,frameworks/native/data,))
+
 # Load framework-specific path mappings used later in the build.
 include $(LOCAL_PATH)/pathmap.mk
 
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 8af2e02..2efeab6 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -55,69 +55,34 @@
     "android-support-multidex-instrumentation",
 ]
 
+// These defaults enable doc-stub generation, api lint database generation and sdk value generation.
 stubs_defaults {
     name: "android-non-updatable-doc-stubs-defaults",
     defaults: ["android-non-updatable-stubs-defaults"],
     srcs: [
         // No longer part of the stubs, but are included in the docs.
-        "test-base/src/**/*.java",
-        "test-mock/src/**/*.java",
-        "test-runner/src/**/*.java",
-    ],
-    libs: framework_docs_only_libs,
-    create_doc_stubs: true,
-    write_sdk_values: true,
-}
-
-stubs_defaults {
-    name: "framework-doc-stubs-default",
-    srcs: [
-        ":android-non-updatable-stub-sources",
-
-        // Module sources
-        ":art.module.public.api{.public.stubs.source}",
-        ":conscrypt.module.public.api{.public.stubs.source}",
-        ":i18n.module.public.api{.public.stubs.source}",
-
-        // 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,
-    filter_packages: packages_to_document,
-    api_levels_annotations_enabled: true,
-    api_levels_annotations_dirs: [
-        "sdk-dir",
-        "api-versions-jars-dir",
-    ],
-    previous_api: ":android.api.public.latest",
-    merge_annotations_dirs: [
-        "metalava-manual",
-    ],
     write_sdk_values: true,
-    // TODO(b/169090544): remove below aidl includes.
-    aidl: {
-        local_include_dirs: ["media/aidl"],
-        include_dirs: [
-            "frameworks/av/aidl",
-            "frameworks/native/libs/permission/aidl",
-        ],
-    },
 }
 
 // Defaults module for doc-stubs targets that use module source code as input.
 stubs_defaults {
     name: "framework-doc-stubs-sources-default",
-    defaults: ["framework-doc-stubs-default"],
+    defaults: ["android-non-updatable-doc-stubs-defaults"],
     srcs: [
+        ":art.module.public.api{.public.stubs.source}",
+        ":conscrypt.module.public.api{.public.stubs.source}",
+        ":i18n.module.public.api{.public.stubs.source}",
+
         ":framework-appsearch-sources",
         ":framework-connectivity-sources",
+        ":framework-bluetooth-sources",
+        ":framework-connectivity-tiramisu-updatable-sources",
         ":framework-graphics-srcs",
         ":framework-mediaprovider-sources",
         ":framework-permission-sources",
@@ -134,13 +99,19 @@
 
 droidstubs {
     name: "android-non-updatable-doc-stubs",
-    defaults: ["android-non-updatable-doc-stubs-defaults"],
+    defaults: [
+        "android-non-updatable-doc-stubs-defaults",
+        "module-classpath-stubs-defaults",
+    ],
     args: metalava_framework_docs_args,
 }
 
 droidstubs {
     name: "android-non-updatable-doc-stubs-system",
-    defaults: ["android-non-updatable-doc-stubs-defaults"],
+    defaults: [
+        "android-non-updatable-doc-stubs-defaults",
+        "module-classpath-stubs-defaults",
+    ],
     args: metalava_framework_docs_args +
         " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
 }
@@ -150,74 +121,32 @@
     defaults: ["framework-doc-stubs-sources-default"],
     args: metalava_framework_docs_args +
         " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
+    ],
     api_levels_sdk_type: "system",
 }
 
 droidstubs {
     name: "framework-doc-stubs",
-    defaults: ["framework-doc-stubs-default"],
+    defaults: ["android-non-updatable-doc-stubs-defaults"],
+    srcs: [":all-modules-public-stubs-source"],
     args: metalava_framework_docs_args,
-    srcs: [
-        ":android.net.ipsec.ike{.public.stubs.source}",
-        ":framework-appsearch{.public.stubs.source}",
-        ":framework-connectivity{.public.stubs.source}",
-        ":framework-graphics{.public.stubs.source}",
-        ":framework-media{.public.stubs.source}",
-        ":framework-mediaprovider{.public.stubs.source}",
-        ":framework-permission{.public.stubs.source}",
-        ":framework-permission-s{.public.stubs.source}",
-        ":framework-scheduling{.public.stubs.source}",
-        ":framework-sdkextensions{.public.stubs.source}",
-        ":framework-statsd{.public.stubs.source}",
-        ":framework-tethering{.public.stubs.source}",
-        ":framework-wifi{.public.stubs.source}",
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
     ],
     aidl: {
-        local_include_dirs: [
-            "apex/media/aidl/stable",
-        ],
         include_dirs: [
             "packages/modules/Connectivity/framework/aidl-export",
+            "packages/modules/Media/apex/aidl/stable",
         ],
     },
 }
 
-// This produces the same annotations.zip as framework-doc-stubs, but by using
-// outputs from individual modules instead of all the source code.
-genrule {
-    name: "sdk-annotations.zip",
-    srcs: [
-        ":android-non-updatable-doc-stubs{.annotations.zip}",
-
-        // Conscrypt and i18n currently do not enable annotations
-        // ":conscrypt.module.public.api{.public.annotations.zip}",
-        // ":i18n.module.public.api{.public.annotations.zip}",
-
-        // Modules that enable annotations below
-        ":android.net.ipsec.ike{.public.annotations.zip}",
-        ":art.module.public.api{.public.annotations.zip}",
-        ":framework-appsearch{.public.annotations.zip}",
-        ":framework-connectivity{.public.annotations.zip}",
-        ":framework-graphics{.public.annotations.zip}",
-        ":framework-media{.public.annotations.zip}",
-        ":framework-mediaprovider{.public.annotations.zip}",
-        ":framework-permission{.public.annotations.zip}",
-        ":framework-permission-s{.public.annotations.zip}",
-        ":framework-scheduling{.public.annotations.zip}",
-        ":framework-sdkextensions{.public.annotations.zip}",
-        ":framework-statsd{.public.annotations.zip}",
-        ":framework-tethering{.public.annotations.zip}",
-        ":framework-wifi{.public.annotations.zip}",
-    ],
-    out: ["annotations.zip"],
-    tools: [
-        "merge_annotation_zips",
-        "soong_zip",
-    ],
-    cmd: "$(location merge_annotation_zips) $(genDir)/out $(in) && " +
-        "$(location soong_zip) -o $(out) -C $(genDir)/out -D $(genDir)/out",
-}
-
 /////////////////////////////////////////////////////////////////////
 // API docs are created from the generated stub source files
 // using droiddoc
diff --git a/INPUT_OWNERS b/INPUT_OWNERS
new file mode 100644
index 0000000..6041f637f
--- /dev/null
+++ b/INPUT_OWNERS
@@ -0,0 +1,3 @@
+michaelwr@google.com
+prabirmsp@google.com
+svv@google.com
diff --git a/METADATA b/METADATA
index 95577d8..5c3f89c 100644
--- a/METADATA
+++ b/METADATA
@@ -1,4 +1,3 @@
 third_party {
-  # would be NOTICE save for libs/usb/tests/accessorytest/f_accessory.h
-  license_type: RESTRICTED
+  license_type: RECIPROCAL
 }
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 31fecd1..39fd511 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -24,23 +24,15 @@
 // with the latest frozen API signature.
 
 /////////////////////////////////////////////////////////////////////
-// Common metalava configs
-/////////////////////////////////////////////////////////////////////
-
-stubs_defaults {
-    name: "metalava-non-updatable-api-stubs-default",
-    defaults: ["android-non-updatable-stubs-defaults"],
-    api_levels_annotations_enabled: false,
-    defaults_visibility: ["//visibility:private"],
-}
-
-/////////////////////////////////////////////////////////////////////
 // These modules provide source files for the stub libraries
 /////////////////////////////////////////////////////////////////////
 
 droidstubs {
     name: "api-stubs-docs-non-updatable",
-    defaults: ["metalava-non-updatable-api-stubs-default"],
+    defaults: [
+        "android-non-updatable-stubs-defaults",
+        "module-classpath-stubs-defaults",
+    ],
     args: metalava_framework_docs_args,
     check_api: {
         current: {
@@ -89,7 +81,10 @@
 
 droidstubs {
     name: "system-api-stubs-docs-non-updatable",
-    defaults: ["metalava-non-updatable-api-stubs-default"],
+    defaults: [
+        "android-non-updatable-stubs-defaults",
+        "module-classpath-stubs-defaults",
+    ],
     args: metalava_framework_docs_args + priv_apps,
     check_api: {
         current: {
@@ -125,7 +120,10 @@
 
 droidstubs {
     name: "test-api-stubs-docs-non-updatable",
-    defaults: ["metalava-non-updatable-api-stubs-default"],
+    defaults: [
+        "android-non-updatable-stubs-defaults",
+        "module-classpath-stubs-defaults",
+    ],
     args: metalava_framework_docs_args + test + priv_apps_in_stubs,
     check_api: {
         current: {
@@ -167,7 +165,10 @@
 
 droidstubs {
     name: "module-lib-api-stubs-docs-non-updatable",
-    defaults: ["metalava-non-updatable-api-stubs-default"],
+    defaults: [
+        "android-non-updatable-stubs-defaults",
+        "module-classpath-stubs-defaults",
+    ],
     args: metalava_framework_docs_args + priv_apps_in_stubs + module_libs,
     check_api: {
         current: {
@@ -177,6 +178,7 @@
         last_released: {
             api_file: ":android-non-updatable.api.module-lib.latest",
             removed_api_file: ":android-non-updatable-removed.api.module-lib.latest",
+            baseline_file: ":android-non-updatable-incompatibilities.api.module-lib.latest",
         },
         api_lint: {
             enabled: true,
@@ -205,44 +207,6 @@
 // from stub sources
 /////////////////////////////////////////////////////////////////////
 
-modules_public_stubs = [
-    "android.net.ipsec.ike.stubs",
-    "art.module.public.api.stubs",
-    "conscrypt.module.public.api.stubs",
-    "framework-appsearch.stubs",
-    "framework-connectivity.stubs",
-    "framework-graphics.stubs",
-    "framework-media.stubs",
-    "framework-mediaprovider.stubs",
-    "framework-permission.stubs",
-    "framework-permission-s.stubs",
-    "framework-scheduling.stubs",
-    "framework-sdkextensions.stubs",
-    "framework-statsd.stubs",
-    "framework-tethering.stubs",
-    "framework-wifi.stubs",
-    "i18n.module.public.api.stubs",
-]
-
-modules_system_stubs = [
-    "android.net.ipsec.ike.stubs.system",
-    "art.module.public.api.stubs.system",
-    "conscrypt.module.public.api.stubs", // Only has public stubs
-    "framework-appsearch.stubs.system",
-    "framework-connectivity.stubs.system",
-    "framework-graphics.stubs.system",
-    "framework-media.stubs.system",
-    "framework-mediaprovider.stubs.system",
-    "framework-permission.stubs.system",
-    "framework-permission-s.stubs.system",
-    "framework-scheduling.stubs.system",
-    "framework-sdkextensions.stubs.system",
-    "framework-statsd.stubs.system",
-    "framework-tethering.stubs.system",
-    "framework-wifi.stubs.system",
-    "i18n.module.public.api.stubs", // Only has public stubs
-]
-
 java_defaults {
     name: "android-non-updatable_defaults_stubs_current",
     libs: ["stub-annotations"],
@@ -264,7 +228,7 @@
     name: "android-non-updatable.stubs",
     defaults: ["android-non-updatable_defaults_stubs_current"],
     srcs: [":api-stubs-docs-non-updatable"],
-    libs: modules_public_stubs,
+    libs: ["all-modules-public-stubs"],
     dist: {
         dir: "apistubs/android/public",
     },
@@ -274,7 +238,7 @@
     name: "android-non-updatable.stubs.system",
     defaults: ["android-non-updatable_defaults_stubs_current"],
     srcs: [":system-api-stubs-docs-non-updatable"],
-    libs: modules_system_stubs,
+    libs: ["all-modules-system-stubs"],
     dist: {
         dir: "apistubs/android/system",
     },
@@ -286,6 +250,8 @@
     srcs: [":module-lib-api-stubs-docs-non-updatable"],
     libs: [
         "sdk_module-lib_current_framework-tethering",
+        "sdk_public_current_framework-bluetooth",
+        // NOTE: The below can be removed once the prebuilt stub contains bluetooth.
         "sdk_system_current_android",
         // NOTE: The below can be removed once the prebuilt stub contains IKE.
         "sdk_system_current_android.net.ipsec.ike",
@@ -299,7 +265,7 @@
     name: "android-non-updatable.stubs.test",
     defaults: ["android-non-updatable_defaults_stubs_current"],
     srcs: [":test-api-stubs-docs-non-updatable"],
-    libs: modules_system_stubs,
+    libs: ["all-modules-system-stubs"],
     dist: {
         dir: "apistubs/android/test",
     },
@@ -317,7 +283,8 @@
 
 java_library {
     name: "android_stubs_current",
-    static_libs: modules_public_stubs + [
+    static_libs: [
+        "all-modules-public-stubs",
         "android-non-updatable.stubs",
         "private-stub-annotations-jar",
     ],
@@ -326,7 +293,8 @@
 
 java_library {
     name: "android_system_stubs_current",
-    static_libs: modules_system_stubs + [
+    static_libs: [
+        "all-modules-system-stubs",
         "android-non-updatable.stubs.system",
         "private-stub-annotations-jar",
     ],
@@ -351,7 +319,8 @@
     name: "android_test_stubs_current",
     // Modules do not have test APIs, but we want to include their SystemApis, like we include
     // the SystemApi of framework-non-updatable-sources.
-    static_libs: modules_system_stubs + [
+    static_libs: [
+        "all-modules-system-stubs",
         "android-non-updatable.stubs.test",
         "private-stub-annotations-jar",
     ],
@@ -396,6 +365,64 @@
     },
 }
 
+////////////////////////////////////////////////////////////////////////
+// api-versions.xml generation, for public and system. This API database
+// also contains the android.test.* APIs.
+////////////////////////////////////////////////////////////////////////
+
+java_library {
+    name: "android_stubs_current_with_test_libs",
+    static_libs: [
+        "android_stubs_current",
+        "android.test.base.stubs",
+        "android.test.mock.stubs",
+        "android.test.runner.stubs",
+    ],
+    defaults: ["android.jar_defaults"],
+    visibility: [
+        "//visibility:override",
+        "//visibility:private",
+    ],
+}
+
+java_library {
+    name: "android_system_stubs_current_with_test_libs",
+    static_libs: [
+        "android_system_stubs_current",
+        "android.test.base.stubs.system",
+        "android.test.mock.stubs.system",
+        "android.test.runner.stubs.system",
+    ],
+    defaults: ["android.jar_defaults"],
+    visibility: [
+        "//visibility:override",
+        "//visibility:private",
+    ],
+}
+
+droidstubs {
+    name: "api_versions_public",
+    srcs: [":android_stubs_current_with_test_libs{.jar}"],
+    generate_stubs: false,
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
+    ],
+}
+
+droidstubs {
+    name: "api_versions_system",
+    srcs: [":android_system_stubs_current_with_test_libs{.jar}"],
+    generate_stubs: false,
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
+    ],
+    api_levels_sdk_type: "system",
+}
+
 /////////////////////////////////////////////////////////////////////
 // hwbinder.stubs provides APIs required for building HIDL Java
 // libraries.
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 18486af..2b3564e 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -1 +1,5 @@
 include /graphics/java/android/graphics/fonts/OWNERS
+
+# Bug component: 568761
+per-file /apct-tests/perftests/core/res/* = felkachang@google.com,zyy@google.com
+
diff --git a/apct-tests/perftests/core/res/values/colors.xml b/apct-tests/perftests/core/res/values/colors.xml
new file mode 100644
index 0000000..5e56c25
--- /dev/null
+++ b/apct-tests/perftests/core/res/values/colors.xml
@@ -0,0 +1,10022 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<resources>
+    <!--- The colors with prefix "i_am_color_%x" and %x is from 0 to 10000. They are used by
+          ResourcesPerfTest.java -->
+    <color name="i_am_color_0">#00000000</color>
+    <color name="i_am_color_1">#00000001</color>
+    <color name="i_am_color_2">#00000002</color>
+    <color name="i_am_color_3">#00000003</color>
+    <color name="i_am_color_4">#00000004</color>
+    <color name="i_am_color_5">#00000005</color>
+    <color name="i_am_color_6">#00000006</color>
+    <color name="i_am_color_7">#00000007</color>
+    <color name="i_am_color_8">#00000008</color>
+    <color name="i_am_color_9">#00000009</color>
+    <color name="i_am_color_a">#0000000a</color>
+    <color name="i_am_color_b">#0000000b</color>
+    <color name="i_am_color_c">#0000000c</color>
+    <color name="i_am_color_d">#0000000d</color>
+    <color name="i_am_color_e">#0000000e</color>
+    <color name="i_am_color_f">#0000000f</color>
+    <color name="i_am_color_10">#00000010</color>
+    <color name="i_am_color_11">#00000011</color>
+    <color name="i_am_color_12">#00000012</color>
+    <color name="i_am_color_13">#00000013</color>
+    <color name="i_am_color_14">#00000014</color>
+    <color name="i_am_color_15">#00000015</color>
+    <color name="i_am_color_16">#00000016</color>
+    <color name="i_am_color_17">#00000017</color>
+    <color name="i_am_color_18">#00000018</color>
+    <color name="i_am_color_19">#00000019</color>
+    <color name="i_am_color_1a">#0000001a</color>
+    <color name="i_am_color_1b">#0000001b</color>
+    <color name="i_am_color_1c">#0000001c</color>
+    <color name="i_am_color_1d">#0000001d</color>
+    <color name="i_am_color_1e">#0000001e</color>
+    <color name="i_am_color_1f">#0000001f</color>
+    <color name="i_am_color_20">#00000020</color>
+    <color name="i_am_color_21">#00000021</color>
+    <color name="i_am_color_22">#00000022</color>
+    <color name="i_am_color_23">#00000023</color>
+    <color name="i_am_color_24">#00000024</color>
+    <color name="i_am_color_25">#00000025</color>
+    <color name="i_am_color_26">#00000026</color>
+    <color name="i_am_color_27">#00000027</color>
+    <color name="i_am_color_28">#00000028</color>
+    <color name="i_am_color_29">#00000029</color>
+    <color name="i_am_color_2a">#0000002a</color>
+    <color name="i_am_color_2b">#0000002b</color>
+    <color name="i_am_color_2c">#0000002c</color>
+    <color name="i_am_color_2d">#0000002d</color>
+    <color name="i_am_color_2e">#0000002e</color>
+    <color name="i_am_color_2f">#0000002f</color>
+    <color name="i_am_color_30">#00000030</color>
+    <color name="i_am_color_31">#00000031</color>
+    <color name="i_am_color_32">#00000032</color>
+    <color name="i_am_color_33">#00000033</color>
+    <color name="i_am_color_34">#00000034</color>
+    <color name="i_am_color_35">#00000035</color>
+    <color name="i_am_color_36">#00000036</color>
+    <color name="i_am_color_37">#00000037</color>
+    <color name="i_am_color_38">#00000038</color>
+    <color name="i_am_color_39">#00000039</color>
+    <color name="i_am_color_3a">#0000003a</color>
+    <color name="i_am_color_3b">#0000003b</color>
+    <color name="i_am_color_3c">#0000003c</color>
+    <color name="i_am_color_3d">#0000003d</color>
+    <color name="i_am_color_3e">#0000003e</color>
+    <color name="i_am_color_3f">#0000003f</color>
+    <color name="i_am_color_40">#00000040</color>
+    <color name="i_am_color_41">#00000041</color>
+    <color name="i_am_color_42">#00000042</color>
+    <color name="i_am_color_43">#00000043</color>
+    <color name="i_am_color_44">#00000044</color>
+    <color name="i_am_color_45">#00000045</color>
+    <color name="i_am_color_46">#00000046</color>
+    <color name="i_am_color_47">#00000047</color>
+    <color name="i_am_color_48">#00000048</color>
+    <color name="i_am_color_49">#00000049</color>
+    <color name="i_am_color_4a">#0000004a</color>
+    <color name="i_am_color_4b">#0000004b</color>
+    <color name="i_am_color_4c">#0000004c</color>
+    <color name="i_am_color_4d">#0000004d</color>
+    <color name="i_am_color_4e">#0000004e</color>
+    <color name="i_am_color_4f">#0000004f</color>
+    <color name="i_am_color_50">#00000050</color>
+    <color name="i_am_color_51">#00000051</color>
+    <color name="i_am_color_52">#00000052</color>
+    <color name="i_am_color_53">#00000053</color>
+    <color name="i_am_color_54">#00000054</color>
+    <color name="i_am_color_55">#00000055</color>
+    <color name="i_am_color_56">#00000056</color>
+    <color name="i_am_color_57">#00000057</color>
+    <color name="i_am_color_58">#00000058</color>
+    <color name="i_am_color_59">#00000059</color>
+    <color name="i_am_color_5a">#0000005a</color>
+    <color name="i_am_color_5b">#0000005b</color>
+    <color name="i_am_color_5c">#0000005c</color>
+    <color name="i_am_color_5d">#0000005d</color>
+    <color name="i_am_color_5e">#0000005e</color>
+    <color name="i_am_color_5f">#0000005f</color>
+    <color name="i_am_color_60">#00000060</color>
+    <color name="i_am_color_61">#00000061</color>
+    <color name="i_am_color_62">#00000062</color>
+    <color name="i_am_color_63">#00000063</color>
+    <color name="i_am_color_64">#00000064</color>
+    <color name="i_am_color_65">#00000065</color>
+    <color name="i_am_color_66">#00000066</color>
+    <color name="i_am_color_67">#00000067</color>
+    <color name="i_am_color_68">#00000068</color>
+    <color name="i_am_color_69">#00000069</color>
+    <color name="i_am_color_6a">#0000006a</color>
+    <color name="i_am_color_6b">#0000006b</color>
+    <color name="i_am_color_6c">#0000006c</color>
+    <color name="i_am_color_6d">#0000006d</color>
+    <color name="i_am_color_6e">#0000006e</color>
+    <color name="i_am_color_6f">#0000006f</color>
+    <color name="i_am_color_70">#00000070</color>
+    <color name="i_am_color_71">#00000071</color>
+    <color name="i_am_color_72">#00000072</color>
+    <color name="i_am_color_73">#00000073</color>
+    <color name="i_am_color_74">#00000074</color>
+    <color name="i_am_color_75">#00000075</color>
+    <color name="i_am_color_76">#00000076</color>
+    <color name="i_am_color_77">#00000077</color>
+    <color name="i_am_color_78">#00000078</color>
+    <color name="i_am_color_79">#00000079</color>
+    <color name="i_am_color_7a">#0000007a</color>
+    <color name="i_am_color_7b">#0000007b</color>
+    <color name="i_am_color_7c">#0000007c</color>
+    <color name="i_am_color_7d">#0000007d</color>
+    <color name="i_am_color_7e">#0000007e</color>
+    <color name="i_am_color_7f">#0000007f</color>
+    <color name="i_am_color_80">#00000080</color>
+    <color name="i_am_color_81">#00000081</color>
+    <color name="i_am_color_82">#00000082</color>
+    <color name="i_am_color_83">#00000083</color>
+    <color name="i_am_color_84">#00000084</color>
+    <color name="i_am_color_85">#00000085</color>
+    <color name="i_am_color_86">#00000086</color>
+    <color name="i_am_color_87">#00000087</color>
+    <color name="i_am_color_88">#00000088</color>
+    <color name="i_am_color_89">#00000089</color>
+    <color name="i_am_color_8a">#0000008a</color>
+    <color name="i_am_color_8b">#0000008b</color>
+    <color name="i_am_color_8c">#0000008c</color>
+    <color name="i_am_color_8d">#0000008d</color>
+    <color name="i_am_color_8e">#0000008e</color>
+    <color name="i_am_color_8f">#0000008f</color>
+    <color name="i_am_color_90">#00000090</color>
+    <color name="i_am_color_91">#00000091</color>
+    <color name="i_am_color_92">#00000092</color>
+    <color name="i_am_color_93">#00000093</color>
+    <color name="i_am_color_94">#00000094</color>
+    <color name="i_am_color_95">#00000095</color>
+    <color name="i_am_color_96">#00000096</color>
+    <color name="i_am_color_97">#00000097</color>
+    <color name="i_am_color_98">#00000098</color>
+    <color name="i_am_color_99">#00000099</color>
+    <color name="i_am_color_9a">#0000009a</color>
+    <color name="i_am_color_9b">#0000009b</color>
+    <color name="i_am_color_9c">#0000009c</color>
+    <color name="i_am_color_9d">#0000009d</color>
+    <color name="i_am_color_9e">#0000009e</color>
+    <color name="i_am_color_9f">#0000009f</color>
+    <color name="i_am_color_a0">#000000a0</color>
+    <color name="i_am_color_a1">#000000a1</color>
+    <color name="i_am_color_a2">#000000a2</color>
+    <color name="i_am_color_a3">#000000a3</color>
+    <color name="i_am_color_a4">#000000a4</color>
+    <color name="i_am_color_a5">#000000a5</color>
+    <color name="i_am_color_a6">#000000a6</color>
+    <color name="i_am_color_a7">#000000a7</color>
+    <color name="i_am_color_a8">#000000a8</color>
+    <color name="i_am_color_a9">#000000a9</color>
+    <color name="i_am_color_aa">#000000aa</color>
+    <color name="i_am_color_ab">#000000ab</color>
+    <color name="i_am_color_ac">#000000ac</color>
+    <color name="i_am_color_ad">#000000ad</color>
+    <color name="i_am_color_ae">#000000ae</color>
+    <color name="i_am_color_af">#000000af</color>
+    <color name="i_am_color_b0">#000000b0</color>
+    <color name="i_am_color_b1">#000000b1</color>
+    <color name="i_am_color_b2">#000000b2</color>
+    <color name="i_am_color_b3">#000000b3</color>
+    <color name="i_am_color_b4">#000000b4</color>
+    <color name="i_am_color_b5">#000000b5</color>
+    <color name="i_am_color_b6">#000000b6</color>
+    <color name="i_am_color_b7">#000000b7</color>
+    <color name="i_am_color_b8">#000000b8</color>
+    <color name="i_am_color_b9">#000000b9</color>
+    <color name="i_am_color_ba">#000000ba</color>
+    <color name="i_am_color_bb">#000000bb</color>
+    <color name="i_am_color_bc">#000000bc</color>
+    <color name="i_am_color_bd">#000000bd</color>
+    <color name="i_am_color_be">#000000be</color>
+    <color name="i_am_color_bf">#000000bf</color>
+    <color name="i_am_color_c0">#000000c0</color>
+    <color name="i_am_color_c1">#000000c1</color>
+    <color name="i_am_color_c2">#000000c2</color>
+    <color name="i_am_color_c3">#000000c3</color>
+    <color name="i_am_color_c4">#000000c4</color>
+    <color name="i_am_color_c5">#000000c5</color>
+    <color name="i_am_color_c6">#000000c6</color>
+    <color name="i_am_color_c7">#000000c7</color>
+    <color name="i_am_color_c8">#000000c8</color>
+    <color name="i_am_color_c9">#000000c9</color>
+    <color name="i_am_color_ca">#000000ca</color>
+    <color name="i_am_color_cb">#000000cb</color>
+    <color name="i_am_color_cc">#000000cc</color>
+    <color name="i_am_color_cd">#000000cd</color>
+    <color name="i_am_color_ce">#000000ce</color>
+    <color name="i_am_color_cf">#000000cf</color>
+    <color name="i_am_color_d0">#000000d0</color>
+    <color name="i_am_color_d1">#000000d1</color>
+    <color name="i_am_color_d2">#000000d2</color>
+    <color name="i_am_color_d3">#000000d3</color>
+    <color name="i_am_color_d4">#000000d4</color>
+    <color name="i_am_color_d5">#000000d5</color>
+    <color name="i_am_color_d6">#000000d6</color>
+    <color name="i_am_color_d7">#000000d7</color>
+    <color name="i_am_color_d8">#000000d8</color>
+    <color name="i_am_color_d9">#000000d9</color>
+    <color name="i_am_color_da">#000000da</color>
+    <color name="i_am_color_db">#000000db</color>
+    <color name="i_am_color_dc">#000000dc</color>
+    <color name="i_am_color_dd">#000000dd</color>
+    <color name="i_am_color_de">#000000de</color>
+    <color name="i_am_color_df">#000000df</color>
+    <color name="i_am_color_e0">#000000e0</color>
+    <color name="i_am_color_e1">#000000e1</color>
+    <color name="i_am_color_e2">#000000e2</color>
+    <color name="i_am_color_e3">#000000e3</color>
+    <color name="i_am_color_e4">#000000e4</color>
+    <color name="i_am_color_e5">#000000e5</color>
+    <color name="i_am_color_e6">#000000e6</color>
+    <color name="i_am_color_e7">#000000e7</color>
+    <color name="i_am_color_e8">#000000e8</color>
+    <color name="i_am_color_e9">#000000e9</color>
+    <color name="i_am_color_ea">#000000ea</color>
+    <color name="i_am_color_eb">#000000eb</color>
+    <color name="i_am_color_ec">#000000ec</color>
+    <color name="i_am_color_ed">#000000ed</color>
+    <color name="i_am_color_ee">#000000ee</color>
+    <color name="i_am_color_ef">#000000ef</color>
+    <color name="i_am_color_f0">#000000f0</color>
+    <color name="i_am_color_f1">#000000f1</color>
+    <color name="i_am_color_f2">#000000f2</color>
+    <color name="i_am_color_f3">#000000f3</color>
+    <color name="i_am_color_f4">#000000f4</color>
+    <color name="i_am_color_f5">#000000f5</color>
+    <color name="i_am_color_f6">#000000f6</color>
+    <color name="i_am_color_f7">#000000f7</color>
+    <color name="i_am_color_f8">#000000f8</color>
+    <color name="i_am_color_f9">#000000f9</color>
+    <color name="i_am_color_fa">#000000fa</color>
+    <color name="i_am_color_fb">#000000fb</color>
+    <color name="i_am_color_fc">#000000fc</color>
+    <color name="i_am_color_fd">#000000fd</color>
+    <color name="i_am_color_fe">#000000fe</color>
+    <color name="i_am_color_ff">#000000ff</color>
+    <color name="i_am_color_100">#00000100</color>
+    <color name="i_am_color_101">#00000101</color>
+    <color name="i_am_color_102">#00000102</color>
+    <color name="i_am_color_103">#00000103</color>
+    <color name="i_am_color_104">#00000104</color>
+    <color name="i_am_color_105">#00000105</color>
+    <color name="i_am_color_106">#00000106</color>
+    <color name="i_am_color_107">#00000107</color>
+    <color name="i_am_color_108">#00000108</color>
+    <color name="i_am_color_109">#00000109</color>
+    <color name="i_am_color_10a">#0000010a</color>
+    <color name="i_am_color_10b">#0000010b</color>
+    <color name="i_am_color_10c">#0000010c</color>
+    <color name="i_am_color_10d">#0000010d</color>
+    <color name="i_am_color_10e">#0000010e</color>
+    <color name="i_am_color_10f">#0000010f</color>
+    <color name="i_am_color_110">#00000110</color>
+    <color name="i_am_color_111">#00000111</color>
+    <color name="i_am_color_112">#00000112</color>
+    <color name="i_am_color_113">#00000113</color>
+    <color name="i_am_color_114">#00000114</color>
+    <color name="i_am_color_115">#00000115</color>
+    <color name="i_am_color_116">#00000116</color>
+    <color name="i_am_color_117">#00000117</color>
+    <color name="i_am_color_118">#00000118</color>
+    <color name="i_am_color_119">#00000119</color>
+    <color name="i_am_color_11a">#0000011a</color>
+    <color name="i_am_color_11b">#0000011b</color>
+    <color name="i_am_color_11c">#0000011c</color>
+    <color name="i_am_color_11d">#0000011d</color>
+    <color name="i_am_color_11e">#0000011e</color>
+    <color name="i_am_color_11f">#0000011f</color>
+    <color name="i_am_color_120">#00000120</color>
+    <color name="i_am_color_121">#00000121</color>
+    <color name="i_am_color_122">#00000122</color>
+    <color name="i_am_color_123">#00000123</color>
+    <color name="i_am_color_124">#00000124</color>
+    <color name="i_am_color_125">#00000125</color>
+    <color name="i_am_color_126">#00000126</color>
+    <color name="i_am_color_127">#00000127</color>
+    <color name="i_am_color_128">#00000128</color>
+    <color name="i_am_color_129">#00000129</color>
+    <color name="i_am_color_12a">#0000012a</color>
+    <color name="i_am_color_12b">#0000012b</color>
+    <color name="i_am_color_12c">#0000012c</color>
+    <color name="i_am_color_12d">#0000012d</color>
+    <color name="i_am_color_12e">#0000012e</color>
+    <color name="i_am_color_12f">#0000012f</color>
+    <color name="i_am_color_130">#00000130</color>
+    <color name="i_am_color_131">#00000131</color>
+    <color name="i_am_color_132">#00000132</color>
+    <color name="i_am_color_133">#00000133</color>
+    <color name="i_am_color_134">#00000134</color>
+    <color name="i_am_color_135">#00000135</color>
+    <color name="i_am_color_136">#00000136</color>
+    <color name="i_am_color_137">#00000137</color>
+    <color name="i_am_color_138">#00000138</color>
+    <color name="i_am_color_139">#00000139</color>
+    <color name="i_am_color_13a">#0000013a</color>
+    <color name="i_am_color_13b">#0000013b</color>
+    <color name="i_am_color_13c">#0000013c</color>
+    <color name="i_am_color_13d">#0000013d</color>
+    <color name="i_am_color_13e">#0000013e</color>
+    <color name="i_am_color_13f">#0000013f</color>
+    <color name="i_am_color_140">#00000140</color>
+    <color name="i_am_color_141">#00000141</color>
+    <color name="i_am_color_142">#00000142</color>
+    <color name="i_am_color_143">#00000143</color>
+    <color name="i_am_color_144">#00000144</color>
+    <color name="i_am_color_145">#00000145</color>
+    <color name="i_am_color_146">#00000146</color>
+    <color name="i_am_color_147">#00000147</color>
+    <color name="i_am_color_148">#00000148</color>
+    <color name="i_am_color_149">#00000149</color>
+    <color name="i_am_color_14a">#0000014a</color>
+    <color name="i_am_color_14b">#0000014b</color>
+    <color name="i_am_color_14c">#0000014c</color>
+    <color name="i_am_color_14d">#0000014d</color>
+    <color name="i_am_color_14e">#0000014e</color>
+    <color name="i_am_color_14f">#0000014f</color>
+    <color name="i_am_color_150">#00000150</color>
+    <color name="i_am_color_151">#00000151</color>
+    <color name="i_am_color_152">#00000152</color>
+    <color name="i_am_color_153">#00000153</color>
+    <color name="i_am_color_154">#00000154</color>
+    <color name="i_am_color_155">#00000155</color>
+    <color name="i_am_color_156">#00000156</color>
+    <color name="i_am_color_157">#00000157</color>
+    <color name="i_am_color_158">#00000158</color>
+    <color name="i_am_color_159">#00000159</color>
+    <color name="i_am_color_15a">#0000015a</color>
+    <color name="i_am_color_15b">#0000015b</color>
+    <color name="i_am_color_15c">#0000015c</color>
+    <color name="i_am_color_15d">#0000015d</color>
+    <color name="i_am_color_15e">#0000015e</color>
+    <color name="i_am_color_15f">#0000015f</color>
+    <color name="i_am_color_160">#00000160</color>
+    <color name="i_am_color_161">#00000161</color>
+    <color name="i_am_color_162">#00000162</color>
+    <color name="i_am_color_163">#00000163</color>
+    <color name="i_am_color_164">#00000164</color>
+    <color name="i_am_color_165">#00000165</color>
+    <color name="i_am_color_166">#00000166</color>
+    <color name="i_am_color_167">#00000167</color>
+    <color name="i_am_color_168">#00000168</color>
+    <color name="i_am_color_169">#00000169</color>
+    <color name="i_am_color_16a">#0000016a</color>
+    <color name="i_am_color_16b">#0000016b</color>
+    <color name="i_am_color_16c">#0000016c</color>
+    <color name="i_am_color_16d">#0000016d</color>
+    <color name="i_am_color_16e">#0000016e</color>
+    <color name="i_am_color_16f">#0000016f</color>
+    <color name="i_am_color_170">#00000170</color>
+    <color name="i_am_color_171">#00000171</color>
+    <color name="i_am_color_172">#00000172</color>
+    <color name="i_am_color_173">#00000173</color>
+    <color name="i_am_color_174">#00000174</color>
+    <color name="i_am_color_175">#00000175</color>
+    <color name="i_am_color_176">#00000176</color>
+    <color name="i_am_color_177">#00000177</color>
+    <color name="i_am_color_178">#00000178</color>
+    <color name="i_am_color_179">#00000179</color>
+    <color name="i_am_color_17a">#0000017a</color>
+    <color name="i_am_color_17b">#0000017b</color>
+    <color name="i_am_color_17c">#0000017c</color>
+    <color name="i_am_color_17d">#0000017d</color>
+    <color name="i_am_color_17e">#0000017e</color>
+    <color name="i_am_color_17f">#0000017f</color>
+    <color name="i_am_color_180">#00000180</color>
+    <color name="i_am_color_181">#00000181</color>
+    <color name="i_am_color_182">#00000182</color>
+    <color name="i_am_color_183">#00000183</color>
+    <color name="i_am_color_184">#00000184</color>
+    <color name="i_am_color_185">#00000185</color>
+    <color name="i_am_color_186">#00000186</color>
+    <color name="i_am_color_187">#00000187</color>
+    <color name="i_am_color_188">#00000188</color>
+    <color name="i_am_color_189">#00000189</color>
+    <color name="i_am_color_18a">#0000018a</color>
+    <color name="i_am_color_18b">#0000018b</color>
+    <color name="i_am_color_18c">#0000018c</color>
+    <color name="i_am_color_18d">#0000018d</color>
+    <color name="i_am_color_18e">#0000018e</color>
+    <color name="i_am_color_18f">#0000018f</color>
+    <color name="i_am_color_190">#00000190</color>
+    <color name="i_am_color_191">#00000191</color>
+    <color name="i_am_color_192">#00000192</color>
+    <color name="i_am_color_193">#00000193</color>
+    <color name="i_am_color_194">#00000194</color>
+    <color name="i_am_color_195">#00000195</color>
+    <color name="i_am_color_196">#00000196</color>
+    <color name="i_am_color_197">#00000197</color>
+    <color name="i_am_color_198">#00000198</color>
+    <color name="i_am_color_199">#00000199</color>
+    <color name="i_am_color_19a">#0000019a</color>
+    <color name="i_am_color_19b">#0000019b</color>
+    <color name="i_am_color_19c">#0000019c</color>
+    <color name="i_am_color_19d">#0000019d</color>
+    <color name="i_am_color_19e">#0000019e</color>
+    <color name="i_am_color_19f">#0000019f</color>
+    <color name="i_am_color_1a0">#000001a0</color>
+    <color name="i_am_color_1a1">#000001a1</color>
+    <color name="i_am_color_1a2">#000001a2</color>
+    <color name="i_am_color_1a3">#000001a3</color>
+    <color name="i_am_color_1a4">#000001a4</color>
+    <color name="i_am_color_1a5">#000001a5</color>
+    <color name="i_am_color_1a6">#000001a6</color>
+    <color name="i_am_color_1a7">#000001a7</color>
+    <color name="i_am_color_1a8">#000001a8</color>
+    <color name="i_am_color_1a9">#000001a9</color>
+    <color name="i_am_color_1aa">#000001aa</color>
+    <color name="i_am_color_1ab">#000001ab</color>
+    <color name="i_am_color_1ac">#000001ac</color>
+    <color name="i_am_color_1ad">#000001ad</color>
+    <color name="i_am_color_1ae">#000001ae</color>
+    <color name="i_am_color_1af">#000001af</color>
+    <color name="i_am_color_1b0">#000001b0</color>
+    <color name="i_am_color_1b1">#000001b1</color>
+    <color name="i_am_color_1b2">#000001b2</color>
+    <color name="i_am_color_1b3">#000001b3</color>
+    <color name="i_am_color_1b4">#000001b4</color>
+    <color name="i_am_color_1b5">#000001b5</color>
+    <color name="i_am_color_1b6">#000001b6</color>
+    <color name="i_am_color_1b7">#000001b7</color>
+    <color name="i_am_color_1b8">#000001b8</color>
+    <color name="i_am_color_1b9">#000001b9</color>
+    <color name="i_am_color_1ba">#000001ba</color>
+    <color name="i_am_color_1bb">#000001bb</color>
+    <color name="i_am_color_1bc">#000001bc</color>
+    <color name="i_am_color_1bd">#000001bd</color>
+    <color name="i_am_color_1be">#000001be</color>
+    <color name="i_am_color_1bf">#000001bf</color>
+    <color name="i_am_color_1c0">#000001c0</color>
+    <color name="i_am_color_1c1">#000001c1</color>
+    <color name="i_am_color_1c2">#000001c2</color>
+    <color name="i_am_color_1c3">#000001c3</color>
+    <color name="i_am_color_1c4">#000001c4</color>
+    <color name="i_am_color_1c5">#000001c5</color>
+    <color name="i_am_color_1c6">#000001c6</color>
+    <color name="i_am_color_1c7">#000001c7</color>
+    <color name="i_am_color_1c8">#000001c8</color>
+    <color name="i_am_color_1c9">#000001c9</color>
+    <color name="i_am_color_1ca">#000001ca</color>
+    <color name="i_am_color_1cb">#000001cb</color>
+    <color name="i_am_color_1cc">#000001cc</color>
+    <color name="i_am_color_1cd">#000001cd</color>
+    <color name="i_am_color_1ce">#000001ce</color>
+    <color name="i_am_color_1cf">#000001cf</color>
+    <color name="i_am_color_1d0">#000001d0</color>
+    <color name="i_am_color_1d1">#000001d1</color>
+    <color name="i_am_color_1d2">#000001d2</color>
+    <color name="i_am_color_1d3">#000001d3</color>
+    <color name="i_am_color_1d4">#000001d4</color>
+    <color name="i_am_color_1d5">#000001d5</color>
+    <color name="i_am_color_1d6">#000001d6</color>
+    <color name="i_am_color_1d7">#000001d7</color>
+    <color name="i_am_color_1d8">#000001d8</color>
+    <color name="i_am_color_1d9">#000001d9</color>
+    <color name="i_am_color_1da">#000001da</color>
+    <color name="i_am_color_1db">#000001db</color>
+    <color name="i_am_color_1dc">#000001dc</color>
+    <color name="i_am_color_1dd">#000001dd</color>
+    <color name="i_am_color_1de">#000001de</color>
+    <color name="i_am_color_1df">#000001df</color>
+    <color name="i_am_color_1e0">#000001e0</color>
+    <color name="i_am_color_1e1">#000001e1</color>
+    <color name="i_am_color_1e2">#000001e2</color>
+    <color name="i_am_color_1e3">#000001e3</color>
+    <color name="i_am_color_1e4">#000001e4</color>
+    <color name="i_am_color_1e5">#000001e5</color>
+    <color name="i_am_color_1e6">#000001e6</color>
+    <color name="i_am_color_1e7">#000001e7</color>
+    <color name="i_am_color_1e8">#000001e8</color>
+    <color name="i_am_color_1e9">#000001e9</color>
+    <color name="i_am_color_1ea">#000001ea</color>
+    <color name="i_am_color_1eb">#000001eb</color>
+    <color name="i_am_color_1ec">#000001ec</color>
+    <color name="i_am_color_1ed">#000001ed</color>
+    <color name="i_am_color_1ee">#000001ee</color>
+    <color name="i_am_color_1ef">#000001ef</color>
+    <color name="i_am_color_1f0">#000001f0</color>
+    <color name="i_am_color_1f1">#000001f1</color>
+    <color name="i_am_color_1f2">#000001f2</color>
+    <color name="i_am_color_1f3">#000001f3</color>
+    <color name="i_am_color_1f4">#000001f4</color>
+    <color name="i_am_color_1f5">#000001f5</color>
+    <color name="i_am_color_1f6">#000001f6</color>
+    <color name="i_am_color_1f7">#000001f7</color>
+    <color name="i_am_color_1f8">#000001f8</color>
+    <color name="i_am_color_1f9">#000001f9</color>
+    <color name="i_am_color_1fa">#000001fa</color>
+    <color name="i_am_color_1fb">#000001fb</color>
+    <color name="i_am_color_1fc">#000001fc</color>
+    <color name="i_am_color_1fd">#000001fd</color>
+    <color name="i_am_color_1fe">#000001fe</color>
+    <color name="i_am_color_1ff">#000001ff</color>
+    <color name="i_am_color_200">#00000200</color>
+    <color name="i_am_color_201">#00000201</color>
+    <color name="i_am_color_202">#00000202</color>
+    <color name="i_am_color_203">#00000203</color>
+    <color name="i_am_color_204">#00000204</color>
+    <color name="i_am_color_205">#00000205</color>
+    <color name="i_am_color_206">#00000206</color>
+    <color name="i_am_color_207">#00000207</color>
+    <color name="i_am_color_208">#00000208</color>
+    <color name="i_am_color_209">#00000209</color>
+    <color name="i_am_color_20a">#0000020a</color>
+    <color name="i_am_color_20b">#0000020b</color>
+    <color name="i_am_color_20c">#0000020c</color>
+    <color name="i_am_color_20d">#0000020d</color>
+    <color name="i_am_color_20e">#0000020e</color>
+    <color name="i_am_color_20f">#0000020f</color>
+    <color name="i_am_color_210">#00000210</color>
+    <color name="i_am_color_211">#00000211</color>
+    <color name="i_am_color_212">#00000212</color>
+    <color name="i_am_color_213">#00000213</color>
+    <color name="i_am_color_214">#00000214</color>
+    <color name="i_am_color_215">#00000215</color>
+    <color name="i_am_color_216">#00000216</color>
+    <color name="i_am_color_217">#00000217</color>
+    <color name="i_am_color_218">#00000218</color>
+    <color name="i_am_color_219">#00000219</color>
+    <color name="i_am_color_21a">#0000021a</color>
+    <color name="i_am_color_21b">#0000021b</color>
+    <color name="i_am_color_21c">#0000021c</color>
+    <color name="i_am_color_21d">#0000021d</color>
+    <color name="i_am_color_21e">#0000021e</color>
+    <color name="i_am_color_21f">#0000021f</color>
+    <color name="i_am_color_220">#00000220</color>
+    <color name="i_am_color_221">#00000221</color>
+    <color name="i_am_color_222">#00000222</color>
+    <color name="i_am_color_223">#00000223</color>
+    <color name="i_am_color_224">#00000224</color>
+    <color name="i_am_color_225">#00000225</color>
+    <color name="i_am_color_226">#00000226</color>
+    <color name="i_am_color_227">#00000227</color>
+    <color name="i_am_color_228">#00000228</color>
+    <color name="i_am_color_229">#00000229</color>
+    <color name="i_am_color_22a">#0000022a</color>
+    <color name="i_am_color_22b">#0000022b</color>
+    <color name="i_am_color_22c">#0000022c</color>
+    <color name="i_am_color_22d">#0000022d</color>
+    <color name="i_am_color_22e">#0000022e</color>
+    <color name="i_am_color_22f">#0000022f</color>
+    <color name="i_am_color_230">#00000230</color>
+    <color name="i_am_color_231">#00000231</color>
+    <color name="i_am_color_232">#00000232</color>
+    <color name="i_am_color_233">#00000233</color>
+    <color name="i_am_color_234">#00000234</color>
+    <color name="i_am_color_235">#00000235</color>
+    <color name="i_am_color_236">#00000236</color>
+    <color name="i_am_color_237">#00000237</color>
+    <color name="i_am_color_238">#00000238</color>
+    <color name="i_am_color_239">#00000239</color>
+    <color name="i_am_color_23a">#0000023a</color>
+    <color name="i_am_color_23b">#0000023b</color>
+    <color name="i_am_color_23c">#0000023c</color>
+    <color name="i_am_color_23d">#0000023d</color>
+    <color name="i_am_color_23e">#0000023e</color>
+    <color name="i_am_color_23f">#0000023f</color>
+    <color name="i_am_color_240">#00000240</color>
+    <color name="i_am_color_241">#00000241</color>
+    <color name="i_am_color_242">#00000242</color>
+    <color name="i_am_color_243">#00000243</color>
+    <color name="i_am_color_244">#00000244</color>
+    <color name="i_am_color_245">#00000245</color>
+    <color name="i_am_color_246">#00000246</color>
+    <color name="i_am_color_247">#00000247</color>
+    <color name="i_am_color_248">#00000248</color>
+    <color name="i_am_color_249">#00000249</color>
+    <color name="i_am_color_24a">#0000024a</color>
+    <color name="i_am_color_24b">#0000024b</color>
+    <color name="i_am_color_24c">#0000024c</color>
+    <color name="i_am_color_24d">#0000024d</color>
+    <color name="i_am_color_24e">#0000024e</color>
+    <color name="i_am_color_24f">#0000024f</color>
+    <color name="i_am_color_250">#00000250</color>
+    <color name="i_am_color_251">#00000251</color>
+    <color name="i_am_color_252">#00000252</color>
+    <color name="i_am_color_253">#00000253</color>
+    <color name="i_am_color_254">#00000254</color>
+    <color name="i_am_color_255">#00000255</color>
+    <color name="i_am_color_256">#00000256</color>
+    <color name="i_am_color_257">#00000257</color>
+    <color name="i_am_color_258">#00000258</color>
+    <color name="i_am_color_259">#00000259</color>
+    <color name="i_am_color_25a">#0000025a</color>
+    <color name="i_am_color_25b">#0000025b</color>
+    <color name="i_am_color_25c">#0000025c</color>
+    <color name="i_am_color_25d">#0000025d</color>
+    <color name="i_am_color_25e">#0000025e</color>
+    <color name="i_am_color_25f">#0000025f</color>
+    <color name="i_am_color_260">#00000260</color>
+    <color name="i_am_color_261">#00000261</color>
+    <color name="i_am_color_262">#00000262</color>
+    <color name="i_am_color_263">#00000263</color>
+    <color name="i_am_color_264">#00000264</color>
+    <color name="i_am_color_265">#00000265</color>
+    <color name="i_am_color_266">#00000266</color>
+    <color name="i_am_color_267">#00000267</color>
+    <color name="i_am_color_268">#00000268</color>
+    <color name="i_am_color_269">#00000269</color>
+    <color name="i_am_color_26a">#0000026a</color>
+    <color name="i_am_color_26b">#0000026b</color>
+    <color name="i_am_color_26c">#0000026c</color>
+    <color name="i_am_color_26d">#0000026d</color>
+    <color name="i_am_color_26e">#0000026e</color>
+    <color name="i_am_color_26f">#0000026f</color>
+    <color name="i_am_color_270">#00000270</color>
+    <color name="i_am_color_271">#00000271</color>
+    <color name="i_am_color_272">#00000272</color>
+    <color name="i_am_color_273">#00000273</color>
+    <color name="i_am_color_274">#00000274</color>
+    <color name="i_am_color_275">#00000275</color>
+    <color name="i_am_color_276">#00000276</color>
+    <color name="i_am_color_277">#00000277</color>
+    <color name="i_am_color_278">#00000278</color>
+    <color name="i_am_color_279">#00000279</color>
+    <color name="i_am_color_27a">#0000027a</color>
+    <color name="i_am_color_27b">#0000027b</color>
+    <color name="i_am_color_27c">#0000027c</color>
+    <color name="i_am_color_27d">#0000027d</color>
+    <color name="i_am_color_27e">#0000027e</color>
+    <color name="i_am_color_27f">#0000027f</color>
+    <color name="i_am_color_280">#00000280</color>
+    <color name="i_am_color_281">#00000281</color>
+    <color name="i_am_color_282">#00000282</color>
+    <color name="i_am_color_283">#00000283</color>
+    <color name="i_am_color_284">#00000284</color>
+    <color name="i_am_color_285">#00000285</color>
+    <color name="i_am_color_286">#00000286</color>
+    <color name="i_am_color_287">#00000287</color>
+    <color name="i_am_color_288">#00000288</color>
+    <color name="i_am_color_289">#00000289</color>
+    <color name="i_am_color_28a">#0000028a</color>
+    <color name="i_am_color_28b">#0000028b</color>
+    <color name="i_am_color_28c">#0000028c</color>
+    <color name="i_am_color_28d">#0000028d</color>
+    <color name="i_am_color_28e">#0000028e</color>
+    <color name="i_am_color_28f">#0000028f</color>
+    <color name="i_am_color_290">#00000290</color>
+    <color name="i_am_color_291">#00000291</color>
+    <color name="i_am_color_292">#00000292</color>
+    <color name="i_am_color_293">#00000293</color>
+    <color name="i_am_color_294">#00000294</color>
+    <color name="i_am_color_295">#00000295</color>
+    <color name="i_am_color_296">#00000296</color>
+    <color name="i_am_color_297">#00000297</color>
+    <color name="i_am_color_298">#00000298</color>
+    <color name="i_am_color_299">#00000299</color>
+    <color name="i_am_color_29a">#0000029a</color>
+    <color name="i_am_color_29b">#0000029b</color>
+    <color name="i_am_color_29c">#0000029c</color>
+    <color name="i_am_color_29d">#0000029d</color>
+    <color name="i_am_color_29e">#0000029e</color>
+    <color name="i_am_color_29f">#0000029f</color>
+    <color name="i_am_color_2a0">#000002a0</color>
+    <color name="i_am_color_2a1">#000002a1</color>
+    <color name="i_am_color_2a2">#000002a2</color>
+    <color name="i_am_color_2a3">#000002a3</color>
+    <color name="i_am_color_2a4">#000002a4</color>
+    <color name="i_am_color_2a5">#000002a5</color>
+    <color name="i_am_color_2a6">#000002a6</color>
+    <color name="i_am_color_2a7">#000002a7</color>
+    <color name="i_am_color_2a8">#000002a8</color>
+    <color name="i_am_color_2a9">#000002a9</color>
+    <color name="i_am_color_2aa">#000002aa</color>
+    <color name="i_am_color_2ab">#000002ab</color>
+    <color name="i_am_color_2ac">#000002ac</color>
+    <color name="i_am_color_2ad">#000002ad</color>
+    <color name="i_am_color_2ae">#000002ae</color>
+    <color name="i_am_color_2af">#000002af</color>
+    <color name="i_am_color_2b0">#000002b0</color>
+    <color name="i_am_color_2b1">#000002b1</color>
+    <color name="i_am_color_2b2">#000002b2</color>
+    <color name="i_am_color_2b3">#000002b3</color>
+    <color name="i_am_color_2b4">#000002b4</color>
+    <color name="i_am_color_2b5">#000002b5</color>
+    <color name="i_am_color_2b6">#000002b6</color>
+    <color name="i_am_color_2b7">#000002b7</color>
+    <color name="i_am_color_2b8">#000002b8</color>
+    <color name="i_am_color_2b9">#000002b9</color>
+    <color name="i_am_color_2ba">#000002ba</color>
+    <color name="i_am_color_2bb">#000002bb</color>
+    <color name="i_am_color_2bc">#000002bc</color>
+    <color name="i_am_color_2bd">#000002bd</color>
+    <color name="i_am_color_2be">#000002be</color>
+    <color name="i_am_color_2bf">#000002bf</color>
+    <color name="i_am_color_2c0">#000002c0</color>
+    <color name="i_am_color_2c1">#000002c1</color>
+    <color name="i_am_color_2c2">#000002c2</color>
+    <color name="i_am_color_2c3">#000002c3</color>
+    <color name="i_am_color_2c4">#000002c4</color>
+    <color name="i_am_color_2c5">#000002c5</color>
+    <color name="i_am_color_2c6">#000002c6</color>
+    <color name="i_am_color_2c7">#000002c7</color>
+    <color name="i_am_color_2c8">#000002c8</color>
+    <color name="i_am_color_2c9">#000002c9</color>
+    <color name="i_am_color_2ca">#000002ca</color>
+    <color name="i_am_color_2cb">#000002cb</color>
+    <color name="i_am_color_2cc">#000002cc</color>
+    <color name="i_am_color_2cd">#000002cd</color>
+    <color name="i_am_color_2ce">#000002ce</color>
+    <color name="i_am_color_2cf">#000002cf</color>
+    <color name="i_am_color_2d0">#000002d0</color>
+    <color name="i_am_color_2d1">#000002d1</color>
+    <color name="i_am_color_2d2">#000002d2</color>
+    <color name="i_am_color_2d3">#000002d3</color>
+    <color name="i_am_color_2d4">#000002d4</color>
+    <color name="i_am_color_2d5">#000002d5</color>
+    <color name="i_am_color_2d6">#000002d6</color>
+    <color name="i_am_color_2d7">#000002d7</color>
+    <color name="i_am_color_2d8">#000002d8</color>
+    <color name="i_am_color_2d9">#000002d9</color>
+    <color name="i_am_color_2da">#000002da</color>
+    <color name="i_am_color_2db">#000002db</color>
+    <color name="i_am_color_2dc">#000002dc</color>
+    <color name="i_am_color_2dd">#000002dd</color>
+    <color name="i_am_color_2de">#000002de</color>
+    <color name="i_am_color_2df">#000002df</color>
+    <color name="i_am_color_2e0">#000002e0</color>
+    <color name="i_am_color_2e1">#000002e1</color>
+    <color name="i_am_color_2e2">#000002e2</color>
+    <color name="i_am_color_2e3">#000002e3</color>
+    <color name="i_am_color_2e4">#000002e4</color>
+    <color name="i_am_color_2e5">#000002e5</color>
+    <color name="i_am_color_2e6">#000002e6</color>
+    <color name="i_am_color_2e7">#000002e7</color>
+    <color name="i_am_color_2e8">#000002e8</color>
+    <color name="i_am_color_2e9">#000002e9</color>
+    <color name="i_am_color_2ea">#000002ea</color>
+    <color name="i_am_color_2eb">#000002eb</color>
+    <color name="i_am_color_2ec">#000002ec</color>
+    <color name="i_am_color_2ed">#000002ed</color>
+    <color name="i_am_color_2ee">#000002ee</color>
+    <color name="i_am_color_2ef">#000002ef</color>
+    <color name="i_am_color_2f0">#000002f0</color>
+    <color name="i_am_color_2f1">#000002f1</color>
+    <color name="i_am_color_2f2">#000002f2</color>
+    <color name="i_am_color_2f3">#000002f3</color>
+    <color name="i_am_color_2f4">#000002f4</color>
+    <color name="i_am_color_2f5">#000002f5</color>
+    <color name="i_am_color_2f6">#000002f6</color>
+    <color name="i_am_color_2f7">#000002f7</color>
+    <color name="i_am_color_2f8">#000002f8</color>
+    <color name="i_am_color_2f9">#000002f9</color>
+    <color name="i_am_color_2fa">#000002fa</color>
+    <color name="i_am_color_2fb">#000002fb</color>
+    <color name="i_am_color_2fc">#000002fc</color>
+    <color name="i_am_color_2fd">#000002fd</color>
+    <color name="i_am_color_2fe">#000002fe</color>
+    <color name="i_am_color_2ff">#000002ff</color>
+    <color name="i_am_color_300">#00000300</color>
+    <color name="i_am_color_301">#00000301</color>
+    <color name="i_am_color_302">#00000302</color>
+    <color name="i_am_color_303">#00000303</color>
+    <color name="i_am_color_304">#00000304</color>
+    <color name="i_am_color_305">#00000305</color>
+    <color name="i_am_color_306">#00000306</color>
+    <color name="i_am_color_307">#00000307</color>
+    <color name="i_am_color_308">#00000308</color>
+    <color name="i_am_color_309">#00000309</color>
+    <color name="i_am_color_30a">#0000030a</color>
+    <color name="i_am_color_30b">#0000030b</color>
+    <color name="i_am_color_30c">#0000030c</color>
+    <color name="i_am_color_30d">#0000030d</color>
+    <color name="i_am_color_30e">#0000030e</color>
+    <color name="i_am_color_30f">#0000030f</color>
+    <color name="i_am_color_310">#00000310</color>
+    <color name="i_am_color_311">#00000311</color>
+    <color name="i_am_color_312">#00000312</color>
+    <color name="i_am_color_313">#00000313</color>
+    <color name="i_am_color_314">#00000314</color>
+    <color name="i_am_color_315">#00000315</color>
+    <color name="i_am_color_316">#00000316</color>
+    <color name="i_am_color_317">#00000317</color>
+    <color name="i_am_color_318">#00000318</color>
+    <color name="i_am_color_319">#00000319</color>
+    <color name="i_am_color_31a">#0000031a</color>
+    <color name="i_am_color_31b">#0000031b</color>
+    <color name="i_am_color_31c">#0000031c</color>
+    <color name="i_am_color_31d">#0000031d</color>
+    <color name="i_am_color_31e">#0000031e</color>
+    <color name="i_am_color_31f">#0000031f</color>
+    <color name="i_am_color_320">#00000320</color>
+    <color name="i_am_color_321">#00000321</color>
+    <color name="i_am_color_322">#00000322</color>
+    <color name="i_am_color_323">#00000323</color>
+    <color name="i_am_color_324">#00000324</color>
+    <color name="i_am_color_325">#00000325</color>
+    <color name="i_am_color_326">#00000326</color>
+    <color name="i_am_color_327">#00000327</color>
+    <color name="i_am_color_328">#00000328</color>
+    <color name="i_am_color_329">#00000329</color>
+    <color name="i_am_color_32a">#0000032a</color>
+    <color name="i_am_color_32b">#0000032b</color>
+    <color name="i_am_color_32c">#0000032c</color>
+    <color name="i_am_color_32d">#0000032d</color>
+    <color name="i_am_color_32e">#0000032e</color>
+    <color name="i_am_color_32f">#0000032f</color>
+    <color name="i_am_color_330">#00000330</color>
+    <color name="i_am_color_331">#00000331</color>
+    <color name="i_am_color_332">#00000332</color>
+    <color name="i_am_color_333">#00000333</color>
+    <color name="i_am_color_334">#00000334</color>
+    <color name="i_am_color_335">#00000335</color>
+    <color name="i_am_color_336">#00000336</color>
+    <color name="i_am_color_337">#00000337</color>
+    <color name="i_am_color_338">#00000338</color>
+    <color name="i_am_color_339">#00000339</color>
+    <color name="i_am_color_33a">#0000033a</color>
+    <color name="i_am_color_33b">#0000033b</color>
+    <color name="i_am_color_33c">#0000033c</color>
+    <color name="i_am_color_33d">#0000033d</color>
+    <color name="i_am_color_33e">#0000033e</color>
+    <color name="i_am_color_33f">#0000033f</color>
+    <color name="i_am_color_340">#00000340</color>
+    <color name="i_am_color_341">#00000341</color>
+    <color name="i_am_color_342">#00000342</color>
+    <color name="i_am_color_343">#00000343</color>
+    <color name="i_am_color_344">#00000344</color>
+    <color name="i_am_color_345">#00000345</color>
+    <color name="i_am_color_346">#00000346</color>
+    <color name="i_am_color_347">#00000347</color>
+    <color name="i_am_color_348">#00000348</color>
+    <color name="i_am_color_349">#00000349</color>
+    <color name="i_am_color_34a">#0000034a</color>
+    <color name="i_am_color_34b">#0000034b</color>
+    <color name="i_am_color_34c">#0000034c</color>
+    <color name="i_am_color_34d">#0000034d</color>
+    <color name="i_am_color_34e">#0000034e</color>
+    <color name="i_am_color_34f">#0000034f</color>
+    <color name="i_am_color_350">#00000350</color>
+    <color name="i_am_color_351">#00000351</color>
+    <color name="i_am_color_352">#00000352</color>
+    <color name="i_am_color_353">#00000353</color>
+    <color name="i_am_color_354">#00000354</color>
+    <color name="i_am_color_355">#00000355</color>
+    <color name="i_am_color_356">#00000356</color>
+    <color name="i_am_color_357">#00000357</color>
+    <color name="i_am_color_358">#00000358</color>
+    <color name="i_am_color_359">#00000359</color>
+    <color name="i_am_color_35a">#0000035a</color>
+    <color name="i_am_color_35b">#0000035b</color>
+    <color name="i_am_color_35c">#0000035c</color>
+    <color name="i_am_color_35d">#0000035d</color>
+    <color name="i_am_color_35e">#0000035e</color>
+    <color name="i_am_color_35f">#0000035f</color>
+    <color name="i_am_color_360">#00000360</color>
+    <color name="i_am_color_361">#00000361</color>
+    <color name="i_am_color_362">#00000362</color>
+    <color name="i_am_color_363">#00000363</color>
+    <color name="i_am_color_364">#00000364</color>
+    <color name="i_am_color_365">#00000365</color>
+    <color name="i_am_color_366">#00000366</color>
+    <color name="i_am_color_367">#00000367</color>
+    <color name="i_am_color_368">#00000368</color>
+    <color name="i_am_color_369">#00000369</color>
+    <color name="i_am_color_36a">#0000036a</color>
+    <color name="i_am_color_36b">#0000036b</color>
+    <color name="i_am_color_36c">#0000036c</color>
+    <color name="i_am_color_36d">#0000036d</color>
+    <color name="i_am_color_36e">#0000036e</color>
+    <color name="i_am_color_36f">#0000036f</color>
+    <color name="i_am_color_370">#00000370</color>
+    <color name="i_am_color_371">#00000371</color>
+    <color name="i_am_color_372">#00000372</color>
+    <color name="i_am_color_373">#00000373</color>
+    <color name="i_am_color_374">#00000374</color>
+    <color name="i_am_color_375">#00000375</color>
+    <color name="i_am_color_376">#00000376</color>
+    <color name="i_am_color_377">#00000377</color>
+    <color name="i_am_color_378">#00000378</color>
+    <color name="i_am_color_379">#00000379</color>
+    <color name="i_am_color_37a">#0000037a</color>
+    <color name="i_am_color_37b">#0000037b</color>
+    <color name="i_am_color_37c">#0000037c</color>
+    <color name="i_am_color_37d">#0000037d</color>
+    <color name="i_am_color_37e">#0000037e</color>
+    <color name="i_am_color_37f">#0000037f</color>
+    <color name="i_am_color_380">#00000380</color>
+    <color name="i_am_color_381">#00000381</color>
+    <color name="i_am_color_382">#00000382</color>
+    <color name="i_am_color_383">#00000383</color>
+    <color name="i_am_color_384">#00000384</color>
+    <color name="i_am_color_385">#00000385</color>
+    <color name="i_am_color_386">#00000386</color>
+    <color name="i_am_color_387">#00000387</color>
+    <color name="i_am_color_388">#00000388</color>
+    <color name="i_am_color_389">#00000389</color>
+    <color name="i_am_color_38a">#0000038a</color>
+    <color name="i_am_color_38b">#0000038b</color>
+    <color name="i_am_color_38c">#0000038c</color>
+    <color name="i_am_color_38d">#0000038d</color>
+    <color name="i_am_color_38e">#0000038e</color>
+    <color name="i_am_color_38f">#0000038f</color>
+    <color name="i_am_color_390">#00000390</color>
+    <color name="i_am_color_391">#00000391</color>
+    <color name="i_am_color_392">#00000392</color>
+    <color name="i_am_color_393">#00000393</color>
+    <color name="i_am_color_394">#00000394</color>
+    <color name="i_am_color_395">#00000395</color>
+    <color name="i_am_color_396">#00000396</color>
+    <color name="i_am_color_397">#00000397</color>
+    <color name="i_am_color_398">#00000398</color>
+    <color name="i_am_color_399">#00000399</color>
+    <color name="i_am_color_39a">#0000039a</color>
+    <color name="i_am_color_39b">#0000039b</color>
+    <color name="i_am_color_39c">#0000039c</color>
+    <color name="i_am_color_39d">#0000039d</color>
+    <color name="i_am_color_39e">#0000039e</color>
+    <color name="i_am_color_39f">#0000039f</color>
+    <color name="i_am_color_3a0">#000003a0</color>
+    <color name="i_am_color_3a1">#000003a1</color>
+    <color name="i_am_color_3a2">#000003a2</color>
+    <color name="i_am_color_3a3">#000003a3</color>
+    <color name="i_am_color_3a4">#000003a4</color>
+    <color name="i_am_color_3a5">#000003a5</color>
+    <color name="i_am_color_3a6">#000003a6</color>
+    <color name="i_am_color_3a7">#000003a7</color>
+    <color name="i_am_color_3a8">#000003a8</color>
+    <color name="i_am_color_3a9">#000003a9</color>
+    <color name="i_am_color_3aa">#000003aa</color>
+    <color name="i_am_color_3ab">#000003ab</color>
+    <color name="i_am_color_3ac">#000003ac</color>
+    <color name="i_am_color_3ad">#000003ad</color>
+    <color name="i_am_color_3ae">#000003ae</color>
+    <color name="i_am_color_3af">#000003af</color>
+    <color name="i_am_color_3b0">#000003b0</color>
+    <color name="i_am_color_3b1">#000003b1</color>
+    <color name="i_am_color_3b2">#000003b2</color>
+    <color name="i_am_color_3b3">#000003b3</color>
+    <color name="i_am_color_3b4">#000003b4</color>
+    <color name="i_am_color_3b5">#000003b5</color>
+    <color name="i_am_color_3b6">#000003b6</color>
+    <color name="i_am_color_3b7">#000003b7</color>
+    <color name="i_am_color_3b8">#000003b8</color>
+    <color name="i_am_color_3b9">#000003b9</color>
+    <color name="i_am_color_3ba">#000003ba</color>
+    <color name="i_am_color_3bb">#000003bb</color>
+    <color name="i_am_color_3bc">#000003bc</color>
+    <color name="i_am_color_3bd">#000003bd</color>
+    <color name="i_am_color_3be">#000003be</color>
+    <color name="i_am_color_3bf">#000003bf</color>
+    <color name="i_am_color_3c0">#000003c0</color>
+    <color name="i_am_color_3c1">#000003c1</color>
+    <color name="i_am_color_3c2">#000003c2</color>
+    <color name="i_am_color_3c3">#000003c3</color>
+    <color name="i_am_color_3c4">#000003c4</color>
+    <color name="i_am_color_3c5">#000003c5</color>
+    <color name="i_am_color_3c6">#000003c6</color>
+    <color name="i_am_color_3c7">#000003c7</color>
+    <color name="i_am_color_3c8">#000003c8</color>
+    <color name="i_am_color_3c9">#000003c9</color>
+    <color name="i_am_color_3ca">#000003ca</color>
+    <color name="i_am_color_3cb">#000003cb</color>
+    <color name="i_am_color_3cc">#000003cc</color>
+    <color name="i_am_color_3cd">#000003cd</color>
+    <color name="i_am_color_3ce">#000003ce</color>
+    <color name="i_am_color_3cf">#000003cf</color>
+    <color name="i_am_color_3d0">#000003d0</color>
+    <color name="i_am_color_3d1">#000003d1</color>
+    <color name="i_am_color_3d2">#000003d2</color>
+    <color name="i_am_color_3d3">#000003d3</color>
+    <color name="i_am_color_3d4">#000003d4</color>
+    <color name="i_am_color_3d5">#000003d5</color>
+    <color name="i_am_color_3d6">#000003d6</color>
+    <color name="i_am_color_3d7">#000003d7</color>
+    <color name="i_am_color_3d8">#000003d8</color>
+    <color name="i_am_color_3d9">#000003d9</color>
+    <color name="i_am_color_3da">#000003da</color>
+    <color name="i_am_color_3db">#000003db</color>
+    <color name="i_am_color_3dc">#000003dc</color>
+    <color name="i_am_color_3dd">#000003dd</color>
+    <color name="i_am_color_3de">#000003de</color>
+    <color name="i_am_color_3df">#000003df</color>
+    <color name="i_am_color_3e0">#000003e0</color>
+    <color name="i_am_color_3e1">#000003e1</color>
+    <color name="i_am_color_3e2">#000003e2</color>
+    <color name="i_am_color_3e3">#000003e3</color>
+    <color name="i_am_color_3e4">#000003e4</color>
+    <color name="i_am_color_3e5">#000003e5</color>
+    <color name="i_am_color_3e6">#000003e6</color>
+    <color name="i_am_color_3e7">#000003e7</color>
+    <color name="i_am_color_3e8">#000003e8</color>
+    <color name="i_am_color_3e9">#000003e9</color>
+    <color name="i_am_color_3ea">#000003ea</color>
+    <color name="i_am_color_3eb">#000003eb</color>
+    <color name="i_am_color_3ec">#000003ec</color>
+    <color name="i_am_color_3ed">#000003ed</color>
+    <color name="i_am_color_3ee">#000003ee</color>
+    <color name="i_am_color_3ef">#000003ef</color>
+    <color name="i_am_color_3f0">#000003f0</color>
+    <color name="i_am_color_3f1">#000003f1</color>
+    <color name="i_am_color_3f2">#000003f2</color>
+    <color name="i_am_color_3f3">#000003f3</color>
+    <color name="i_am_color_3f4">#000003f4</color>
+    <color name="i_am_color_3f5">#000003f5</color>
+    <color name="i_am_color_3f6">#000003f6</color>
+    <color name="i_am_color_3f7">#000003f7</color>
+    <color name="i_am_color_3f8">#000003f8</color>
+    <color name="i_am_color_3f9">#000003f9</color>
+    <color name="i_am_color_3fa">#000003fa</color>
+    <color name="i_am_color_3fb">#000003fb</color>
+    <color name="i_am_color_3fc">#000003fc</color>
+    <color name="i_am_color_3fd">#000003fd</color>
+    <color name="i_am_color_3fe">#000003fe</color>
+    <color name="i_am_color_3ff">#000003ff</color>
+    <color name="i_am_color_400">#00000400</color>
+    <color name="i_am_color_401">#00000401</color>
+    <color name="i_am_color_402">#00000402</color>
+    <color name="i_am_color_403">#00000403</color>
+    <color name="i_am_color_404">#00000404</color>
+    <color name="i_am_color_405">#00000405</color>
+    <color name="i_am_color_406">#00000406</color>
+    <color name="i_am_color_407">#00000407</color>
+    <color name="i_am_color_408">#00000408</color>
+    <color name="i_am_color_409">#00000409</color>
+    <color name="i_am_color_40a">#0000040a</color>
+    <color name="i_am_color_40b">#0000040b</color>
+    <color name="i_am_color_40c">#0000040c</color>
+    <color name="i_am_color_40d">#0000040d</color>
+    <color name="i_am_color_40e">#0000040e</color>
+    <color name="i_am_color_40f">#0000040f</color>
+    <color name="i_am_color_410">#00000410</color>
+    <color name="i_am_color_411">#00000411</color>
+    <color name="i_am_color_412">#00000412</color>
+    <color name="i_am_color_413">#00000413</color>
+    <color name="i_am_color_414">#00000414</color>
+    <color name="i_am_color_415">#00000415</color>
+    <color name="i_am_color_416">#00000416</color>
+    <color name="i_am_color_417">#00000417</color>
+    <color name="i_am_color_418">#00000418</color>
+    <color name="i_am_color_419">#00000419</color>
+    <color name="i_am_color_41a">#0000041a</color>
+    <color name="i_am_color_41b">#0000041b</color>
+    <color name="i_am_color_41c">#0000041c</color>
+    <color name="i_am_color_41d">#0000041d</color>
+    <color name="i_am_color_41e">#0000041e</color>
+    <color name="i_am_color_41f">#0000041f</color>
+    <color name="i_am_color_420">#00000420</color>
+    <color name="i_am_color_421">#00000421</color>
+    <color name="i_am_color_422">#00000422</color>
+    <color name="i_am_color_423">#00000423</color>
+    <color name="i_am_color_424">#00000424</color>
+    <color name="i_am_color_425">#00000425</color>
+    <color name="i_am_color_426">#00000426</color>
+    <color name="i_am_color_427">#00000427</color>
+    <color name="i_am_color_428">#00000428</color>
+    <color name="i_am_color_429">#00000429</color>
+    <color name="i_am_color_42a">#0000042a</color>
+    <color name="i_am_color_42b">#0000042b</color>
+    <color name="i_am_color_42c">#0000042c</color>
+    <color name="i_am_color_42d">#0000042d</color>
+    <color name="i_am_color_42e">#0000042e</color>
+    <color name="i_am_color_42f">#0000042f</color>
+    <color name="i_am_color_430">#00000430</color>
+    <color name="i_am_color_431">#00000431</color>
+    <color name="i_am_color_432">#00000432</color>
+    <color name="i_am_color_433">#00000433</color>
+    <color name="i_am_color_434">#00000434</color>
+    <color name="i_am_color_435">#00000435</color>
+    <color name="i_am_color_436">#00000436</color>
+    <color name="i_am_color_437">#00000437</color>
+    <color name="i_am_color_438">#00000438</color>
+    <color name="i_am_color_439">#00000439</color>
+    <color name="i_am_color_43a">#0000043a</color>
+    <color name="i_am_color_43b">#0000043b</color>
+    <color name="i_am_color_43c">#0000043c</color>
+    <color name="i_am_color_43d">#0000043d</color>
+    <color name="i_am_color_43e">#0000043e</color>
+    <color name="i_am_color_43f">#0000043f</color>
+    <color name="i_am_color_440">#00000440</color>
+    <color name="i_am_color_441">#00000441</color>
+    <color name="i_am_color_442">#00000442</color>
+    <color name="i_am_color_443">#00000443</color>
+    <color name="i_am_color_444">#00000444</color>
+    <color name="i_am_color_445">#00000445</color>
+    <color name="i_am_color_446">#00000446</color>
+    <color name="i_am_color_447">#00000447</color>
+    <color name="i_am_color_448">#00000448</color>
+    <color name="i_am_color_449">#00000449</color>
+    <color name="i_am_color_44a">#0000044a</color>
+    <color name="i_am_color_44b">#0000044b</color>
+    <color name="i_am_color_44c">#0000044c</color>
+    <color name="i_am_color_44d">#0000044d</color>
+    <color name="i_am_color_44e">#0000044e</color>
+    <color name="i_am_color_44f">#0000044f</color>
+    <color name="i_am_color_450">#00000450</color>
+    <color name="i_am_color_451">#00000451</color>
+    <color name="i_am_color_452">#00000452</color>
+    <color name="i_am_color_453">#00000453</color>
+    <color name="i_am_color_454">#00000454</color>
+    <color name="i_am_color_455">#00000455</color>
+    <color name="i_am_color_456">#00000456</color>
+    <color name="i_am_color_457">#00000457</color>
+    <color name="i_am_color_458">#00000458</color>
+    <color name="i_am_color_459">#00000459</color>
+    <color name="i_am_color_45a">#0000045a</color>
+    <color name="i_am_color_45b">#0000045b</color>
+    <color name="i_am_color_45c">#0000045c</color>
+    <color name="i_am_color_45d">#0000045d</color>
+    <color name="i_am_color_45e">#0000045e</color>
+    <color name="i_am_color_45f">#0000045f</color>
+    <color name="i_am_color_460">#00000460</color>
+    <color name="i_am_color_461">#00000461</color>
+    <color name="i_am_color_462">#00000462</color>
+    <color name="i_am_color_463">#00000463</color>
+    <color name="i_am_color_464">#00000464</color>
+    <color name="i_am_color_465">#00000465</color>
+    <color name="i_am_color_466">#00000466</color>
+    <color name="i_am_color_467">#00000467</color>
+    <color name="i_am_color_468">#00000468</color>
+    <color name="i_am_color_469">#00000469</color>
+    <color name="i_am_color_46a">#0000046a</color>
+    <color name="i_am_color_46b">#0000046b</color>
+    <color name="i_am_color_46c">#0000046c</color>
+    <color name="i_am_color_46d">#0000046d</color>
+    <color name="i_am_color_46e">#0000046e</color>
+    <color name="i_am_color_46f">#0000046f</color>
+    <color name="i_am_color_470">#00000470</color>
+    <color name="i_am_color_471">#00000471</color>
+    <color name="i_am_color_472">#00000472</color>
+    <color name="i_am_color_473">#00000473</color>
+    <color name="i_am_color_474">#00000474</color>
+    <color name="i_am_color_475">#00000475</color>
+    <color name="i_am_color_476">#00000476</color>
+    <color name="i_am_color_477">#00000477</color>
+    <color name="i_am_color_478">#00000478</color>
+    <color name="i_am_color_479">#00000479</color>
+    <color name="i_am_color_47a">#0000047a</color>
+    <color name="i_am_color_47b">#0000047b</color>
+    <color name="i_am_color_47c">#0000047c</color>
+    <color name="i_am_color_47d">#0000047d</color>
+    <color name="i_am_color_47e">#0000047e</color>
+    <color name="i_am_color_47f">#0000047f</color>
+    <color name="i_am_color_480">#00000480</color>
+    <color name="i_am_color_481">#00000481</color>
+    <color name="i_am_color_482">#00000482</color>
+    <color name="i_am_color_483">#00000483</color>
+    <color name="i_am_color_484">#00000484</color>
+    <color name="i_am_color_485">#00000485</color>
+    <color name="i_am_color_486">#00000486</color>
+    <color name="i_am_color_487">#00000487</color>
+    <color name="i_am_color_488">#00000488</color>
+    <color name="i_am_color_489">#00000489</color>
+    <color name="i_am_color_48a">#0000048a</color>
+    <color name="i_am_color_48b">#0000048b</color>
+    <color name="i_am_color_48c">#0000048c</color>
+    <color name="i_am_color_48d">#0000048d</color>
+    <color name="i_am_color_48e">#0000048e</color>
+    <color name="i_am_color_48f">#0000048f</color>
+    <color name="i_am_color_490">#00000490</color>
+    <color name="i_am_color_491">#00000491</color>
+    <color name="i_am_color_492">#00000492</color>
+    <color name="i_am_color_493">#00000493</color>
+    <color name="i_am_color_494">#00000494</color>
+    <color name="i_am_color_495">#00000495</color>
+    <color name="i_am_color_496">#00000496</color>
+    <color name="i_am_color_497">#00000497</color>
+    <color name="i_am_color_498">#00000498</color>
+    <color name="i_am_color_499">#00000499</color>
+    <color name="i_am_color_49a">#0000049a</color>
+    <color name="i_am_color_49b">#0000049b</color>
+    <color name="i_am_color_49c">#0000049c</color>
+    <color name="i_am_color_49d">#0000049d</color>
+    <color name="i_am_color_49e">#0000049e</color>
+    <color name="i_am_color_49f">#0000049f</color>
+    <color name="i_am_color_4a0">#000004a0</color>
+    <color name="i_am_color_4a1">#000004a1</color>
+    <color name="i_am_color_4a2">#000004a2</color>
+    <color name="i_am_color_4a3">#000004a3</color>
+    <color name="i_am_color_4a4">#000004a4</color>
+    <color name="i_am_color_4a5">#000004a5</color>
+    <color name="i_am_color_4a6">#000004a6</color>
+    <color name="i_am_color_4a7">#000004a7</color>
+    <color name="i_am_color_4a8">#000004a8</color>
+    <color name="i_am_color_4a9">#000004a9</color>
+    <color name="i_am_color_4aa">#000004aa</color>
+    <color name="i_am_color_4ab">#000004ab</color>
+    <color name="i_am_color_4ac">#000004ac</color>
+    <color name="i_am_color_4ad">#000004ad</color>
+    <color name="i_am_color_4ae">#000004ae</color>
+    <color name="i_am_color_4af">#000004af</color>
+    <color name="i_am_color_4b0">#000004b0</color>
+    <color name="i_am_color_4b1">#000004b1</color>
+    <color name="i_am_color_4b2">#000004b2</color>
+    <color name="i_am_color_4b3">#000004b3</color>
+    <color name="i_am_color_4b4">#000004b4</color>
+    <color name="i_am_color_4b5">#000004b5</color>
+    <color name="i_am_color_4b6">#000004b6</color>
+    <color name="i_am_color_4b7">#000004b7</color>
+    <color name="i_am_color_4b8">#000004b8</color>
+    <color name="i_am_color_4b9">#000004b9</color>
+    <color name="i_am_color_4ba">#000004ba</color>
+    <color name="i_am_color_4bb">#000004bb</color>
+    <color name="i_am_color_4bc">#000004bc</color>
+    <color name="i_am_color_4bd">#000004bd</color>
+    <color name="i_am_color_4be">#000004be</color>
+    <color name="i_am_color_4bf">#000004bf</color>
+    <color name="i_am_color_4c0">#000004c0</color>
+    <color name="i_am_color_4c1">#000004c1</color>
+    <color name="i_am_color_4c2">#000004c2</color>
+    <color name="i_am_color_4c3">#000004c3</color>
+    <color name="i_am_color_4c4">#000004c4</color>
+    <color name="i_am_color_4c5">#000004c5</color>
+    <color name="i_am_color_4c6">#000004c6</color>
+    <color name="i_am_color_4c7">#000004c7</color>
+    <color name="i_am_color_4c8">#000004c8</color>
+    <color name="i_am_color_4c9">#000004c9</color>
+    <color name="i_am_color_4ca">#000004ca</color>
+    <color name="i_am_color_4cb">#000004cb</color>
+    <color name="i_am_color_4cc">#000004cc</color>
+    <color name="i_am_color_4cd">#000004cd</color>
+    <color name="i_am_color_4ce">#000004ce</color>
+    <color name="i_am_color_4cf">#000004cf</color>
+    <color name="i_am_color_4d0">#000004d0</color>
+    <color name="i_am_color_4d1">#000004d1</color>
+    <color name="i_am_color_4d2">#000004d2</color>
+    <color name="i_am_color_4d3">#000004d3</color>
+    <color name="i_am_color_4d4">#000004d4</color>
+    <color name="i_am_color_4d5">#000004d5</color>
+    <color name="i_am_color_4d6">#000004d6</color>
+    <color name="i_am_color_4d7">#000004d7</color>
+    <color name="i_am_color_4d8">#000004d8</color>
+    <color name="i_am_color_4d9">#000004d9</color>
+    <color name="i_am_color_4da">#000004da</color>
+    <color name="i_am_color_4db">#000004db</color>
+    <color name="i_am_color_4dc">#000004dc</color>
+    <color name="i_am_color_4dd">#000004dd</color>
+    <color name="i_am_color_4de">#000004de</color>
+    <color name="i_am_color_4df">#000004df</color>
+    <color name="i_am_color_4e0">#000004e0</color>
+    <color name="i_am_color_4e1">#000004e1</color>
+    <color name="i_am_color_4e2">#000004e2</color>
+    <color name="i_am_color_4e3">#000004e3</color>
+    <color name="i_am_color_4e4">#000004e4</color>
+    <color name="i_am_color_4e5">#000004e5</color>
+    <color name="i_am_color_4e6">#000004e6</color>
+    <color name="i_am_color_4e7">#000004e7</color>
+    <color name="i_am_color_4e8">#000004e8</color>
+    <color name="i_am_color_4e9">#000004e9</color>
+    <color name="i_am_color_4ea">#000004ea</color>
+    <color name="i_am_color_4eb">#000004eb</color>
+    <color name="i_am_color_4ec">#000004ec</color>
+    <color name="i_am_color_4ed">#000004ed</color>
+    <color name="i_am_color_4ee">#000004ee</color>
+    <color name="i_am_color_4ef">#000004ef</color>
+    <color name="i_am_color_4f0">#000004f0</color>
+    <color name="i_am_color_4f1">#000004f1</color>
+    <color name="i_am_color_4f2">#000004f2</color>
+    <color name="i_am_color_4f3">#000004f3</color>
+    <color name="i_am_color_4f4">#000004f4</color>
+    <color name="i_am_color_4f5">#000004f5</color>
+    <color name="i_am_color_4f6">#000004f6</color>
+    <color name="i_am_color_4f7">#000004f7</color>
+    <color name="i_am_color_4f8">#000004f8</color>
+    <color name="i_am_color_4f9">#000004f9</color>
+    <color name="i_am_color_4fa">#000004fa</color>
+    <color name="i_am_color_4fb">#000004fb</color>
+    <color name="i_am_color_4fc">#000004fc</color>
+    <color name="i_am_color_4fd">#000004fd</color>
+    <color name="i_am_color_4fe">#000004fe</color>
+    <color name="i_am_color_4ff">#000004ff</color>
+    <color name="i_am_color_500">#00000500</color>
+    <color name="i_am_color_501">#00000501</color>
+    <color name="i_am_color_502">#00000502</color>
+    <color name="i_am_color_503">#00000503</color>
+    <color name="i_am_color_504">#00000504</color>
+    <color name="i_am_color_505">#00000505</color>
+    <color name="i_am_color_506">#00000506</color>
+    <color name="i_am_color_507">#00000507</color>
+    <color name="i_am_color_508">#00000508</color>
+    <color name="i_am_color_509">#00000509</color>
+    <color name="i_am_color_50a">#0000050a</color>
+    <color name="i_am_color_50b">#0000050b</color>
+    <color name="i_am_color_50c">#0000050c</color>
+    <color name="i_am_color_50d">#0000050d</color>
+    <color name="i_am_color_50e">#0000050e</color>
+    <color name="i_am_color_50f">#0000050f</color>
+    <color name="i_am_color_510">#00000510</color>
+    <color name="i_am_color_511">#00000511</color>
+    <color name="i_am_color_512">#00000512</color>
+    <color name="i_am_color_513">#00000513</color>
+    <color name="i_am_color_514">#00000514</color>
+    <color name="i_am_color_515">#00000515</color>
+    <color name="i_am_color_516">#00000516</color>
+    <color name="i_am_color_517">#00000517</color>
+    <color name="i_am_color_518">#00000518</color>
+    <color name="i_am_color_519">#00000519</color>
+    <color name="i_am_color_51a">#0000051a</color>
+    <color name="i_am_color_51b">#0000051b</color>
+    <color name="i_am_color_51c">#0000051c</color>
+    <color name="i_am_color_51d">#0000051d</color>
+    <color name="i_am_color_51e">#0000051e</color>
+    <color name="i_am_color_51f">#0000051f</color>
+    <color name="i_am_color_520">#00000520</color>
+    <color name="i_am_color_521">#00000521</color>
+    <color name="i_am_color_522">#00000522</color>
+    <color name="i_am_color_523">#00000523</color>
+    <color name="i_am_color_524">#00000524</color>
+    <color name="i_am_color_525">#00000525</color>
+    <color name="i_am_color_526">#00000526</color>
+    <color name="i_am_color_527">#00000527</color>
+    <color name="i_am_color_528">#00000528</color>
+    <color name="i_am_color_529">#00000529</color>
+    <color name="i_am_color_52a">#0000052a</color>
+    <color name="i_am_color_52b">#0000052b</color>
+    <color name="i_am_color_52c">#0000052c</color>
+    <color name="i_am_color_52d">#0000052d</color>
+    <color name="i_am_color_52e">#0000052e</color>
+    <color name="i_am_color_52f">#0000052f</color>
+    <color name="i_am_color_530">#00000530</color>
+    <color name="i_am_color_531">#00000531</color>
+    <color name="i_am_color_532">#00000532</color>
+    <color name="i_am_color_533">#00000533</color>
+    <color name="i_am_color_534">#00000534</color>
+    <color name="i_am_color_535">#00000535</color>
+    <color name="i_am_color_536">#00000536</color>
+    <color name="i_am_color_537">#00000537</color>
+    <color name="i_am_color_538">#00000538</color>
+    <color name="i_am_color_539">#00000539</color>
+    <color name="i_am_color_53a">#0000053a</color>
+    <color name="i_am_color_53b">#0000053b</color>
+    <color name="i_am_color_53c">#0000053c</color>
+    <color name="i_am_color_53d">#0000053d</color>
+    <color name="i_am_color_53e">#0000053e</color>
+    <color name="i_am_color_53f">#0000053f</color>
+    <color name="i_am_color_540">#00000540</color>
+    <color name="i_am_color_541">#00000541</color>
+    <color name="i_am_color_542">#00000542</color>
+    <color name="i_am_color_543">#00000543</color>
+    <color name="i_am_color_544">#00000544</color>
+    <color name="i_am_color_545">#00000545</color>
+    <color name="i_am_color_546">#00000546</color>
+    <color name="i_am_color_547">#00000547</color>
+    <color name="i_am_color_548">#00000548</color>
+    <color name="i_am_color_549">#00000549</color>
+    <color name="i_am_color_54a">#0000054a</color>
+    <color name="i_am_color_54b">#0000054b</color>
+    <color name="i_am_color_54c">#0000054c</color>
+    <color name="i_am_color_54d">#0000054d</color>
+    <color name="i_am_color_54e">#0000054e</color>
+    <color name="i_am_color_54f">#0000054f</color>
+    <color name="i_am_color_550">#00000550</color>
+    <color name="i_am_color_551">#00000551</color>
+    <color name="i_am_color_552">#00000552</color>
+    <color name="i_am_color_553">#00000553</color>
+    <color name="i_am_color_554">#00000554</color>
+    <color name="i_am_color_555">#00000555</color>
+    <color name="i_am_color_556">#00000556</color>
+    <color name="i_am_color_557">#00000557</color>
+    <color name="i_am_color_558">#00000558</color>
+    <color name="i_am_color_559">#00000559</color>
+    <color name="i_am_color_55a">#0000055a</color>
+    <color name="i_am_color_55b">#0000055b</color>
+    <color name="i_am_color_55c">#0000055c</color>
+    <color name="i_am_color_55d">#0000055d</color>
+    <color name="i_am_color_55e">#0000055e</color>
+    <color name="i_am_color_55f">#0000055f</color>
+    <color name="i_am_color_560">#00000560</color>
+    <color name="i_am_color_561">#00000561</color>
+    <color name="i_am_color_562">#00000562</color>
+    <color name="i_am_color_563">#00000563</color>
+    <color name="i_am_color_564">#00000564</color>
+    <color name="i_am_color_565">#00000565</color>
+    <color name="i_am_color_566">#00000566</color>
+    <color name="i_am_color_567">#00000567</color>
+    <color name="i_am_color_568">#00000568</color>
+    <color name="i_am_color_569">#00000569</color>
+    <color name="i_am_color_56a">#0000056a</color>
+    <color name="i_am_color_56b">#0000056b</color>
+    <color name="i_am_color_56c">#0000056c</color>
+    <color name="i_am_color_56d">#0000056d</color>
+    <color name="i_am_color_56e">#0000056e</color>
+    <color name="i_am_color_56f">#0000056f</color>
+    <color name="i_am_color_570">#00000570</color>
+    <color name="i_am_color_571">#00000571</color>
+    <color name="i_am_color_572">#00000572</color>
+    <color name="i_am_color_573">#00000573</color>
+    <color name="i_am_color_574">#00000574</color>
+    <color name="i_am_color_575">#00000575</color>
+    <color name="i_am_color_576">#00000576</color>
+    <color name="i_am_color_577">#00000577</color>
+    <color name="i_am_color_578">#00000578</color>
+    <color name="i_am_color_579">#00000579</color>
+    <color name="i_am_color_57a">#0000057a</color>
+    <color name="i_am_color_57b">#0000057b</color>
+    <color name="i_am_color_57c">#0000057c</color>
+    <color name="i_am_color_57d">#0000057d</color>
+    <color name="i_am_color_57e">#0000057e</color>
+    <color name="i_am_color_57f">#0000057f</color>
+    <color name="i_am_color_580">#00000580</color>
+    <color name="i_am_color_581">#00000581</color>
+    <color name="i_am_color_582">#00000582</color>
+    <color name="i_am_color_583">#00000583</color>
+    <color name="i_am_color_584">#00000584</color>
+    <color name="i_am_color_585">#00000585</color>
+    <color name="i_am_color_586">#00000586</color>
+    <color name="i_am_color_587">#00000587</color>
+    <color name="i_am_color_588">#00000588</color>
+    <color name="i_am_color_589">#00000589</color>
+    <color name="i_am_color_58a">#0000058a</color>
+    <color name="i_am_color_58b">#0000058b</color>
+    <color name="i_am_color_58c">#0000058c</color>
+    <color name="i_am_color_58d">#0000058d</color>
+    <color name="i_am_color_58e">#0000058e</color>
+    <color name="i_am_color_58f">#0000058f</color>
+    <color name="i_am_color_590">#00000590</color>
+    <color name="i_am_color_591">#00000591</color>
+    <color name="i_am_color_592">#00000592</color>
+    <color name="i_am_color_593">#00000593</color>
+    <color name="i_am_color_594">#00000594</color>
+    <color name="i_am_color_595">#00000595</color>
+    <color name="i_am_color_596">#00000596</color>
+    <color name="i_am_color_597">#00000597</color>
+    <color name="i_am_color_598">#00000598</color>
+    <color name="i_am_color_599">#00000599</color>
+    <color name="i_am_color_59a">#0000059a</color>
+    <color name="i_am_color_59b">#0000059b</color>
+    <color name="i_am_color_59c">#0000059c</color>
+    <color name="i_am_color_59d">#0000059d</color>
+    <color name="i_am_color_59e">#0000059e</color>
+    <color name="i_am_color_59f">#0000059f</color>
+    <color name="i_am_color_5a0">#000005a0</color>
+    <color name="i_am_color_5a1">#000005a1</color>
+    <color name="i_am_color_5a2">#000005a2</color>
+    <color name="i_am_color_5a3">#000005a3</color>
+    <color name="i_am_color_5a4">#000005a4</color>
+    <color name="i_am_color_5a5">#000005a5</color>
+    <color name="i_am_color_5a6">#000005a6</color>
+    <color name="i_am_color_5a7">#000005a7</color>
+    <color name="i_am_color_5a8">#000005a8</color>
+    <color name="i_am_color_5a9">#000005a9</color>
+    <color name="i_am_color_5aa">#000005aa</color>
+    <color name="i_am_color_5ab">#000005ab</color>
+    <color name="i_am_color_5ac">#000005ac</color>
+    <color name="i_am_color_5ad">#000005ad</color>
+    <color name="i_am_color_5ae">#000005ae</color>
+    <color name="i_am_color_5af">#000005af</color>
+    <color name="i_am_color_5b0">#000005b0</color>
+    <color name="i_am_color_5b1">#000005b1</color>
+    <color name="i_am_color_5b2">#000005b2</color>
+    <color name="i_am_color_5b3">#000005b3</color>
+    <color name="i_am_color_5b4">#000005b4</color>
+    <color name="i_am_color_5b5">#000005b5</color>
+    <color name="i_am_color_5b6">#000005b6</color>
+    <color name="i_am_color_5b7">#000005b7</color>
+    <color name="i_am_color_5b8">#000005b8</color>
+    <color name="i_am_color_5b9">#000005b9</color>
+    <color name="i_am_color_5ba">#000005ba</color>
+    <color name="i_am_color_5bb">#000005bb</color>
+    <color name="i_am_color_5bc">#000005bc</color>
+    <color name="i_am_color_5bd">#000005bd</color>
+    <color name="i_am_color_5be">#000005be</color>
+    <color name="i_am_color_5bf">#000005bf</color>
+    <color name="i_am_color_5c0">#000005c0</color>
+    <color name="i_am_color_5c1">#000005c1</color>
+    <color name="i_am_color_5c2">#000005c2</color>
+    <color name="i_am_color_5c3">#000005c3</color>
+    <color name="i_am_color_5c4">#000005c4</color>
+    <color name="i_am_color_5c5">#000005c5</color>
+    <color name="i_am_color_5c6">#000005c6</color>
+    <color name="i_am_color_5c7">#000005c7</color>
+    <color name="i_am_color_5c8">#000005c8</color>
+    <color name="i_am_color_5c9">#000005c9</color>
+    <color name="i_am_color_5ca">#000005ca</color>
+    <color name="i_am_color_5cb">#000005cb</color>
+    <color name="i_am_color_5cc">#000005cc</color>
+    <color name="i_am_color_5cd">#000005cd</color>
+    <color name="i_am_color_5ce">#000005ce</color>
+    <color name="i_am_color_5cf">#000005cf</color>
+    <color name="i_am_color_5d0">#000005d0</color>
+    <color name="i_am_color_5d1">#000005d1</color>
+    <color name="i_am_color_5d2">#000005d2</color>
+    <color name="i_am_color_5d3">#000005d3</color>
+    <color name="i_am_color_5d4">#000005d4</color>
+    <color name="i_am_color_5d5">#000005d5</color>
+    <color name="i_am_color_5d6">#000005d6</color>
+    <color name="i_am_color_5d7">#000005d7</color>
+    <color name="i_am_color_5d8">#000005d8</color>
+    <color name="i_am_color_5d9">#000005d9</color>
+    <color name="i_am_color_5da">#000005da</color>
+    <color name="i_am_color_5db">#000005db</color>
+    <color name="i_am_color_5dc">#000005dc</color>
+    <color name="i_am_color_5dd">#000005dd</color>
+    <color name="i_am_color_5de">#000005de</color>
+    <color name="i_am_color_5df">#000005df</color>
+    <color name="i_am_color_5e0">#000005e0</color>
+    <color name="i_am_color_5e1">#000005e1</color>
+    <color name="i_am_color_5e2">#000005e2</color>
+    <color name="i_am_color_5e3">#000005e3</color>
+    <color name="i_am_color_5e4">#000005e4</color>
+    <color name="i_am_color_5e5">#000005e5</color>
+    <color name="i_am_color_5e6">#000005e6</color>
+    <color name="i_am_color_5e7">#000005e7</color>
+    <color name="i_am_color_5e8">#000005e8</color>
+    <color name="i_am_color_5e9">#000005e9</color>
+    <color name="i_am_color_5ea">#000005ea</color>
+    <color name="i_am_color_5eb">#000005eb</color>
+    <color name="i_am_color_5ec">#000005ec</color>
+    <color name="i_am_color_5ed">#000005ed</color>
+    <color name="i_am_color_5ee">#000005ee</color>
+    <color name="i_am_color_5ef">#000005ef</color>
+    <color name="i_am_color_5f0">#000005f0</color>
+    <color name="i_am_color_5f1">#000005f1</color>
+    <color name="i_am_color_5f2">#000005f2</color>
+    <color name="i_am_color_5f3">#000005f3</color>
+    <color name="i_am_color_5f4">#000005f4</color>
+    <color name="i_am_color_5f5">#000005f5</color>
+    <color name="i_am_color_5f6">#000005f6</color>
+    <color name="i_am_color_5f7">#000005f7</color>
+    <color name="i_am_color_5f8">#000005f8</color>
+    <color name="i_am_color_5f9">#000005f9</color>
+    <color name="i_am_color_5fa">#000005fa</color>
+    <color name="i_am_color_5fb">#000005fb</color>
+    <color name="i_am_color_5fc">#000005fc</color>
+    <color name="i_am_color_5fd">#000005fd</color>
+    <color name="i_am_color_5fe">#000005fe</color>
+    <color name="i_am_color_5ff">#000005ff</color>
+    <color name="i_am_color_600">#00000600</color>
+    <color name="i_am_color_601">#00000601</color>
+    <color name="i_am_color_602">#00000602</color>
+    <color name="i_am_color_603">#00000603</color>
+    <color name="i_am_color_604">#00000604</color>
+    <color name="i_am_color_605">#00000605</color>
+    <color name="i_am_color_606">#00000606</color>
+    <color name="i_am_color_607">#00000607</color>
+    <color name="i_am_color_608">#00000608</color>
+    <color name="i_am_color_609">#00000609</color>
+    <color name="i_am_color_60a">#0000060a</color>
+    <color name="i_am_color_60b">#0000060b</color>
+    <color name="i_am_color_60c">#0000060c</color>
+    <color name="i_am_color_60d">#0000060d</color>
+    <color name="i_am_color_60e">#0000060e</color>
+    <color name="i_am_color_60f">#0000060f</color>
+    <color name="i_am_color_610">#00000610</color>
+    <color name="i_am_color_611">#00000611</color>
+    <color name="i_am_color_612">#00000612</color>
+    <color name="i_am_color_613">#00000613</color>
+    <color name="i_am_color_614">#00000614</color>
+    <color name="i_am_color_615">#00000615</color>
+    <color name="i_am_color_616">#00000616</color>
+    <color name="i_am_color_617">#00000617</color>
+    <color name="i_am_color_618">#00000618</color>
+    <color name="i_am_color_619">#00000619</color>
+    <color name="i_am_color_61a">#0000061a</color>
+    <color name="i_am_color_61b">#0000061b</color>
+    <color name="i_am_color_61c">#0000061c</color>
+    <color name="i_am_color_61d">#0000061d</color>
+    <color name="i_am_color_61e">#0000061e</color>
+    <color name="i_am_color_61f">#0000061f</color>
+    <color name="i_am_color_620">#00000620</color>
+    <color name="i_am_color_621">#00000621</color>
+    <color name="i_am_color_622">#00000622</color>
+    <color name="i_am_color_623">#00000623</color>
+    <color name="i_am_color_624">#00000624</color>
+    <color name="i_am_color_625">#00000625</color>
+    <color name="i_am_color_626">#00000626</color>
+    <color name="i_am_color_627">#00000627</color>
+    <color name="i_am_color_628">#00000628</color>
+    <color name="i_am_color_629">#00000629</color>
+    <color name="i_am_color_62a">#0000062a</color>
+    <color name="i_am_color_62b">#0000062b</color>
+    <color name="i_am_color_62c">#0000062c</color>
+    <color name="i_am_color_62d">#0000062d</color>
+    <color name="i_am_color_62e">#0000062e</color>
+    <color name="i_am_color_62f">#0000062f</color>
+    <color name="i_am_color_630">#00000630</color>
+    <color name="i_am_color_631">#00000631</color>
+    <color name="i_am_color_632">#00000632</color>
+    <color name="i_am_color_633">#00000633</color>
+    <color name="i_am_color_634">#00000634</color>
+    <color name="i_am_color_635">#00000635</color>
+    <color name="i_am_color_636">#00000636</color>
+    <color name="i_am_color_637">#00000637</color>
+    <color name="i_am_color_638">#00000638</color>
+    <color name="i_am_color_639">#00000639</color>
+    <color name="i_am_color_63a">#0000063a</color>
+    <color name="i_am_color_63b">#0000063b</color>
+    <color name="i_am_color_63c">#0000063c</color>
+    <color name="i_am_color_63d">#0000063d</color>
+    <color name="i_am_color_63e">#0000063e</color>
+    <color name="i_am_color_63f">#0000063f</color>
+    <color name="i_am_color_640">#00000640</color>
+    <color name="i_am_color_641">#00000641</color>
+    <color name="i_am_color_642">#00000642</color>
+    <color name="i_am_color_643">#00000643</color>
+    <color name="i_am_color_644">#00000644</color>
+    <color name="i_am_color_645">#00000645</color>
+    <color name="i_am_color_646">#00000646</color>
+    <color name="i_am_color_647">#00000647</color>
+    <color name="i_am_color_648">#00000648</color>
+    <color name="i_am_color_649">#00000649</color>
+    <color name="i_am_color_64a">#0000064a</color>
+    <color name="i_am_color_64b">#0000064b</color>
+    <color name="i_am_color_64c">#0000064c</color>
+    <color name="i_am_color_64d">#0000064d</color>
+    <color name="i_am_color_64e">#0000064e</color>
+    <color name="i_am_color_64f">#0000064f</color>
+    <color name="i_am_color_650">#00000650</color>
+    <color name="i_am_color_651">#00000651</color>
+    <color name="i_am_color_652">#00000652</color>
+    <color name="i_am_color_653">#00000653</color>
+    <color name="i_am_color_654">#00000654</color>
+    <color name="i_am_color_655">#00000655</color>
+    <color name="i_am_color_656">#00000656</color>
+    <color name="i_am_color_657">#00000657</color>
+    <color name="i_am_color_658">#00000658</color>
+    <color name="i_am_color_659">#00000659</color>
+    <color name="i_am_color_65a">#0000065a</color>
+    <color name="i_am_color_65b">#0000065b</color>
+    <color name="i_am_color_65c">#0000065c</color>
+    <color name="i_am_color_65d">#0000065d</color>
+    <color name="i_am_color_65e">#0000065e</color>
+    <color name="i_am_color_65f">#0000065f</color>
+    <color name="i_am_color_660">#00000660</color>
+    <color name="i_am_color_661">#00000661</color>
+    <color name="i_am_color_662">#00000662</color>
+    <color name="i_am_color_663">#00000663</color>
+    <color name="i_am_color_664">#00000664</color>
+    <color name="i_am_color_665">#00000665</color>
+    <color name="i_am_color_666">#00000666</color>
+    <color name="i_am_color_667">#00000667</color>
+    <color name="i_am_color_668">#00000668</color>
+    <color name="i_am_color_669">#00000669</color>
+    <color name="i_am_color_66a">#0000066a</color>
+    <color name="i_am_color_66b">#0000066b</color>
+    <color name="i_am_color_66c">#0000066c</color>
+    <color name="i_am_color_66d">#0000066d</color>
+    <color name="i_am_color_66e">#0000066e</color>
+    <color name="i_am_color_66f">#0000066f</color>
+    <color name="i_am_color_670">#00000670</color>
+    <color name="i_am_color_671">#00000671</color>
+    <color name="i_am_color_672">#00000672</color>
+    <color name="i_am_color_673">#00000673</color>
+    <color name="i_am_color_674">#00000674</color>
+    <color name="i_am_color_675">#00000675</color>
+    <color name="i_am_color_676">#00000676</color>
+    <color name="i_am_color_677">#00000677</color>
+    <color name="i_am_color_678">#00000678</color>
+    <color name="i_am_color_679">#00000679</color>
+    <color name="i_am_color_67a">#0000067a</color>
+    <color name="i_am_color_67b">#0000067b</color>
+    <color name="i_am_color_67c">#0000067c</color>
+    <color name="i_am_color_67d">#0000067d</color>
+    <color name="i_am_color_67e">#0000067e</color>
+    <color name="i_am_color_67f">#0000067f</color>
+    <color name="i_am_color_680">#00000680</color>
+    <color name="i_am_color_681">#00000681</color>
+    <color name="i_am_color_682">#00000682</color>
+    <color name="i_am_color_683">#00000683</color>
+    <color name="i_am_color_684">#00000684</color>
+    <color name="i_am_color_685">#00000685</color>
+    <color name="i_am_color_686">#00000686</color>
+    <color name="i_am_color_687">#00000687</color>
+    <color name="i_am_color_688">#00000688</color>
+    <color name="i_am_color_689">#00000689</color>
+    <color name="i_am_color_68a">#0000068a</color>
+    <color name="i_am_color_68b">#0000068b</color>
+    <color name="i_am_color_68c">#0000068c</color>
+    <color name="i_am_color_68d">#0000068d</color>
+    <color name="i_am_color_68e">#0000068e</color>
+    <color name="i_am_color_68f">#0000068f</color>
+    <color name="i_am_color_690">#00000690</color>
+    <color name="i_am_color_691">#00000691</color>
+    <color name="i_am_color_692">#00000692</color>
+    <color name="i_am_color_693">#00000693</color>
+    <color name="i_am_color_694">#00000694</color>
+    <color name="i_am_color_695">#00000695</color>
+    <color name="i_am_color_696">#00000696</color>
+    <color name="i_am_color_697">#00000697</color>
+    <color name="i_am_color_698">#00000698</color>
+    <color name="i_am_color_699">#00000699</color>
+    <color name="i_am_color_69a">#0000069a</color>
+    <color name="i_am_color_69b">#0000069b</color>
+    <color name="i_am_color_69c">#0000069c</color>
+    <color name="i_am_color_69d">#0000069d</color>
+    <color name="i_am_color_69e">#0000069e</color>
+    <color name="i_am_color_69f">#0000069f</color>
+    <color name="i_am_color_6a0">#000006a0</color>
+    <color name="i_am_color_6a1">#000006a1</color>
+    <color name="i_am_color_6a2">#000006a2</color>
+    <color name="i_am_color_6a3">#000006a3</color>
+    <color name="i_am_color_6a4">#000006a4</color>
+    <color name="i_am_color_6a5">#000006a5</color>
+    <color name="i_am_color_6a6">#000006a6</color>
+    <color name="i_am_color_6a7">#000006a7</color>
+    <color name="i_am_color_6a8">#000006a8</color>
+    <color name="i_am_color_6a9">#000006a9</color>
+    <color name="i_am_color_6aa">#000006aa</color>
+    <color name="i_am_color_6ab">#000006ab</color>
+    <color name="i_am_color_6ac">#000006ac</color>
+    <color name="i_am_color_6ad">#000006ad</color>
+    <color name="i_am_color_6ae">#000006ae</color>
+    <color name="i_am_color_6af">#000006af</color>
+    <color name="i_am_color_6b0">#000006b0</color>
+    <color name="i_am_color_6b1">#000006b1</color>
+    <color name="i_am_color_6b2">#000006b2</color>
+    <color name="i_am_color_6b3">#000006b3</color>
+    <color name="i_am_color_6b4">#000006b4</color>
+    <color name="i_am_color_6b5">#000006b5</color>
+    <color name="i_am_color_6b6">#000006b6</color>
+    <color name="i_am_color_6b7">#000006b7</color>
+    <color name="i_am_color_6b8">#000006b8</color>
+    <color name="i_am_color_6b9">#000006b9</color>
+    <color name="i_am_color_6ba">#000006ba</color>
+    <color name="i_am_color_6bb">#000006bb</color>
+    <color name="i_am_color_6bc">#000006bc</color>
+    <color name="i_am_color_6bd">#000006bd</color>
+    <color name="i_am_color_6be">#000006be</color>
+    <color name="i_am_color_6bf">#000006bf</color>
+    <color name="i_am_color_6c0">#000006c0</color>
+    <color name="i_am_color_6c1">#000006c1</color>
+    <color name="i_am_color_6c2">#000006c2</color>
+    <color name="i_am_color_6c3">#000006c3</color>
+    <color name="i_am_color_6c4">#000006c4</color>
+    <color name="i_am_color_6c5">#000006c5</color>
+    <color name="i_am_color_6c6">#000006c6</color>
+    <color name="i_am_color_6c7">#000006c7</color>
+    <color name="i_am_color_6c8">#000006c8</color>
+    <color name="i_am_color_6c9">#000006c9</color>
+    <color name="i_am_color_6ca">#000006ca</color>
+    <color name="i_am_color_6cb">#000006cb</color>
+    <color name="i_am_color_6cc">#000006cc</color>
+    <color name="i_am_color_6cd">#000006cd</color>
+    <color name="i_am_color_6ce">#000006ce</color>
+    <color name="i_am_color_6cf">#000006cf</color>
+    <color name="i_am_color_6d0">#000006d0</color>
+    <color name="i_am_color_6d1">#000006d1</color>
+    <color name="i_am_color_6d2">#000006d2</color>
+    <color name="i_am_color_6d3">#000006d3</color>
+    <color name="i_am_color_6d4">#000006d4</color>
+    <color name="i_am_color_6d5">#000006d5</color>
+    <color name="i_am_color_6d6">#000006d6</color>
+    <color name="i_am_color_6d7">#000006d7</color>
+    <color name="i_am_color_6d8">#000006d8</color>
+    <color name="i_am_color_6d9">#000006d9</color>
+    <color name="i_am_color_6da">#000006da</color>
+    <color name="i_am_color_6db">#000006db</color>
+    <color name="i_am_color_6dc">#000006dc</color>
+    <color name="i_am_color_6dd">#000006dd</color>
+    <color name="i_am_color_6de">#000006de</color>
+    <color name="i_am_color_6df">#000006df</color>
+    <color name="i_am_color_6e0">#000006e0</color>
+    <color name="i_am_color_6e1">#000006e1</color>
+    <color name="i_am_color_6e2">#000006e2</color>
+    <color name="i_am_color_6e3">#000006e3</color>
+    <color name="i_am_color_6e4">#000006e4</color>
+    <color name="i_am_color_6e5">#000006e5</color>
+    <color name="i_am_color_6e6">#000006e6</color>
+    <color name="i_am_color_6e7">#000006e7</color>
+    <color name="i_am_color_6e8">#000006e8</color>
+    <color name="i_am_color_6e9">#000006e9</color>
+    <color name="i_am_color_6ea">#000006ea</color>
+    <color name="i_am_color_6eb">#000006eb</color>
+    <color name="i_am_color_6ec">#000006ec</color>
+    <color name="i_am_color_6ed">#000006ed</color>
+    <color name="i_am_color_6ee">#000006ee</color>
+    <color name="i_am_color_6ef">#000006ef</color>
+    <color name="i_am_color_6f0">#000006f0</color>
+    <color name="i_am_color_6f1">#000006f1</color>
+    <color name="i_am_color_6f2">#000006f2</color>
+    <color name="i_am_color_6f3">#000006f3</color>
+    <color name="i_am_color_6f4">#000006f4</color>
+    <color name="i_am_color_6f5">#000006f5</color>
+    <color name="i_am_color_6f6">#000006f6</color>
+    <color name="i_am_color_6f7">#000006f7</color>
+    <color name="i_am_color_6f8">#000006f8</color>
+    <color name="i_am_color_6f9">#000006f9</color>
+    <color name="i_am_color_6fa">#000006fa</color>
+    <color name="i_am_color_6fb">#000006fb</color>
+    <color name="i_am_color_6fc">#000006fc</color>
+    <color name="i_am_color_6fd">#000006fd</color>
+    <color name="i_am_color_6fe">#000006fe</color>
+    <color name="i_am_color_6ff">#000006ff</color>
+    <color name="i_am_color_700">#00000700</color>
+    <color name="i_am_color_701">#00000701</color>
+    <color name="i_am_color_702">#00000702</color>
+    <color name="i_am_color_703">#00000703</color>
+    <color name="i_am_color_704">#00000704</color>
+    <color name="i_am_color_705">#00000705</color>
+    <color name="i_am_color_706">#00000706</color>
+    <color name="i_am_color_707">#00000707</color>
+    <color name="i_am_color_708">#00000708</color>
+    <color name="i_am_color_709">#00000709</color>
+    <color name="i_am_color_70a">#0000070a</color>
+    <color name="i_am_color_70b">#0000070b</color>
+    <color name="i_am_color_70c">#0000070c</color>
+    <color name="i_am_color_70d">#0000070d</color>
+    <color name="i_am_color_70e">#0000070e</color>
+    <color name="i_am_color_70f">#0000070f</color>
+    <color name="i_am_color_710">#00000710</color>
+    <color name="i_am_color_711">#00000711</color>
+    <color name="i_am_color_712">#00000712</color>
+    <color name="i_am_color_713">#00000713</color>
+    <color name="i_am_color_714">#00000714</color>
+    <color name="i_am_color_715">#00000715</color>
+    <color name="i_am_color_716">#00000716</color>
+    <color name="i_am_color_717">#00000717</color>
+    <color name="i_am_color_718">#00000718</color>
+    <color name="i_am_color_719">#00000719</color>
+    <color name="i_am_color_71a">#0000071a</color>
+    <color name="i_am_color_71b">#0000071b</color>
+    <color name="i_am_color_71c">#0000071c</color>
+    <color name="i_am_color_71d">#0000071d</color>
+    <color name="i_am_color_71e">#0000071e</color>
+    <color name="i_am_color_71f">#0000071f</color>
+    <color name="i_am_color_720">#00000720</color>
+    <color name="i_am_color_721">#00000721</color>
+    <color name="i_am_color_722">#00000722</color>
+    <color name="i_am_color_723">#00000723</color>
+    <color name="i_am_color_724">#00000724</color>
+    <color name="i_am_color_725">#00000725</color>
+    <color name="i_am_color_726">#00000726</color>
+    <color name="i_am_color_727">#00000727</color>
+    <color name="i_am_color_728">#00000728</color>
+    <color name="i_am_color_729">#00000729</color>
+    <color name="i_am_color_72a">#0000072a</color>
+    <color name="i_am_color_72b">#0000072b</color>
+    <color name="i_am_color_72c">#0000072c</color>
+    <color name="i_am_color_72d">#0000072d</color>
+    <color name="i_am_color_72e">#0000072e</color>
+    <color name="i_am_color_72f">#0000072f</color>
+    <color name="i_am_color_730">#00000730</color>
+    <color name="i_am_color_731">#00000731</color>
+    <color name="i_am_color_732">#00000732</color>
+    <color name="i_am_color_733">#00000733</color>
+    <color name="i_am_color_734">#00000734</color>
+    <color name="i_am_color_735">#00000735</color>
+    <color name="i_am_color_736">#00000736</color>
+    <color name="i_am_color_737">#00000737</color>
+    <color name="i_am_color_738">#00000738</color>
+    <color name="i_am_color_739">#00000739</color>
+    <color name="i_am_color_73a">#0000073a</color>
+    <color name="i_am_color_73b">#0000073b</color>
+    <color name="i_am_color_73c">#0000073c</color>
+    <color name="i_am_color_73d">#0000073d</color>
+    <color name="i_am_color_73e">#0000073e</color>
+    <color name="i_am_color_73f">#0000073f</color>
+    <color name="i_am_color_740">#00000740</color>
+    <color name="i_am_color_741">#00000741</color>
+    <color name="i_am_color_742">#00000742</color>
+    <color name="i_am_color_743">#00000743</color>
+    <color name="i_am_color_744">#00000744</color>
+    <color name="i_am_color_745">#00000745</color>
+    <color name="i_am_color_746">#00000746</color>
+    <color name="i_am_color_747">#00000747</color>
+    <color name="i_am_color_748">#00000748</color>
+    <color name="i_am_color_749">#00000749</color>
+    <color name="i_am_color_74a">#0000074a</color>
+    <color name="i_am_color_74b">#0000074b</color>
+    <color name="i_am_color_74c">#0000074c</color>
+    <color name="i_am_color_74d">#0000074d</color>
+    <color name="i_am_color_74e">#0000074e</color>
+    <color name="i_am_color_74f">#0000074f</color>
+    <color name="i_am_color_750">#00000750</color>
+    <color name="i_am_color_751">#00000751</color>
+    <color name="i_am_color_752">#00000752</color>
+    <color name="i_am_color_753">#00000753</color>
+    <color name="i_am_color_754">#00000754</color>
+    <color name="i_am_color_755">#00000755</color>
+    <color name="i_am_color_756">#00000756</color>
+    <color name="i_am_color_757">#00000757</color>
+    <color name="i_am_color_758">#00000758</color>
+    <color name="i_am_color_759">#00000759</color>
+    <color name="i_am_color_75a">#0000075a</color>
+    <color name="i_am_color_75b">#0000075b</color>
+    <color name="i_am_color_75c">#0000075c</color>
+    <color name="i_am_color_75d">#0000075d</color>
+    <color name="i_am_color_75e">#0000075e</color>
+    <color name="i_am_color_75f">#0000075f</color>
+    <color name="i_am_color_760">#00000760</color>
+    <color name="i_am_color_761">#00000761</color>
+    <color name="i_am_color_762">#00000762</color>
+    <color name="i_am_color_763">#00000763</color>
+    <color name="i_am_color_764">#00000764</color>
+    <color name="i_am_color_765">#00000765</color>
+    <color name="i_am_color_766">#00000766</color>
+    <color name="i_am_color_767">#00000767</color>
+    <color name="i_am_color_768">#00000768</color>
+    <color name="i_am_color_769">#00000769</color>
+    <color name="i_am_color_76a">#0000076a</color>
+    <color name="i_am_color_76b">#0000076b</color>
+    <color name="i_am_color_76c">#0000076c</color>
+    <color name="i_am_color_76d">#0000076d</color>
+    <color name="i_am_color_76e">#0000076e</color>
+    <color name="i_am_color_76f">#0000076f</color>
+    <color name="i_am_color_770">#00000770</color>
+    <color name="i_am_color_771">#00000771</color>
+    <color name="i_am_color_772">#00000772</color>
+    <color name="i_am_color_773">#00000773</color>
+    <color name="i_am_color_774">#00000774</color>
+    <color name="i_am_color_775">#00000775</color>
+    <color name="i_am_color_776">#00000776</color>
+    <color name="i_am_color_777">#00000777</color>
+    <color name="i_am_color_778">#00000778</color>
+    <color name="i_am_color_779">#00000779</color>
+    <color name="i_am_color_77a">#0000077a</color>
+    <color name="i_am_color_77b">#0000077b</color>
+    <color name="i_am_color_77c">#0000077c</color>
+    <color name="i_am_color_77d">#0000077d</color>
+    <color name="i_am_color_77e">#0000077e</color>
+    <color name="i_am_color_77f">#0000077f</color>
+    <color name="i_am_color_780">#00000780</color>
+    <color name="i_am_color_781">#00000781</color>
+    <color name="i_am_color_782">#00000782</color>
+    <color name="i_am_color_783">#00000783</color>
+    <color name="i_am_color_784">#00000784</color>
+    <color name="i_am_color_785">#00000785</color>
+    <color name="i_am_color_786">#00000786</color>
+    <color name="i_am_color_787">#00000787</color>
+    <color name="i_am_color_788">#00000788</color>
+    <color name="i_am_color_789">#00000789</color>
+    <color name="i_am_color_78a">#0000078a</color>
+    <color name="i_am_color_78b">#0000078b</color>
+    <color name="i_am_color_78c">#0000078c</color>
+    <color name="i_am_color_78d">#0000078d</color>
+    <color name="i_am_color_78e">#0000078e</color>
+    <color name="i_am_color_78f">#0000078f</color>
+    <color name="i_am_color_790">#00000790</color>
+    <color name="i_am_color_791">#00000791</color>
+    <color name="i_am_color_792">#00000792</color>
+    <color name="i_am_color_793">#00000793</color>
+    <color name="i_am_color_794">#00000794</color>
+    <color name="i_am_color_795">#00000795</color>
+    <color name="i_am_color_796">#00000796</color>
+    <color name="i_am_color_797">#00000797</color>
+    <color name="i_am_color_798">#00000798</color>
+    <color name="i_am_color_799">#00000799</color>
+    <color name="i_am_color_79a">#0000079a</color>
+    <color name="i_am_color_79b">#0000079b</color>
+    <color name="i_am_color_79c">#0000079c</color>
+    <color name="i_am_color_79d">#0000079d</color>
+    <color name="i_am_color_79e">#0000079e</color>
+    <color name="i_am_color_79f">#0000079f</color>
+    <color name="i_am_color_7a0">#000007a0</color>
+    <color name="i_am_color_7a1">#000007a1</color>
+    <color name="i_am_color_7a2">#000007a2</color>
+    <color name="i_am_color_7a3">#000007a3</color>
+    <color name="i_am_color_7a4">#000007a4</color>
+    <color name="i_am_color_7a5">#000007a5</color>
+    <color name="i_am_color_7a6">#000007a6</color>
+    <color name="i_am_color_7a7">#000007a7</color>
+    <color name="i_am_color_7a8">#000007a8</color>
+    <color name="i_am_color_7a9">#000007a9</color>
+    <color name="i_am_color_7aa">#000007aa</color>
+    <color name="i_am_color_7ab">#000007ab</color>
+    <color name="i_am_color_7ac">#000007ac</color>
+    <color name="i_am_color_7ad">#000007ad</color>
+    <color name="i_am_color_7ae">#000007ae</color>
+    <color name="i_am_color_7af">#000007af</color>
+    <color name="i_am_color_7b0">#000007b0</color>
+    <color name="i_am_color_7b1">#000007b1</color>
+    <color name="i_am_color_7b2">#000007b2</color>
+    <color name="i_am_color_7b3">#000007b3</color>
+    <color name="i_am_color_7b4">#000007b4</color>
+    <color name="i_am_color_7b5">#000007b5</color>
+    <color name="i_am_color_7b6">#000007b6</color>
+    <color name="i_am_color_7b7">#000007b7</color>
+    <color name="i_am_color_7b8">#000007b8</color>
+    <color name="i_am_color_7b9">#000007b9</color>
+    <color name="i_am_color_7ba">#000007ba</color>
+    <color name="i_am_color_7bb">#000007bb</color>
+    <color name="i_am_color_7bc">#000007bc</color>
+    <color name="i_am_color_7bd">#000007bd</color>
+    <color name="i_am_color_7be">#000007be</color>
+    <color name="i_am_color_7bf">#000007bf</color>
+    <color name="i_am_color_7c0">#000007c0</color>
+    <color name="i_am_color_7c1">#000007c1</color>
+    <color name="i_am_color_7c2">#000007c2</color>
+    <color name="i_am_color_7c3">#000007c3</color>
+    <color name="i_am_color_7c4">#000007c4</color>
+    <color name="i_am_color_7c5">#000007c5</color>
+    <color name="i_am_color_7c6">#000007c6</color>
+    <color name="i_am_color_7c7">#000007c7</color>
+    <color name="i_am_color_7c8">#000007c8</color>
+    <color name="i_am_color_7c9">#000007c9</color>
+    <color name="i_am_color_7ca">#000007ca</color>
+    <color name="i_am_color_7cb">#000007cb</color>
+    <color name="i_am_color_7cc">#000007cc</color>
+    <color name="i_am_color_7cd">#000007cd</color>
+    <color name="i_am_color_7ce">#000007ce</color>
+    <color name="i_am_color_7cf">#000007cf</color>
+    <color name="i_am_color_7d0">#000007d0</color>
+    <color name="i_am_color_7d1">#000007d1</color>
+    <color name="i_am_color_7d2">#000007d2</color>
+    <color name="i_am_color_7d3">#000007d3</color>
+    <color name="i_am_color_7d4">#000007d4</color>
+    <color name="i_am_color_7d5">#000007d5</color>
+    <color name="i_am_color_7d6">#000007d6</color>
+    <color name="i_am_color_7d7">#000007d7</color>
+    <color name="i_am_color_7d8">#000007d8</color>
+    <color name="i_am_color_7d9">#000007d9</color>
+    <color name="i_am_color_7da">#000007da</color>
+    <color name="i_am_color_7db">#000007db</color>
+    <color name="i_am_color_7dc">#000007dc</color>
+    <color name="i_am_color_7dd">#000007dd</color>
+    <color name="i_am_color_7de">#000007de</color>
+    <color name="i_am_color_7df">#000007df</color>
+    <color name="i_am_color_7e0">#000007e0</color>
+    <color name="i_am_color_7e1">#000007e1</color>
+    <color name="i_am_color_7e2">#000007e2</color>
+    <color name="i_am_color_7e3">#000007e3</color>
+    <color name="i_am_color_7e4">#000007e4</color>
+    <color name="i_am_color_7e5">#000007e5</color>
+    <color name="i_am_color_7e6">#000007e6</color>
+    <color name="i_am_color_7e7">#000007e7</color>
+    <color name="i_am_color_7e8">#000007e8</color>
+    <color name="i_am_color_7e9">#000007e9</color>
+    <color name="i_am_color_7ea">#000007ea</color>
+    <color name="i_am_color_7eb">#000007eb</color>
+    <color name="i_am_color_7ec">#000007ec</color>
+    <color name="i_am_color_7ed">#000007ed</color>
+    <color name="i_am_color_7ee">#000007ee</color>
+    <color name="i_am_color_7ef">#000007ef</color>
+    <color name="i_am_color_7f0">#000007f0</color>
+    <color name="i_am_color_7f1">#000007f1</color>
+    <color name="i_am_color_7f2">#000007f2</color>
+    <color name="i_am_color_7f3">#000007f3</color>
+    <color name="i_am_color_7f4">#000007f4</color>
+    <color name="i_am_color_7f5">#000007f5</color>
+    <color name="i_am_color_7f6">#000007f6</color>
+    <color name="i_am_color_7f7">#000007f7</color>
+    <color name="i_am_color_7f8">#000007f8</color>
+    <color name="i_am_color_7f9">#000007f9</color>
+    <color name="i_am_color_7fa">#000007fa</color>
+    <color name="i_am_color_7fb">#000007fb</color>
+    <color name="i_am_color_7fc">#000007fc</color>
+    <color name="i_am_color_7fd">#000007fd</color>
+    <color name="i_am_color_7fe">#000007fe</color>
+    <color name="i_am_color_7ff">#000007ff</color>
+    <color name="i_am_color_800">#00000800</color>
+    <color name="i_am_color_801">#00000801</color>
+    <color name="i_am_color_802">#00000802</color>
+    <color name="i_am_color_803">#00000803</color>
+    <color name="i_am_color_804">#00000804</color>
+    <color name="i_am_color_805">#00000805</color>
+    <color name="i_am_color_806">#00000806</color>
+    <color name="i_am_color_807">#00000807</color>
+    <color name="i_am_color_808">#00000808</color>
+    <color name="i_am_color_809">#00000809</color>
+    <color name="i_am_color_80a">#0000080a</color>
+    <color name="i_am_color_80b">#0000080b</color>
+    <color name="i_am_color_80c">#0000080c</color>
+    <color name="i_am_color_80d">#0000080d</color>
+    <color name="i_am_color_80e">#0000080e</color>
+    <color name="i_am_color_80f">#0000080f</color>
+    <color name="i_am_color_810">#00000810</color>
+    <color name="i_am_color_811">#00000811</color>
+    <color name="i_am_color_812">#00000812</color>
+    <color name="i_am_color_813">#00000813</color>
+    <color name="i_am_color_814">#00000814</color>
+    <color name="i_am_color_815">#00000815</color>
+    <color name="i_am_color_816">#00000816</color>
+    <color name="i_am_color_817">#00000817</color>
+    <color name="i_am_color_818">#00000818</color>
+    <color name="i_am_color_819">#00000819</color>
+    <color name="i_am_color_81a">#0000081a</color>
+    <color name="i_am_color_81b">#0000081b</color>
+    <color name="i_am_color_81c">#0000081c</color>
+    <color name="i_am_color_81d">#0000081d</color>
+    <color name="i_am_color_81e">#0000081e</color>
+    <color name="i_am_color_81f">#0000081f</color>
+    <color name="i_am_color_820">#00000820</color>
+    <color name="i_am_color_821">#00000821</color>
+    <color name="i_am_color_822">#00000822</color>
+    <color name="i_am_color_823">#00000823</color>
+    <color name="i_am_color_824">#00000824</color>
+    <color name="i_am_color_825">#00000825</color>
+    <color name="i_am_color_826">#00000826</color>
+    <color name="i_am_color_827">#00000827</color>
+    <color name="i_am_color_828">#00000828</color>
+    <color name="i_am_color_829">#00000829</color>
+    <color name="i_am_color_82a">#0000082a</color>
+    <color name="i_am_color_82b">#0000082b</color>
+    <color name="i_am_color_82c">#0000082c</color>
+    <color name="i_am_color_82d">#0000082d</color>
+    <color name="i_am_color_82e">#0000082e</color>
+    <color name="i_am_color_82f">#0000082f</color>
+    <color name="i_am_color_830">#00000830</color>
+    <color name="i_am_color_831">#00000831</color>
+    <color name="i_am_color_832">#00000832</color>
+    <color name="i_am_color_833">#00000833</color>
+    <color name="i_am_color_834">#00000834</color>
+    <color name="i_am_color_835">#00000835</color>
+    <color name="i_am_color_836">#00000836</color>
+    <color name="i_am_color_837">#00000837</color>
+    <color name="i_am_color_838">#00000838</color>
+    <color name="i_am_color_839">#00000839</color>
+    <color name="i_am_color_83a">#0000083a</color>
+    <color name="i_am_color_83b">#0000083b</color>
+    <color name="i_am_color_83c">#0000083c</color>
+    <color name="i_am_color_83d">#0000083d</color>
+    <color name="i_am_color_83e">#0000083e</color>
+    <color name="i_am_color_83f">#0000083f</color>
+    <color name="i_am_color_840">#00000840</color>
+    <color name="i_am_color_841">#00000841</color>
+    <color name="i_am_color_842">#00000842</color>
+    <color name="i_am_color_843">#00000843</color>
+    <color name="i_am_color_844">#00000844</color>
+    <color name="i_am_color_845">#00000845</color>
+    <color name="i_am_color_846">#00000846</color>
+    <color name="i_am_color_847">#00000847</color>
+    <color name="i_am_color_848">#00000848</color>
+    <color name="i_am_color_849">#00000849</color>
+    <color name="i_am_color_84a">#0000084a</color>
+    <color name="i_am_color_84b">#0000084b</color>
+    <color name="i_am_color_84c">#0000084c</color>
+    <color name="i_am_color_84d">#0000084d</color>
+    <color name="i_am_color_84e">#0000084e</color>
+    <color name="i_am_color_84f">#0000084f</color>
+    <color name="i_am_color_850">#00000850</color>
+    <color name="i_am_color_851">#00000851</color>
+    <color name="i_am_color_852">#00000852</color>
+    <color name="i_am_color_853">#00000853</color>
+    <color name="i_am_color_854">#00000854</color>
+    <color name="i_am_color_855">#00000855</color>
+    <color name="i_am_color_856">#00000856</color>
+    <color name="i_am_color_857">#00000857</color>
+    <color name="i_am_color_858">#00000858</color>
+    <color name="i_am_color_859">#00000859</color>
+    <color name="i_am_color_85a">#0000085a</color>
+    <color name="i_am_color_85b">#0000085b</color>
+    <color name="i_am_color_85c">#0000085c</color>
+    <color name="i_am_color_85d">#0000085d</color>
+    <color name="i_am_color_85e">#0000085e</color>
+    <color name="i_am_color_85f">#0000085f</color>
+    <color name="i_am_color_860">#00000860</color>
+    <color name="i_am_color_861">#00000861</color>
+    <color name="i_am_color_862">#00000862</color>
+    <color name="i_am_color_863">#00000863</color>
+    <color name="i_am_color_864">#00000864</color>
+    <color name="i_am_color_865">#00000865</color>
+    <color name="i_am_color_866">#00000866</color>
+    <color name="i_am_color_867">#00000867</color>
+    <color name="i_am_color_868">#00000868</color>
+    <color name="i_am_color_869">#00000869</color>
+    <color name="i_am_color_86a">#0000086a</color>
+    <color name="i_am_color_86b">#0000086b</color>
+    <color name="i_am_color_86c">#0000086c</color>
+    <color name="i_am_color_86d">#0000086d</color>
+    <color name="i_am_color_86e">#0000086e</color>
+    <color name="i_am_color_86f">#0000086f</color>
+    <color name="i_am_color_870">#00000870</color>
+    <color name="i_am_color_871">#00000871</color>
+    <color name="i_am_color_872">#00000872</color>
+    <color name="i_am_color_873">#00000873</color>
+    <color name="i_am_color_874">#00000874</color>
+    <color name="i_am_color_875">#00000875</color>
+    <color name="i_am_color_876">#00000876</color>
+    <color name="i_am_color_877">#00000877</color>
+    <color name="i_am_color_878">#00000878</color>
+    <color name="i_am_color_879">#00000879</color>
+    <color name="i_am_color_87a">#0000087a</color>
+    <color name="i_am_color_87b">#0000087b</color>
+    <color name="i_am_color_87c">#0000087c</color>
+    <color name="i_am_color_87d">#0000087d</color>
+    <color name="i_am_color_87e">#0000087e</color>
+    <color name="i_am_color_87f">#0000087f</color>
+    <color name="i_am_color_880">#00000880</color>
+    <color name="i_am_color_881">#00000881</color>
+    <color name="i_am_color_882">#00000882</color>
+    <color name="i_am_color_883">#00000883</color>
+    <color name="i_am_color_884">#00000884</color>
+    <color name="i_am_color_885">#00000885</color>
+    <color name="i_am_color_886">#00000886</color>
+    <color name="i_am_color_887">#00000887</color>
+    <color name="i_am_color_888">#00000888</color>
+    <color name="i_am_color_889">#00000889</color>
+    <color name="i_am_color_88a">#0000088a</color>
+    <color name="i_am_color_88b">#0000088b</color>
+    <color name="i_am_color_88c">#0000088c</color>
+    <color name="i_am_color_88d">#0000088d</color>
+    <color name="i_am_color_88e">#0000088e</color>
+    <color name="i_am_color_88f">#0000088f</color>
+    <color name="i_am_color_890">#00000890</color>
+    <color name="i_am_color_891">#00000891</color>
+    <color name="i_am_color_892">#00000892</color>
+    <color name="i_am_color_893">#00000893</color>
+    <color name="i_am_color_894">#00000894</color>
+    <color name="i_am_color_895">#00000895</color>
+    <color name="i_am_color_896">#00000896</color>
+    <color name="i_am_color_897">#00000897</color>
+    <color name="i_am_color_898">#00000898</color>
+    <color name="i_am_color_899">#00000899</color>
+    <color name="i_am_color_89a">#0000089a</color>
+    <color name="i_am_color_89b">#0000089b</color>
+    <color name="i_am_color_89c">#0000089c</color>
+    <color name="i_am_color_89d">#0000089d</color>
+    <color name="i_am_color_89e">#0000089e</color>
+    <color name="i_am_color_89f">#0000089f</color>
+    <color name="i_am_color_8a0">#000008a0</color>
+    <color name="i_am_color_8a1">#000008a1</color>
+    <color name="i_am_color_8a2">#000008a2</color>
+    <color name="i_am_color_8a3">#000008a3</color>
+    <color name="i_am_color_8a4">#000008a4</color>
+    <color name="i_am_color_8a5">#000008a5</color>
+    <color name="i_am_color_8a6">#000008a6</color>
+    <color name="i_am_color_8a7">#000008a7</color>
+    <color name="i_am_color_8a8">#000008a8</color>
+    <color name="i_am_color_8a9">#000008a9</color>
+    <color name="i_am_color_8aa">#000008aa</color>
+    <color name="i_am_color_8ab">#000008ab</color>
+    <color name="i_am_color_8ac">#000008ac</color>
+    <color name="i_am_color_8ad">#000008ad</color>
+    <color name="i_am_color_8ae">#000008ae</color>
+    <color name="i_am_color_8af">#000008af</color>
+    <color name="i_am_color_8b0">#000008b0</color>
+    <color name="i_am_color_8b1">#000008b1</color>
+    <color name="i_am_color_8b2">#000008b2</color>
+    <color name="i_am_color_8b3">#000008b3</color>
+    <color name="i_am_color_8b4">#000008b4</color>
+    <color name="i_am_color_8b5">#000008b5</color>
+    <color name="i_am_color_8b6">#000008b6</color>
+    <color name="i_am_color_8b7">#000008b7</color>
+    <color name="i_am_color_8b8">#000008b8</color>
+    <color name="i_am_color_8b9">#000008b9</color>
+    <color name="i_am_color_8ba">#000008ba</color>
+    <color name="i_am_color_8bb">#000008bb</color>
+    <color name="i_am_color_8bc">#000008bc</color>
+    <color name="i_am_color_8bd">#000008bd</color>
+    <color name="i_am_color_8be">#000008be</color>
+    <color name="i_am_color_8bf">#000008bf</color>
+    <color name="i_am_color_8c0">#000008c0</color>
+    <color name="i_am_color_8c1">#000008c1</color>
+    <color name="i_am_color_8c2">#000008c2</color>
+    <color name="i_am_color_8c3">#000008c3</color>
+    <color name="i_am_color_8c4">#000008c4</color>
+    <color name="i_am_color_8c5">#000008c5</color>
+    <color name="i_am_color_8c6">#000008c6</color>
+    <color name="i_am_color_8c7">#000008c7</color>
+    <color name="i_am_color_8c8">#000008c8</color>
+    <color name="i_am_color_8c9">#000008c9</color>
+    <color name="i_am_color_8ca">#000008ca</color>
+    <color name="i_am_color_8cb">#000008cb</color>
+    <color name="i_am_color_8cc">#000008cc</color>
+    <color name="i_am_color_8cd">#000008cd</color>
+    <color name="i_am_color_8ce">#000008ce</color>
+    <color name="i_am_color_8cf">#000008cf</color>
+    <color name="i_am_color_8d0">#000008d0</color>
+    <color name="i_am_color_8d1">#000008d1</color>
+    <color name="i_am_color_8d2">#000008d2</color>
+    <color name="i_am_color_8d3">#000008d3</color>
+    <color name="i_am_color_8d4">#000008d4</color>
+    <color name="i_am_color_8d5">#000008d5</color>
+    <color name="i_am_color_8d6">#000008d6</color>
+    <color name="i_am_color_8d7">#000008d7</color>
+    <color name="i_am_color_8d8">#000008d8</color>
+    <color name="i_am_color_8d9">#000008d9</color>
+    <color name="i_am_color_8da">#000008da</color>
+    <color name="i_am_color_8db">#000008db</color>
+    <color name="i_am_color_8dc">#000008dc</color>
+    <color name="i_am_color_8dd">#000008dd</color>
+    <color name="i_am_color_8de">#000008de</color>
+    <color name="i_am_color_8df">#000008df</color>
+    <color name="i_am_color_8e0">#000008e0</color>
+    <color name="i_am_color_8e1">#000008e1</color>
+    <color name="i_am_color_8e2">#000008e2</color>
+    <color name="i_am_color_8e3">#000008e3</color>
+    <color name="i_am_color_8e4">#000008e4</color>
+    <color name="i_am_color_8e5">#000008e5</color>
+    <color name="i_am_color_8e6">#000008e6</color>
+    <color name="i_am_color_8e7">#000008e7</color>
+    <color name="i_am_color_8e8">#000008e8</color>
+    <color name="i_am_color_8e9">#000008e9</color>
+    <color name="i_am_color_8ea">#000008ea</color>
+    <color name="i_am_color_8eb">#000008eb</color>
+    <color name="i_am_color_8ec">#000008ec</color>
+    <color name="i_am_color_8ed">#000008ed</color>
+    <color name="i_am_color_8ee">#000008ee</color>
+    <color name="i_am_color_8ef">#000008ef</color>
+    <color name="i_am_color_8f0">#000008f0</color>
+    <color name="i_am_color_8f1">#000008f1</color>
+    <color name="i_am_color_8f2">#000008f2</color>
+    <color name="i_am_color_8f3">#000008f3</color>
+    <color name="i_am_color_8f4">#000008f4</color>
+    <color name="i_am_color_8f5">#000008f5</color>
+    <color name="i_am_color_8f6">#000008f6</color>
+    <color name="i_am_color_8f7">#000008f7</color>
+    <color name="i_am_color_8f8">#000008f8</color>
+    <color name="i_am_color_8f9">#000008f9</color>
+    <color name="i_am_color_8fa">#000008fa</color>
+    <color name="i_am_color_8fb">#000008fb</color>
+    <color name="i_am_color_8fc">#000008fc</color>
+    <color name="i_am_color_8fd">#000008fd</color>
+    <color name="i_am_color_8fe">#000008fe</color>
+    <color name="i_am_color_8ff">#000008ff</color>
+    <color name="i_am_color_900">#00000900</color>
+    <color name="i_am_color_901">#00000901</color>
+    <color name="i_am_color_902">#00000902</color>
+    <color name="i_am_color_903">#00000903</color>
+    <color name="i_am_color_904">#00000904</color>
+    <color name="i_am_color_905">#00000905</color>
+    <color name="i_am_color_906">#00000906</color>
+    <color name="i_am_color_907">#00000907</color>
+    <color name="i_am_color_908">#00000908</color>
+    <color name="i_am_color_909">#00000909</color>
+    <color name="i_am_color_90a">#0000090a</color>
+    <color name="i_am_color_90b">#0000090b</color>
+    <color name="i_am_color_90c">#0000090c</color>
+    <color name="i_am_color_90d">#0000090d</color>
+    <color name="i_am_color_90e">#0000090e</color>
+    <color name="i_am_color_90f">#0000090f</color>
+    <color name="i_am_color_910">#00000910</color>
+    <color name="i_am_color_911">#00000911</color>
+    <color name="i_am_color_912">#00000912</color>
+    <color name="i_am_color_913">#00000913</color>
+    <color name="i_am_color_914">#00000914</color>
+    <color name="i_am_color_915">#00000915</color>
+    <color name="i_am_color_916">#00000916</color>
+    <color name="i_am_color_917">#00000917</color>
+    <color name="i_am_color_918">#00000918</color>
+    <color name="i_am_color_919">#00000919</color>
+    <color name="i_am_color_91a">#0000091a</color>
+    <color name="i_am_color_91b">#0000091b</color>
+    <color name="i_am_color_91c">#0000091c</color>
+    <color name="i_am_color_91d">#0000091d</color>
+    <color name="i_am_color_91e">#0000091e</color>
+    <color name="i_am_color_91f">#0000091f</color>
+    <color name="i_am_color_920">#00000920</color>
+    <color name="i_am_color_921">#00000921</color>
+    <color name="i_am_color_922">#00000922</color>
+    <color name="i_am_color_923">#00000923</color>
+    <color name="i_am_color_924">#00000924</color>
+    <color name="i_am_color_925">#00000925</color>
+    <color name="i_am_color_926">#00000926</color>
+    <color name="i_am_color_927">#00000927</color>
+    <color name="i_am_color_928">#00000928</color>
+    <color name="i_am_color_929">#00000929</color>
+    <color name="i_am_color_92a">#0000092a</color>
+    <color name="i_am_color_92b">#0000092b</color>
+    <color name="i_am_color_92c">#0000092c</color>
+    <color name="i_am_color_92d">#0000092d</color>
+    <color name="i_am_color_92e">#0000092e</color>
+    <color name="i_am_color_92f">#0000092f</color>
+    <color name="i_am_color_930">#00000930</color>
+    <color name="i_am_color_931">#00000931</color>
+    <color name="i_am_color_932">#00000932</color>
+    <color name="i_am_color_933">#00000933</color>
+    <color name="i_am_color_934">#00000934</color>
+    <color name="i_am_color_935">#00000935</color>
+    <color name="i_am_color_936">#00000936</color>
+    <color name="i_am_color_937">#00000937</color>
+    <color name="i_am_color_938">#00000938</color>
+    <color name="i_am_color_939">#00000939</color>
+    <color name="i_am_color_93a">#0000093a</color>
+    <color name="i_am_color_93b">#0000093b</color>
+    <color name="i_am_color_93c">#0000093c</color>
+    <color name="i_am_color_93d">#0000093d</color>
+    <color name="i_am_color_93e">#0000093e</color>
+    <color name="i_am_color_93f">#0000093f</color>
+    <color name="i_am_color_940">#00000940</color>
+    <color name="i_am_color_941">#00000941</color>
+    <color name="i_am_color_942">#00000942</color>
+    <color name="i_am_color_943">#00000943</color>
+    <color name="i_am_color_944">#00000944</color>
+    <color name="i_am_color_945">#00000945</color>
+    <color name="i_am_color_946">#00000946</color>
+    <color name="i_am_color_947">#00000947</color>
+    <color name="i_am_color_948">#00000948</color>
+    <color name="i_am_color_949">#00000949</color>
+    <color name="i_am_color_94a">#0000094a</color>
+    <color name="i_am_color_94b">#0000094b</color>
+    <color name="i_am_color_94c">#0000094c</color>
+    <color name="i_am_color_94d">#0000094d</color>
+    <color name="i_am_color_94e">#0000094e</color>
+    <color name="i_am_color_94f">#0000094f</color>
+    <color name="i_am_color_950">#00000950</color>
+    <color name="i_am_color_951">#00000951</color>
+    <color name="i_am_color_952">#00000952</color>
+    <color name="i_am_color_953">#00000953</color>
+    <color name="i_am_color_954">#00000954</color>
+    <color name="i_am_color_955">#00000955</color>
+    <color name="i_am_color_956">#00000956</color>
+    <color name="i_am_color_957">#00000957</color>
+    <color name="i_am_color_958">#00000958</color>
+    <color name="i_am_color_959">#00000959</color>
+    <color name="i_am_color_95a">#0000095a</color>
+    <color name="i_am_color_95b">#0000095b</color>
+    <color name="i_am_color_95c">#0000095c</color>
+    <color name="i_am_color_95d">#0000095d</color>
+    <color name="i_am_color_95e">#0000095e</color>
+    <color name="i_am_color_95f">#0000095f</color>
+    <color name="i_am_color_960">#00000960</color>
+    <color name="i_am_color_961">#00000961</color>
+    <color name="i_am_color_962">#00000962</color>
+    <color name="i_am_color_963">#00000963</color>
+    <color name="i_am_color_964">#00000964</color>
+    <color name="i_am_color_965">#00000965</color>
+    <color name="i_am_color_966">#00000966</color>
+    <color name="i_am_color_967">#00000967</color>
+    <color name="i_am_color_968">#00000968</color>
+    <color name="i_am_color_969">#00000969</color>
+    <color name="i_am_color_96a">#0000096a</color>
+    <color name="i_am_color_96b">#0000096b</color>
+    <color name="i_am_color_96c">#0000096c</color>
+    <color name="i_am_color_96d">#0000096d</color>
+    <color name="i_am_color_96e">#0000096e</color>
+    <color name="i_am_color_96f">#0000096f</color>
+    <color name="i_am_color_970">#00000970</color>
+    <color name="i_am_color_971">#00000971</color>
+    <color name="i_am_color_972">#00000972</color>
+    <color name="i_am_color_973">#00000973</color>
+    <color name="i_am_color_974">#00000974</color>
+    <color name="i_am_color_975">#00000975</color>
+    <color name="i_am_color_976">#00000976</color>
+    <color name="i_am_color_977">#00000977</color>
+    <color name="i_am_color_978">#00000978</color>
+    <color name="i_am_color_979">#00000979</color>
+    <color name="i_am_color_97a">#0000097a</color>
+    <color name="i_am_color_97b">#0000097b</color>
+    <color name="i_am_color_97c">#0000097c</color>
+    <color name="i_am_color_97d">#0000097d</color>
+    <color name="i_am_color_97e">#0000097e</color>
+    <color name="i_am_color_97f">#0000097f</color>
+    <color name="i_am_color_980">#00000980</color>
+    <color name="i_am_color_981">#00000981</color>
+    <color name="i_am_color_982">#00000982</color>
+    <color name="i_am_color_983">#00000983</color>
+    <color name="i_am_color_984">#00000984</color>
+    <color name="i_am_color_985">#00000985</color>
+    <color name="i_am_color_986">#00000986</color>
+    <color name="i_am_color_987">#00000987</color>
+    <color name="i_am_color_988">#00000988</color>
+    <color name="i_am_color_989">#00000989</color>
+    <color name="i_am_color_98a">#0000098a</color>
+    <color name="i_am_color_98b">#0000098b</color>
+    <color name="i_am_color_98c">#0000098c</color>
+    <color name="i_am_color_98d">#0000098d</color>
+    <color name="i_am_color_98e">#0000098e</color>
+    <color name="i_am_color_98f">#0000098f</color>
+    <color name="i_am_color_990">#00000990</color>
+    <color name="i_am_color_991">#00000991</color>
+    <color name="i_am_color_992">#00000992</color>
+    <color name="i_am_color_993">#00000993</color>
+    <color name="i_am_color_994">#00000994</color>
+    <color name="i_am_color_995">#00000995</color>
+    <color name="i_am_color_996">#00000996</color>
+    <color name="i_am_color_997">#00000997</color>
+    <color name="i_am_color_998">#00000998</color>
+    <color name="i_am_color_999">#00000999</color>
+    <color name="i_am_color_99a">#0000099a</color>
+    <color name="i_am_color_99b">#0000099b</color>
+    <color name="i_am_color_99c">#0000099c</color>
+    <color name="i_am_color_99d">#0000099d</color>
+    <color name="i_am_color_99e">#0000099e</color>
+    <color name="i_am_color_99f">#0000099f</color>
+    <color name="i_am_color_9a0">#000009a0</color>
+    <color name="i_am_color_9a1">#000009a1</color>
+    <color name="i_am_color_9a2">#000009a2</color>
+    <color name="i_am_color_9a3">#000009a3</color>
+    <color name="i_am_color_9a4">#000009a4</color>
+    <color name="i_am_color_9a5">#000009a5</color>
+    <color name="i_am_color_9a6">#000009a6</color>
+    <color name="i_am_color_9a7">#000009a7</color>
+    <color name="i_am_color_9a8">#000009a8</color>
+    <color name="i_am_color_9a9">#000009a9</color>
+    <color name="i_am_color_9aa">#000009aa</color>
+    <color name="i_am_color_9ab">#000009ab</color>
+    <color name="i_am_color_9ac">#000009ac</color>
+    <color name="i_am_color_9ad">#000009ad</color>
+    <color name="i_am_color_9ae">#000009ae</color>
+    <color name="i_am_color_9af">#000009af</color>
+    <color name="i_am_color_9b0">#000009b0</color>
+    <color name="i_am_color_9b1">#000009b1</color>
+    <color name="i_am_color_9b2">#000009b2</color>
+    <color name="i_am_color_9b3">#000009b3</color>
+    <color name="i_am_color_9b4">#000009b4</color>
+    <color name="i_am_color_9b5">#000009b5</color>
+    <color name="i_am_color_9b6">#000009b6</color>
+    <color name="i_am_color_9b7">#000009b7</color>
+    <color name="i_am_color_9b8">#000009b8</color>
+    <color name="i_am_color_9b9">#000009b9</color>
+    <color name="i_am_color_9ba">#000009ba</color>
+    <color name="i_am_color_9bb">#000009bb</color>
+    <color name="i_am_color_9bc">#000009bc</color>
+    <color name="i_am_color_9bd">#000009bd</color>
+    <color name="i_am_color_9be">#000009be</color>
+    <color name="i_am_color_9bf">#000009bf</color>
+    <color name="i_am_color_9c0">#000009c0</color>
+    <color name="i_am_color_9c1">#000009c1</color>
+    <color name="i_am_color_9c2">#000009c2</color>
+    <color name="i_am_color_9c3">#000009c3</color>
+    <color name="i_am_color_9c4">#000009c4</color>
+    <color name="i_am_color_9c5">#000009c5</color>
+    <color name="i_am_color_9c6">#000009c6</color>
+    <color name="i_am_color_9c7">#000009c7</color>
+    <color name="i_am_color_9c8">#000009c8</color>
+    <color name="i_am_color_9c9">#000009c9</color>
+    <color name="i_am_color_9ca">#000009ca</color>
+    <color name="i_am_color_9cb">#000009cb</color>
+    <color name="i_am_color_9cc">#000009cc</color>
+    <color name="i_am_color_9cd">#000009cd</color>
+    <color name="i_am_color_9ce">#000009ce</color>
+    <color name="i_am_color_9cf">#000009cf</color>
+    <color name="i_am_color_9d0">#000009d0</color>
+    <color name="i_am_color_9d1">#000009d1</color>
+    <color name="i_am_color_9d2">#000009d2</color>
+    <color name="i_am_color_9d3">#000009d3</color>
+    <color name="i_am_color_9d4">#000009d4</color>
+    <color name="i_am_color_9d5">#000009d5</color>
+    <color name="i_am_color_9d6">#000009d6</color>
+    <color name="i_am_color_9d7">#000009d7</color>
+    <color name="i_am_color_9d8">#000009d8</color>
+    <color name="i_am_color_9d9">#000009d9</color>
+    <color name="i_am_color_9da">#000009da</color>
+    <color name="i_am_color_9db">#000009db</color>
+    <color name="i_am_color_9dc">#000009dc</color>
+    <color name="i_am_color_9dd">#000009dd</color>
+    <color name="i_am_color_9de">#000009de</color>
+    <color name="i_am_color_9df">#000009df</color>
+    <color name="i_am_color_9e0">#000009e0</color>
+    <color name="i_am_color_9e1">#000009e1</color>
+    <color name="i_am_color_9e2">#000009e2</color>
+    <color name="i_am_color_9e3">#000009e3</color>
+    <color name="i_am_color_9e4">#000009e4</color>
+    <color name="i_am_color_9e5">#000009e5</color>
+    <color name="i_am_color_9e6">#000009e6</color>
+    <color name="i_am_color_9e7">#000009e7</color>
+    <color name="i_am_color_9e8">#000009e8</color>
+    <color name="i_am_color_9e9">#000009e9</color>
+    <color name="i_am_color_9ea">#000009ea</color>
+    <color name="i_am_color_9eb">#000009eb</color>
+    <color name="i_am_color_9ec">#000009ec</color>
+    <color name="i_am_color_9ed">#000009ed</color>
+    <color name="i_am_color_9ee">#000009ee</color>
+    <color name="i_am_color_9ef">#000009ef</color>
+    <color name="i_am_color_9f0">#000009f0</color>
+    <color name="i_am_color_9f1">#000009f1</color>
+    <color name="i_am_color_9f2">#000009f2</color>
+    <color name="i_am_color_9f3">#000009f3</color>
+    <color name="i_am_color_9f4">#000009f4</color>
+    <color name="i_am_color_9f5">#000009f5</color>
+    <color name="i_am_color_9f6">#000009f6</color>
+    <color name="i_am_color_9f7">#000009f7</color>
+    <color name="i_am_color_9f8">#000009f8</color>
+    <color name="i_am_color_9f9">#000009f9</color>
+    <color name="i_am_color_9fa">#000009fa</color>
+    <color name="i_am_color_9fb">#000009fb</color>
+    <color name="i_am_color_9fc">#000009fc</color>
+    <color name="i_am_color_9fd">#000009fd</color>
+    <color name="i_am_color_9fe">#000009fe</color>
+    <color name="i_am_color_9ff">#000009ff</color>
+    <color name="i_am_color_a00">#00000a00</color>
+    <color name="i_am_color_a01">#00000a01</color>
+    <color name="i_am_color_a02">#00000a02</color>
+    <color name="i_am_color_a03">#00000a03</color>
+    <color name="i_am_color_a04">#00000a04</color>
+    <color name="i_am_color_a05">#00000a05</color>
+    <color name="i_am_color_a06">#00000a06</color>
+    <color name="i_am_color_a07">#00000a07</color>
+    <color name="i_am_color_a08">#00000a08</color>
+    <color name="i_am_color_a09">#00000a09</color>
+    <color name="i_am_color_a0a">#00000a0a</color>
+    <color name="i_am_color_a0b">#00000a0b</color>
+    <color name="i_am_color_a0c">#00000a0c</color>
+    <color name="i_am_color_a0d">#00000a0d</color>
+    <color name="i_am_color_a0e">#00000a0e</color>
+    <color name="i_am_color_a0f">#00000a0f</color>
+    <color name="i_am_color_a10">#00000a10</color>
+    <color name="i_am_color_a11">#00000a11</color>
+    <color name="i_am_color_a12">#00000a12</color>
+    <color name="i_am_color_a13">#00000a13</color>
+    <color name="i_am_color_a14">#00000a14</color>
+    <color name="i_am_color_a15">#00000a15</color>
+    <color name="i_am_color_a16">#00000a16</color>
+    <color name="i_am_color_a17">#00000a17</color>
+    <color name="i_am_color_a18">#00000a18</color>
+    <color name="i_am_color_a19">#00000a19</color>
+    <color name="i_am_color_a1a">#00000a1a</color>
+    <color name="i_am_color_a1b">#00000a1b</color>
+    <color name="i_am_color_a1c">#00000a1c</color>
+    <color name="i_am_color_a1d">#00000a1d</color>
+    <color name="i_am_color_a1e">#00000a1e</color>
+    <color name="i_am_color_a1f">#00000a1f</color>
+    <color name="i_am_color_a20">#00000a20</color>
+    <color name="i_am_color_a21">#00000a21</color>
+    <color name="i_am_color_a22">#00000a22</color>
+    <color name="i_am_color_a23">#00000a23</color>
+    <color name="i_am_color_a24">#00000a24</color>
+    <color name="i_am_color_a25">#00000a25</color>
+    <color name="i_am_color_a26">#00000a26</color>
+    <color name="i_am_color_a27">#00000a27</color>
+    <color name="i_am_color_a28">#00000a28</color>
+    <color name="i_am_color_a29">#00000a29</color>
+    <color name="i_am_color_a2a">#00000a2a</color>
+    <color name="i_am_color_a2b">#00000a2b</color>
+    <color name="i_am_color_a2c">#00000a2c</color>
+    <color name="i_am_color_a2d">#00000a2d</color>
+    <color name="i_am_color_a2e">#00000a2e</color>
+    <color name="i_am_color_a2f">#00000a2f</color>
+    <color name="i_am_color_a30">#00000a30</color>
+    <color name="i_am_color_a31">#00000a31</color>
+    <color name="i_am_color_a32">#00000a32</color>
+    <color name="i_am_color_a33">#00000a33</color>
+    <color name="i_am_color_a34">#00000a34</color>
+    <color name="i_am_color_a35">#00000a35</color>
+    <color name="i_am_color_a36">#00000a36</color>
+    <color name="i_am_color_a37">#00000a37</color>
+    <color name="i_am_color_a38">#00000a38</color>
+    <color name="i_am_color_a39">#00000a39</color>
+    <color name="i_am_color_a3a">#00000a3a</color>
+    <color name="i_am_color_a3b">#00000a3b</color>
+    <color name="i_am_color_a3c">#00000a3c</color>
+    <color name="i_am_color_a3d">#00000a3d</color>
+    <color name="i_am_color_a3e">#00000a3e</color>
+    <color name="i_am_color_a3f">#00000a3f</color>
+    <color name="i_am_color_a40">#00000a40</color>
+    <color name="i_am_color_a41">#00000a41</color>
+    <color name="i_am_color_a42">#00000a42</color>
+    <color name="i_am_color_a43">#00000a43</color>
+    <color name="i_am_color_a44">#00000a44</color>
+    <color name="i_am_color_a45">#00000a45</color>
+    <color name="i_am_color_a46">#00000a46</color>
+    <color name="i_am_color_a47">#00000a47</color>
+    <color name="i_am_color_a48">#00000a48</color>
+    <color name="i_am_color_a49">#00000a49</color>
+    <color name="i_am_color_a4a">#00000a4a</color>
+    <color name="i_am_color_a4b">#00000a4b</color>
+    <color name="i_am_color_a4c">#00000a4c</color>
+    <color name="i_am_color_a4d">#00000a4d</color>
+    <color name="i_am_color_a4e">#00000a4e</color>
+    <color name="i_am_color_a4f">#00000a4f</color>
+    <color name="i_am_color_a50">#00000a50</color>
+    <color name="i_am_color_a51">#00000a51</color>
+    <color name="i_am_color_a52">#00000a52</color>
+    <color name="i_am_color_a53">#00000a53</color>
+    <color name="i_am_color_a54">#00000a54</color>
+    <color name="i_am_color_a55">#00000a55</color>
+    <color name="i_am_color_a56">#00000a56</color>
+    <color name="i_am_color_a57">#00000a57</color>
+    <color name="i_am_color_a58">#00000a58</color>
+    <color name="i_am_color_a59">#00000a59</color>
+    <color name="i_am_color_a5a">#00000a5a</color>
+    <color name="i_am_color_a5b">#00000a5b</color>
+    <color name="i_am_color_a5c">#00000a5c</color>
+    <color name="i_am_color_a5d">#00000a5d</color>
+    <color name="i_am_color_a5e">#00000a5e</color>
+    <color name="i_am_color_a5f">#00000a5f</color>
+    <color name="i_am_color_a60">#00000a60</color>
+    <color name="i_am_color_a61">#00000a61</color>
+    <color name="i_am_color_a62">#00000a62</color>
+    <color name="i_am_color_a63">#00000a63</color>
+    <color name="i_am_color_a64">#00000a64</color>
+    <color name="i_am_color_a65">#00000a65</color>
+    <color name="i_am_color_a66">#00000a66</color>
+    <color name="i_am_color_a67">#00000a67</color>
+    <color name="i_am_color_a68">#00000a68</color>
+    <color name="i_am_color_a69">#00000a69</color>
+    <color name="i_am_color_a6a">#00000a6a</color>
+    <color name="i_am_color_a6b">#00000a6b</color>
+    <color name="i_am_color_a6c">#00000a6c</color>
+    <color name="i_am_color_a6d">#00000a6d</color>
+    <color name="i_am_color_a6e">#00000a6e</color>
+    <color name="i_am_color_a6f">#00000a6f</color>
+    <color name="i_am_color_a70">#00000a70</color>
+    <color name="i_am_color_a71">#00000a71</color>
+    <color name="i_am_color_a72">#00000a72</color>
+    <color name="i_am_color_a73">#00000a73</color>
+    <color name="i_am_color_a74">#00000a74</color>
+    <color name="i_am_color_a75">#00000a75</color>
+    <color name="i_am_color_a76">#00000a76</color>
+    <color name="i_am_color_a77">#00000a77</color>
+    <color name="i_am_color_a78">#00000a78</color>
+    <color name="i_am_color_a79">#00000a79</color>
+    <color name="i_am_color_a7a">#00000a7a</color>
+    <color name="i_am_color_a7b">#00000a7b</color>
+    <color name="i_am_color_a7c">#00000a7c</color>
+    <color name="i_am_color_a7d">#00000a7d</color>
+    <color name="i_am_color_a7e">#00000a7e</color>
+    <color name="i_am_color_a7f">#00000a7f</color>
+    <color name="i_am_color_a80">#00000a80</color>
+    <color name="i_am_color_a81">#00000a81</color>
+    <color name="i_am_color_a82">#00000a82</color>
+    <color name="i_am_color_a83">#00000a83</color>
+    <color name="i_am_color_a84">#00000a84</color>
+    <color name="i_am_color_a85">#00000a85</color>
+    <color name="i_am_color_a86">#00000a86</color>
+    <color name="i_am_color_a87">#00000a87</color>
+    <color name="i_am_color_a88">#00000a88</color>
+    <color name="i_am_color_a89">#00000a89</color>
+    <color name="i_am_color_a8a">#00000a8a</color>
+    <color name="i_am_color_a8b">#00000a8b</color>
+    <color name="i_am_color_a8c">#00000a8c</color>
+    <color name="i_am_color_a8d">#00000a8d</color>
+    <color name="i_am_color_a8e">#00000a8e</color>
+    <color name="i_am_color_a8f">#00000a8f</color>
+    <color name="i_am_color_a90">#00000a90</color>
+    <color name="i_am_color_a91">#00000a91</color>
+    <color name="i_am_color_a92">#00000a92</color>
+    <color name="i_am_color_a93">#00000a93</color>
+    <color name="i_am_color_a94">#00000a94</color>
+    <color name="i_am_color_a95">#00000a95</color>
+    <color name="i_am_color_a96">#00000a96</color>
+    <color name="i_am_color_a97">#00000a97</color>
+    <color name="i_am_color_a98">#00000a98</color>
+    <color name="i_am_color_a99">#00000a99</color>
+    <color name="i_am_color_a9a">#00000a9a</color>
+    <color name="i_am_color_a9b">#00000a9b</color>
+    <color name="i_am_color_a9c">#00000a9c</color>
+    <color name="i_am_color_a9d">#00000a9d</color>
+    <color name="i_am_color_a9e">#00000a9e</color>
+    <color name="i_am_color_a9f">#00000a9f</color>
+    <color name="i_am_color_aa0">#00000aa0</color>
+    <color name="i_am_color_aa1">#00000aa1</color>
+    <color name="i_am_color_aa2">#00000aa2</color>
+    <color name="i_am_color_aa3">#00000aa3</color>
+    <color name="i_am_color_aa4">#00000aa4</color>
+    <color name="i_am_color_aa5">#00000aa5</color>
+    <color name="i_am_color_aa6">#00000aa6</color>
+    <color name="i_am_color_aa7">#00000aa7</color>
+    <color name="i_am_color_aa8">#00000aa8</color>
+    <color name="i_am_color_aa9">#00000aa9</color>
+    <color name="i_am_color_aaa">#00000aaa</color>
+    <color name="i_am_color_aab">#00000aab</color>
+    <color name="i_am_color_aac">#00000aac</color>
+    <color name="i_am_color_aad">#00000aad</color>
+    <color name="i_am_color_aae">#00000aae</color>
+    <color name="i_am_color_aaf">#00000aaf</color>
+    <color name="i_am_color_ab0">#00000ab0</color>
+    <color name="i_am_color_ab1">#00000ab1</color>
+    <color name="i_am_color_ab2">#00000ab2</color>
+    <color name="i_am_color_ab3">#00000ab3</color>
+    <color name="i_am_color_ab4">#00000ab4</color>
+    <color name="i_am_color_ab5">#00000ab5</color>
+    <color name="i_am_color_ab6">#00000ab6</color>
+    <color name="i_am_color_ab7">#00000ab7</color>
+    <color name="i_am_color_ab8">#00000ab8</color>
+    <color name="i_am_color_ab9">#00000ab9</color>
+    <color name="i_am_color_aba">#00000aba</color>
+    <color name="i_am_color_abb">#00000abb</color>
+    <color name="i_am_color_abc">#00000abc</color>
+    <color name="i_am_color_abd">#00000abd</color>
+    <color name="i_am_color_abe">#00000abe</color>
+    <color name="i_am_color_abf">#00000abf</color>
+    <color name="i_am_color_ac0">#00000ac0</color>
+    <color name="i_am_color_ac1">#00000ac1</color>
+    <color name="i_am_color_ac2">#00000ac2</color>
+    <color name="i_am_color_ac3">#00000ac3</color>
+    <color name="i_am_color_ac4">#00000ac4</color>
+    <color name="i_am_color_ac5">#00000ac5</color>
+    <color name="i_am_color_ac6">#00000ac6</color>
+    <color name="i_am_color_ac7">#00000ac7</color>
+    <color name="i_am_color_ac8">#00000ac8</color>
+    <color name="i_am_color_ac9">#00000ac9</color>
+    <color name="i_am_color_aca">#00000aca</color>
+    <color name="i_am_color_acb">#00000acb</color>
+    <color name="i_am_color_acc">#00000acc</color>
+    <color name="i_am_color_acd">#00000acd</color>
+    <color name="i_am_color_ace">#00000ace</color>
+    <color name="i_am_color_acf">#00000acf</color>
+    <color name="i_am_color_ad0">#00000ad0</color>
+    <color name="i_am_color_ad1">#00000ad1</color>
+    <color name="i_am_color_ad2">#00000ad2</color>
+    <color name="i_am_color_ad3">#00000ad3</color>
+    <color name="i_am_color_ad4">#00000ad4</color>
+    <color name="i_am_color_ad5">#00000ad5</color>
+    <color name="i_am_color_ad6">#00000ad6</color>
+    <color name="i_am_color_ad7">#00000ad7</color>
+    <color name="i_am_color_ad8">#00000ad8</color>
+    <color name="i_am_color_ad9">#00000ad9</color>
+    <color name="i_am_color_ada">#00000ada</color>
+    <color name="i_am_color_adb">#00000adb</color>
+    <color name="i_am_color_adc">#00000adc</color>
+    <color name="i_am_color_add">#00000add</color>
+    <color name="i_am_color_ade">#00000ade</color>
+    <color name="i_am_color_adf">#00000adf</color>
+    <color name="i_am_color_ae0">#00000ae0</color>
+    <color name="i_am_color_ae1">#00000ae1</color>
+    <color name="i_am_color_ae2">#00000ae2</color>
+    <color name="i_am_color_ae3">#00000ae3</color>
+    <color name="i_am_color_ae4">#00000ae4</color>
+    <color name="i_am_color_ae5">#00000ae5</color>
+    <color name="i_am_color_ae6">#00000ae6</color>
+    <color name="i_am_color_ae7">#00000ae7</color>
+    <color name="i_am_color_ae8">#00000ae8</color>
+    <color name="i_am_color_ae9">#00000ae9</color>
+    <color name="i_am_color_aea">#00000aea</color>
+    <color name="i_am_color_aeb">#00000aeb</color>
+    <color name="i_am_color_aec">#00000aec</color>
+    <color name="i_am_color_aed">#00000aed</color>
+    <color name="i_am_color_aee">#00000aee</color>
+    <color name="i_am_color_aef">#00000aef</color>
+    <color name="i_am_color_af0">#00000af0</color>
+    <color name="i_am_color_af1">#00000af1</color>
+    <color name="i_am_color_af2">#00000af2</color>
+    <color name="i_am_color_af3">#00000af3</color>
+    <color name="i_am_color_af4">#00000af4</color>
+    <color name="i_am_color_af5">#00000af5</color>
+    <color name="i_am_color_af6">#00000af6</color>
+    <color name="i_am_color_af7">#00000af7</color>
+    <color name="i_am_color_af8">#00000af8</color>
+    <color name="i_am_color_af9">#00000af9</color>
+    <color name="i_am_color_afa">#00000afa</color>
+    <color name="i_am_color_afb">#00000afb</color>
+    <color name="i_am_color_afc">#00000afc</color>
+    <color name="i_am_color_afd">#00000afd</color>
+    <color name="i_am_color_afe">#00000afe</color>
+    <color name="i_am_color_aff">#00000aff</color>
+    <color name="i_am_color_b00">#00000b00</color>
+    <color name="i_am_color_b01">#00000b01</color>
+    <color name="i_am_color_b02">#00000b02</color>
+    <color name="i_am_color_b03">#00000b03</color>
+    <color name="i_am_color_b04">#00000b04</color>
+    <color name="i_am_color_b05">#00000b05</color>
+    <color name="i_am_color_b06">#00000b06</color>
+    <color name="i_am_color_b07">#00000b07</color>
+    <color name="i_am_color_b08">#00000b08</color>
+    <color name="i_am_color_b09">#00000b09</color>
+    <color name="i_am_color_b0a">#00000b0a</color>
+    <color name="i_am_color_b0b">#00000b0b</color>
+    <color name="i_am_color_b0c">#00000b0c</color>
+    <color name="i_am_color_b0d">#00000b0d</color>
+    <color name="i_am_color_b0e">#00000b0e</color>
+    <color name="i_am_color_b0f">#00000b0f</color>
+    <color name="i_am_color_b10">#00000b10</color>
+    <color name="i_am_color_b11">#00000b11</color>
+    <color name="i_am_color_b12">#00000b12</color>
+    <color name="i_am_color_b13">#00000b13</color>
+    <color name="i_am_color_b14">#00000b14</color>
+    <color name="i_am_color_b15">#00000b15</color>
+    <color name="i_am_color_b16">#00000b16</color>
+    <color name="i_am_color_b17">#00000b17</color>
+    <color name="i_am_color_b18">#00000b18</color>
+    <color name="i_am_color_b19">#00000b19</color>
+    <color name="i_am_color_b1a">#00000b1a</color>
+    <color name="i_am_color_b1b">#00000b1b</color>
+    <color name="i_am_color_b1c">#00000b1c</color>
+    <color name="i_am_color_b1d">#00000b1d</color>
+    <color name="i_am_color_b1e">#00000b1e</color>
+    <color name="i_am_color_b1f">#00000b1f</color>
+    <color name="i_am_color_b20">#00000b20</color>
+    <color name="i_am_color_b21">#00000b21</color>
+    <color name="i_am_color_b22">#00000b22</color>
+    <color name="i_am_color_b23">#00000b23</color>
+    <color name="i_am_color_b24">#00000b24</color>
+    <color name="i_am_color_b25">#00000b25</color>
+    <color name="i_am_color_b26">#00000b26</color>
+    <color name="i_am_color_b27">#00000b27</color>
+    <color name="i_am_color_b28">#00000b28</color>
+    <color name="i_am_color_b29">#00000b29</color>
+    <color name="i_am_color_b2a">#00000b2a</color>
+    <color name="i_am_color_b2b">#00000b2b</color>
+    <color name="i_am_color_b2c">#00000b2c</color>
+    <color name="i_am_color_b2d">#00000b2d</color>
+    <color name="i_am_color_b2e">#00000b2e</color>
+    <color name="i_am_color_b2f">#00000b2f</color>
+    <color name="i_am_color_b30">#00000b30</color>
+    <color name="i_am_color_b31">#00000b31</color>
+    <color name="i_am_color_b32">#00000b32</color>
+    <color name="i_am_color_b33">#00000b33</color>
+    <color name="i_am_color_b34">#00000b34</color>
+    <color name="i_am_color_b35">#00000b35</color>
+    <color name="i_am_color_b36">#00000b36</color>
+    <color name="i_am_color_b37">#00000b37</color>
+    <color name="i_am_color_b38">#00000b38</color>
+    <color name="i_am_color_b39">#00000b39</color>
+    <color name="i_am_color_b3a">#00000b3a</color>
+    <color name="i_am_color_b3b">#00000b3b</color>
+    <color name="i_am_color_b3c">#00000b3c</color>
+    <color name="i_am_color_b3d">#00000b3d</color>
+    <color name="i_am_color_b3e">#00000b3e</color>
+    <color name="i_am_color_b3f">#00000b3f</color>
+    <color name="i_am_color_b40">#00000b40</color>
+    <color name="i_am_color_b41">#00000b41</color>
+    <color name="i_am_color_b42">#00000b42</color>
+    <color name="i_am_color_b43">#00000b43</color>
+    <color name="i_am_color_b44">#00000b44</color>
+    <color name="i_am_color_b45">#00000b45</color>
+    <color name="i_am_color_b46">#00000b46</color>
+    <color name="i_am_color_b47">#00000b47</color>
+    <color name="i_am_color_b48">#00000b48</color>
+    <color name="i_am_color_b49">#00000b49</color>
+    <color name="i_am_color_b4a">#00000b4a</color>
+    <color name="i_am_color_b4b">#00000b4b</color>
+    <color name="i_am_color_b4c">#00000b4c</color>
+    <color name="i_am_color_b4d">#00000b4d</color>
+    <color name="i_am_color_b4e">#00000b4e</color>
+    <color name="i_am_color_b4f">#00000b4f</color>
+    <color name="i_am_color_b50">#00000b50</color>
+    <color name="i_am_color_b51">#00000b51</color>
+    <color name="i_am_color_b52">#00000b52</color>
+    <color name="i_am_color_b53">#00000b53</color>
+    <color name="i_am_color_b54">#00000b54</color>
+    <color name="i_am_color_b55">#00000b55</color>
+    <color name="i_am_color_b56">#00000b56</color>
+    <color name="i_am_color_b57">#00000b57</color>
+    <color name="i_am_color_b58">#00000b58</color>
+    <color name="i_am_color_b59">#00000b59</color>
+    <color name="i_am_color_b5a">#00000b5a</color>
+    <color name="i_am_color_b5b">#00000b5b</color>
+    <color name="i_am_color_b5c">#00000b5c</color>
+    <color name="i_am_color_b5d">#00000b5d</color>
+    <color name="i_am_color_b5e">#00000b5e</color>
+    <color name="i_am_color_b5f">#00000b5f</color>
+    <color name="i_am_color_b60">#00000b60</color>
+    <color name="i_am_color_b61">#00000b61</color>
+    <color name="i_am_color_b62">#00000b62</color>
+    <color name="i_am_color_b63">#00000b63</color>
+    <color name="i_am_color_b64">#00000b64</color>
+    <color name="i_am_color_b65">#00000b65</color>
+    <color name="i_am_color_b66">#00000b66</color>
+    <color name="i_am_color_b67">#00000b67</color>
+    <color name="i_am_color_b68">#00000b68</color>
+    <color name="i_am_color_b69">#00000b69</color>
+    <color name="i_am_color_b6a">#00000b6a</color>
+    <color name="i_am_color_b6b">#00000b6b</color>
+    <color name="i_am_color_b6c">#00000b6c</color>
+    <color name="i_am_color_b6d">#00000b6d</color>
+    <color name="i_am_color_b6e">#00000b6e</color>
+    <color name="i_am_color_b6f">#00000b6f</color>
+    <color name="i_am_color_b70">#00000b70</color>
+    <color name="i_am_color_b71">#00000b71</color>
+    <color name="i_am_color_b72">#00000b72</color>
+    <color name="i_am_color_b73">#00000b73</color>
+    <color name="i_am_color_b74">#00000b74</color>
+    <color name="i_am_color_b75">#00000b75</color>
+    <color name="i_am_color_b76">#00000b76</color>
+    <color name="i_am_color_b77">#00000b77</color>
+    <color name="i_am_color_b78">#00000b78</color>
+    <color name="i_am_color_b79">#00000b79</color>
+    <color name="i_am_color_b7a">#00000b7a</color>
+    <color name="i_am_color_b7b">#00000b7b</color>
+    <color name="i_am_color_b7c">#00000b7c</color>
+    <color name="i_am_color_b7d">#00000b7d</color>
+    <color name="i_am_color_b7e">#00000b7e</color>
+    <color name="i_am_color_b7f">#00000b7f</color>
+    <color name="i_am_color_b80">#00000b80</color>
+    <color name="i_am_color_b81">#00000b81</color>
+    <color name="i_am_color_b82">#00000b82</color>
+    <color name="i_am_color_b83">#00000b83</color>
+    <color name="i_am_color_b84">#00000b84</color>
+    <color name="i_am_color_b85">#00000b85</color>
+    <color name="i_am_color_b86">#00000b86</color>
+    <color name="i_am_color_b87">#00000b87</color>
+    <color name="i_am_color_b88">#00000b88</color>
+    <color name="i_am_color_b89">#00000b89</color>
+    <color name="i_am_color_b8a">#00000b8a</color>
+    <color name="i_am_color_b8b">#00000b8b</color>
+    <color name="i_am_color_b8c">#00000b8c</color>
+    <color name="i_am_color_b8d">#00000b8d</color>
+    <color name="i_am_color_b8e">#00000b8e</color>
+    <color name="i_am_color_b8f">#00000b8f</color>
+    <color name="i_am_color_b90">#00000b90</color>
+    <color name="i_am_color_b91">#00000b91</color>
+    <color name="i_am_color_b92">#00000b92</color>
+    <color name="i_am_color_b93">#00000b93</color>
+    <color name="i_am_color_b94">#00000b94</color>
+    <color name="i_am_color_b95">#00000b95</color>
+    <color name="i_am_color_b96">#00000b96</color>
+    <color name="i_am_color_b97">#00000b97</color>
+    <color name="i_am_color_b98">#00000b98</color>
+    <color name="i_am_color_b99">#00000b99</color>
+    <color name="i_am_color_b9a">#00000b9a</color>
+    <color name="i_am_color_b9b">#00000b9b</color>
+    <color name="i_am_color_b9c">#00000b9c</color>
+    <color name="i_am_color_b9d">#00000b9d</color>
+    <color name="i_am_color_b9e">#00000b9e</color>
+    <color name="i_am_color_b9f">#00000b9f</color>
+    <color name="i_am_color_ba0">#00000ba0</color>
+    <color name="i_am_color_ba1">#00000ba1</color>
+    <color name="i_am_color_ba2">#00000ba2</color>
+    <color name="i_am_color_ba3">#00000ba3</color>
+    <color name="i_am_color_ba4">#00000ba4</color>
+    <color name="i_am_color_ba5">#00000ba5</color>
+    <color name="i_am_color_ba6">#00000ba6</color>
+    <color name="i_am_color_ba7">#00000ba7</color>
+    <color name="i_am_color_ba8">#00000ba8</color>
+    <color name="i_am_color_ba9">#00000ba9</color>
+    <color name="i_am_color_baa">#00000baa</color>
+    <color name="i_am_color_bab">#00000bab</color>
+    <color name="i_am_color_bac">#00000bac</color>
+    <color name="i_am_color_bad">#00000bad</color>
+    <color name="i_am_color_bae">#00000bae</color>
+    <color name="i_am_color_baf">#00000baf</color>
+    <color name="i_am_color_bb0">#00000bb0</color>
+    <color name="i_am_color_bb1">#00000bb1</color>
+    <color name="i_am_color_bb2">#00000bb2</color>
+    <color name="i_am_color_bb3">#00000bb3</color>
+    <color name="i_am_color_bb4">#00000bb4</color>
+    <color name="i_am_color_bb5">#00000bb5</color>
+    <color name="i_am_color_bb6">#00000bb6</color>
+    <color name="i_am_color_bb7">#00000bb7</color>
+    <color name="i_am_color_bb8">#00000bb8</color>
+    <color name="i_am_color_bb9">#00000bb9</color>
+    <color name="i_am_color_bba">#00000bba</color>
+    <color name="i_am_color_bbb">#00000bbb</color>
+    <color name="i_am_color_bbc">#00000bbc</color>
+    <color name="i_am_color_bbd">#00000bbd</color>
+    <color name="i_am_color_bbe">#00000bbe</color>
+    <color name="i_am_color_bbf">#00000bbf</color>
+    <color name="i_am_color_bc0">#00000bc0</color>
+    <color name="i_am_color_bc1">#00000bc1</color>
+    <color name="i_am_color_bc2">#00000bc2</color>
+    <color name="i_am_color_bc3">#00000bc3</color>
+    <color name="i_am_color_bc4">#00000bc4</color>
+    <color name="i_am_color_bc5">#00000bc5</color>
+    <color name="i_am_color_bc6">#00000bc6</color>
+    <color name="i_am_color_bc7">#00000bc7</color>
+    <color name="i_am_color_bc8">#00000bc8</color>
+    <color name="i_am_color_bc9">#00000bc9</color>
+    <color name="i_am_color_bca">#00000bca</color>
+    <color name="i_am_color_bcb">#00000bcb</color>
+    <color name="i_am_color_bcc">#00000bcc</color>
+    <color name="i_am_color_bcd">#00000bcd</color>
+    <color name="i_am_color_bce">#00000bce</color>
+    <color name="i_am_color_bcf">#00000bcf</color>
+    <color name="i_am_color_bd0">#00000bd0</color>
+    <color name="i_am_color_bd1">#00000bd1</color>
+    <color name="i_am_color_bd2">#00000bd2</color>
+    <color name="i_am_color_bd3">#00000bd3</color>
+    <color name="i_am_color_bd4">#00000bd4</color>
+    <color name="i_am_color_bd5">#00000bd5</color>
+    <color name="i_am_color_bd6">#00000bd6</color>
+    <color name="i_am_color_bd7">#00000bd7</color>
+    <color name="i_am_color_bd8">#00000bd8</color>
+    <color name="i_am_color_bd9">#00000bd9</color>
+    <color name="i_am_color_bda">#00000bda</color>
+    <color name="i_am_color_bdb">#00000bdb</color>
+    <color name="i_am_color_bdc">#00000bdc</color>
+    <color name="i_am_color_bdd">#00000bdd</color>
+    <color name="i_am_color_bde">#00000bde</color>
+    <color name="i_am_color_bdf">#00000bdf</color>
+    <color name="i_am_color_be0">#00000be0</color>
+    <color name="i_am_color_be1">#00000be1</color>
+    <color name="i_am_color_be2">#00000be2</color>
+    <color name="i_am_color_be3">#00000be3</color>
+    <color name="i_am_color_be4">#00000be4</color>
+    <color name="i_am_color_be5">#00000be5</color>
+    <color name="i_am_color_be6">#00000be6</color>
+    <color name="i_am_color_be7">#00000be7</color>
+    <color name="i_am_color_be8">#00000be8</color>
+    <color name="i_am_color_be9">#00000be9</color>
+    <color name="i_am_color_bea">#00000bea</color>
+    <color name="i_am_color_beb">#00000beb</color>
+    <color name="i_am_color_bec">#00000bec</color>
+    <color name="i_am_color_bed">#00000bed</color>
+    <color name="i_am_color_bee">#00000bee</color>
+    <color name="i_am_color_bef">#00000bef</color>
+    <color name="i_am_color_bf0">#00000bf0</color>
+    <color name="i_am_color_bf1">#00000bf1</color>
+    <color name="i_am_color_bf2">#00000bf2</color>
+    <color name="i_am_color_bf3">#00000bf3</color>
+    <color name="i_am_color_bf4">#00000bf4</color>
+    <color name="i_am_color_bf5">#00000bf5</color>
+    <color name="i_am_color_bf6">#00000bf6</color>
+    <color name="i_am_color_bf7">#00000bf7</color>
+    <color name="i_am_color_bf8">#00000bf8</color>
+    <color name="i_am_color_bf9">#00000bf9</color>
+    <color name="i_am_color_bfa">#00000bfa</color>
+    <color name="i_am_color_bfb">#00000bfb</color>
+    <color name="i_am_color_bfc">#00000bfc</color>
+    <color name="i_am_color_bfd">#00000bfd</color>
+    <color name="i_am_color_bfe">#00000bfe</color>
+    <color name="i_am_color_bff">#00000bff</color>
+    <color name="i_am_color_c00">#00000c00</color>
+    <color name="i_am_color_c01">#00000c01</color>
+    <color name="i_am_color_c02">#00000c02</color>
+    <color name="i_am_color_c03">#00000c03</color>
+    <color name="i_am_color_c04">#00000c04</color>
+    <color name="i_am_color_c05">#00000c05</color>
+    <color name="i_am_color_c06">#00000c06</color>
+    <color name="i_am_color_c07">#00000c07</color>
+    <color name="i_am_color_c08">#00000c08</color>
+    <color name="i_am_color_c09">#00000c09</color>
+    <color name="i_am_color_c0a">#00000c0a</color>
+    <color name="i_am_color_c0b">#00000c0b</color>
+    <color name="i_am_color_c0c">#00000c0c</color>
+    <color name="i_am_color_c0d">#00000c0d</color>
+    <color name="i_am_color_c0e">#00000c0e</color>
+    <color name="i_am_color_c0f">#00000c0f</color>
+    <color name="i_am_color_c10">#00000c10</color>
+    <color name="i_am_color_c11">#00000c11</color>
+    <color name="i_am_color_c12">#00000c12</color>
+    <color name="i_am_color_c13">#00000c13</color>
+    <color name="i_am_color_c14">#00000c14</color>
+    <color name="i_am_color_c15">#00000c15</color>
+    <color name="i_am_color_c16">#00000c16</color>
+    <color name="i_am_color_c17">#00000c17</color>
+    <color name="i_am_color_c18">#00000c18</color>
+    <color name="i_am_color_c19">#00000c19</color>
+    <color name="i_am_color_c1a">#00000c1a</color>
+    <color name="i_am_color_c1b">#00000c1b</color>
+    <color name="i_am_color_c1c">#00000c1c</color>
+    <color name="i_am_color_c1d">#00000c1d</color>
+    <color name="i_am_color_c1e">#00000c1e</color>
+    <color name="i_am_color_c1f">#00000c1f</color>
+    <color name="i_am_color_c20">#00000c20</color>
+    <color name="i_am_color_c21">#00000c21</color>
+    <color name="i_am_color_c22">#00000c22</color>
+    <color name="i_am_color_c23">#00000c23</color>
+    <color name="i_am_color_c24">#00000c24</color>
+    <color name="i_am_color_c25">#00000c25</color>
+    <color name="i_am_color_c26">#00000c26</color>
+    <color name="i_am_color_c27">#00000c27</color>
+    <color name="i_am_color_c28">#00000c28</color>
+    <color name="i_am_color_c29">#00000c29</color>
+    <color name="i_am_color_c2a">#00000c2a</color>
+    <color name="i_am_color_c2b">#00000c2b</color>
+    <color name="i_am_color_c2c">#00000c2c</color>
+    <color name="i_am_color_c2d">#00000c2d</color>
+    <color name="i_am_color_c2e">#00000c2e</color>
+    <color name="i_am_color_c2f">#00000c2f</color>
+    <color name="i_am_color_c30">#00000c30</color>
+    <color name="i_am_color_c31">#00000c31</color>
+    <color name="i_am_color_c32">#00000c32</color>
+    <color name="i_am_color_c33">#00000c33</color>
+    <color name="i_am_color_c34">#00000c34</color>
+    <color name="i_am_color_c35">#00000c35</color>
+    <color name="i_am_color_c36">#00000c36</color>
+    <color name="i_am_color_c37">#00000c37</color>
+    <color name="i_am_color_c38">#00000c38</color>
+    <color name="i_am_color_c39">#00000c39</color>
+    <color name="i_am_color_c3a">#00000c3a</color>
+    <color name="i_am_color_c3b">#00000c3b</color>
+    <color name="i_am_color_c3c">#00000c3c</color>
+    <color name="i_am_color_c3d">#00000c3d</color>
+    <color name="i_am_color_c3e">#00000c3e</color>
+    <color name="i_am_color_c3f">#00000c3f</color>
+    <color name="i_am_color_c40">#00000c40</color>
+    <color name="i_am_color_c41">#00000c41</color>
+    <color name="i_am_color_c42">#00000c42</color>
+    <color name="i_am_color_c43">#00000c43</color>
+    <color name="i_am_color_c44">#00000c44</color>
+    <color name="i_am_color_c45">#00000c45</color>
+    <color name="i_am_color_c46">#00000c46</color>
+    <color name="i_am_color_c47">#00000c47</color>
+    <color name="i_am_color_c48">#00000c48</color>
+    <color name="i_am_color_c49">#00000c49</color>
+    <color name="i_am_color_c4a">#00000c4a</color>
+    <color name="i_am_color_c4b">#00000c4b</color>
+    <color name="i_am_color_c4c">#00000c4c</color>
+    <color name="i_am_color_c4d">#00000c4d</color>
+    <color name="i_am_color_c4e">#00000c4e</color>
+    <color name="i_am_color_c4f">#00000c4f</color>
+    <color name="i_am_color_c50">#00000c50</color>
+    <color name="i_am_color_c51">#00000c51</color>
+    <color name="i_am_color_c52">#00000c52</color>
+    <color name="i_am_color_c53">#00000c53</color>
+    <color name="i_am_color_c54">#00000c54</color>
+    <color name="i_am_color_c55">#00000c55</color>
+    <color name="i_am_color_c56">#00000c56</color>
+    <color name="i_am_color_c57">#00000c57</color>
+    <color name="i_am_color_c58">#00000c58</color>
+    <color name="i_am_color_c59">#00000c59</color>
+    <color name="i_am_color_c5a">#00000c5a</color>
+    <color name="i_am_color_c5b">#00000c5b</color>
+    <color name="i_am_color_c5c">#00000c5c</color>
+    <color name="i_am_color_c5d">#00000c5d</color>
+    <color name="i_am_color_c5e">#00000c5e</color>
+    <color name="i_am_color_c5f">#00000c5f</color>
+    <color name="i_am_color_c60">#00000c60</color>
+    <color name="i_am_color_c61">#00000c61</color>
+    <color name="i_am_color_c62">#00000c62</color>
+    <color name="i_am_color_c63">#00000c63</color>
+    <color name="i_am_color_c64">#00000c64</color>
+    <color name="i_am_color_c65">#00000c65</color>
+    <color name="i_am_color_c66">#00000c66</color>
+    <color name="i_am_color_c67">#00000c67</color>
+    <color name="i_am_color_c68">#00000c68</color>
+    <color name="i_am_color_c69">#00000c69</color>
+    <color name="i_am_color_c6a">#00000c6a</color>
+    <color name="i_am_color_c6b">#00000c6b</color>
+    <color name="i_am_color_c6c">#00000c6c</color>
+    <color name="i_am_color_c6d">#00000c6d</color>
+    <color name="i_am_color_c6e">#00000c6e</color>
+    <color name="i_am_color_c6f">#00000c6f</color>
+    <color name="i_am_color_c70">#00000c70</color>
+    <color name="i_am_color_c71">#00000c71</color>
+    <color name="i_am_color_c72">#00000c72</color>
+    <color name="i_am_color_c73">#00000c73</color>
+    <color name="i_am_color_c74">#00000c74</color>
+    <color name="i_am_color_c75">#00000c75</color>
+    <color name="i_am_color_c76">#00000c76</color>
+    <color name="i_am_color_c77">#00000c77</color>
+    <color name="i_am_color_c78">#00000c78</color>
+    <color name="i_am_color_c79">#00000c79</color>
+    <color name="i_am_color_c7a">#00000c7a</color>
+    <color name="i_am_color_c7b">#00000c7b</color>
+    <color name="i_am_color_c7c">#00000c7c</color>
+    <color name="i_am_color_c7d">#00000c7d</color>
+    <color name="i_am_color_c7e">#00000c7e</color>
+    <color name="i_am_color_c7f">#00000c7f</color>
+    <color name="i_am_color_c80">#00000c80</color>
+    <color name="i_am_color_c81">#00000c81</color>
+    <color name="i_am_color_c82">#00000c82</color>
+    <color name="i_am_color_c83">#00000c83</color>
+    <color name="i_am_color_c84">#00000c84</color>
+    <color name="i_am_color_c85">#00000c85</color>
+    <color name="i_am_color_c86">#00000c86</color>
+    <color name="i_am_color_c87">#00000c87</color>
+    <color name="i_am_color_c88">#00000c88</color>
+    <color name="i_am_color_c89">#00000c89</color>
+    <color name="i_am_color_c8a">#00000c8a</color>
+    <color name="i_am_color_c8b">#00000c8b</color>
+    <color name="i_am_color_c8c">#00000c8c</color>
+    <color name="i_am_color_c8d">#00000c8d</color>
+    <color name="i_am_color_c8e">#00000c8e</color>
+    <color name="i_am_color_c8f">#00000c8f</color>
+    <color name="i_am_color_c90">#00000c90</color>
+    <color name="i_am_color_c91">#00000c91</color>
+    <color name="i_am_color_c92">#00000c92</color>
+    <color name="i_am_color_c93">#00000c93</color>
+    <color name="i_am_color_c94">#00000c94</color>
+    <color name="i_am_color_c95">#00000c95</color>
+    <color name="i_am_color_c96">#00000c96</color>
+    <color name="i_am_color_c97">#00000c97</color>
+    <color name="i_am_color_c98">#00000c98</color>
+    <color name="i_am_color_c99">#00000c99</color>
+    <color name="i_am_color_c9a">#00000c9a</color>
+    <color name="i_am_color_c9b">#00000c9b</color>
+    <color name="i_am_color_c9c">#00000c9c</color>
+    <color name="i_am_color_c9d">#00000c9d</color>
+    <color name="i_am_color_c9e">#00000c9e</color>
+    <color name="i_am_color_c9f">#00000c9f</color>
+    <color name="i_am_color_ca0">#00000ca0</color>
+    <color name="i_am_color_ca1">#00000ca1</color>
+    <color name="i_am_color_ca2">#00000ca2</color>
+    <color name="i_am_color_ca3">#00000ca3</color>
+    <color name="i_am_color_ca4">#00000ca4</color>
+    <color name="i_am_color_ca5">#00000ca5</color>
+    <color name="i_am_color_ca6">#00000ca6</color>
+    <color name="i_am_color_ca7">#00000ca7</color>
+    <color name="i_am_color_ca8">#00000ca8</color>
+    <color name="i_am_color_ca9">#00000ca9</color>
+    <color name="i_am_color_caa">#00000caa</color>
+    <color name="i_am_color_cab">#00000cab</color>
+    <color name="i_am_color_cac">#00000cac</color>
+    <color name="i_am_color_cad">#00000cad</color>
+    <color name="i_am_color_cae">#00000cae</color>
+    <color name="i_am_color_caf">#00000caf</color>
+    <color name="i_am_color_cb0">#00000cb0</color>
+    <color name="i_am_color_cb1">#00000cb1</color>
+    <color name="i_am_color_cb2">#00000cb2</color>
+    <color name="i_am_color_cb3">#00000cb3</color>
+    <color name="i_am_color_cb4">#00000cb4</color>
+    <color name="i_am_color_cb5">#00000cb5</color>
+    <color name="i_am_color_cb6">#00000cb6</color>
+    <color name="i_am_color_cb7">#00000cb7</color>
+    <color name="i_am_color_cb8">#00000cb8</color>
+    <color name="i_am_color_cb9">#00000cb9</color>
+    <color name="i_am_color_cba">#00000cba</color>
+    <color name="i_am_color_cbb">#00000cbb</color>
+    <color name="i_am_color_cbc">#00000cbc</color>
+    <color name="i_am_color_cbd">#00000cbd</color>
+    <color name="i_am_color_cbe">#00000cbe</color>
+    <color name="i_am_color_cbf">#00000cbf</color>
+    <color name="i_am_color_cc0">#00000cc0</color>
+    <color name="i_am_color_cc1">#00000cc1</color>
+    <color name="i_am_color_cc2">#00000cc2</color>
+    <color name="i_am_color_cc3">#00000cc3</color>
+    <color name="i_am_color_cc4">#00000cc4</color>
+    <color name="i_am_color_cc5">#00000cc5</color>
+    <color name="i_am_color_cc6">#00000cc6</color>
+    <color name="i_am_color_cc7">#00000cc7</color>
+    <color name="i_am_color_cc8">#00000cc8</color>
+    <color name="i_am_color_cc9">#00000cc9</color>
+    <color name="i_am_color_cca">#00000cca</color>
+    <color name="i_am_color_ccb">#00000ccb</color>
+    <color name="i_am_color_ccc">#00000ccc</color>
+    <color name="i_am_color_ccd">#00000ccd</color>
+    <color name="i_am_color_cce">#00000cce</color>
+    <color name="i_am_color_ccf">#00000ccf</color>
+    <color name="i_am_color_cd0">#00000cd0</color>
+    <color name="i_am_color_cd1">#00000cd1</color>
+    <color name="i_am_color_cd2">#00000cd2</color>
+    <color name="i_am_color_cd3">#00000cd3</color>
+    <color name="i_am_color_cd4">#00000cd4</color>
+    <color name="i_am_color_cd5">#00000cd5</color>
+    <color name="i_am_color_cd6">#00000cd6</color>
+    <color name="i_am_color_cd7">#00000cd7</color>
+    <color name="i_am_color_cd8">#00000cd8</color>
+    <color name="i_am_color_cd9">#00000cd9</color>
+    <color name="i_am_color_cda">#00000cda</color>
+    <color name="i_am_color_cdb">#00000cdb</color>
+    <color name="i_am_color_cdc">#00000cdc</color>
+    <color name="i_am_color_cdd">#00000cdd</color>
+    <color name="i_am_color_cde">#00000cde</color>
+    <color name="i_am_color_cdf">#00000cdf</color>
+    <color name="i_am_color_ce0">#00000ce0</color>
+    <color name="i_am_color_ce1">#00000ce1</color>
+    <color name="i_am_color_ce2">#00000ce2</color>
+    <color name="i_am_color_ce3">#00000ce3</color>
+    <color name="i_am_color_ce4">#00000ce4</color>
+    <color name="i_am_color_ce5">#00000ce5</color>
+    <color name="i_am_color_ce6">#00000ce6</color>
+    <color name="i_am_color_ce7">#00000ce7</color>
+    <color name="i_am_color_ce8">#00000ce8</color>
+    <color name="i_am_color_ce9">#00000ce9</color>
+    <color name="i_am_color_cea">#00000cea</color>
+    <color name="i_am_color_ceb">#00000ceb</color>
+    <color name="i_am_color_cec">#00000cec</color>
+    <color name="i_am_color_ced">#00000ced</color>
+    <color name="i_am_color_cee">#00000cee</color>
+    <color name="i_am_color_cef">#00000cef</color>
+    <color name="i_am_color_cf0">#00000cf0</color>
+    <color name="i_am_color_cf1">#00000cf1</color>
+    <color name="i_am_color_cf2">#00000cf2</color>
+    <color name="i_am_color_cf3">#00000cf3</color>
+    <color name="i_am_color_cf4">#00000cf4</color>
+    <color name="i_am_color_cf5">#00000cf5</color>
+    <color name="i_am_color_cf6">#00000cf6</color>
+    <color name="i_am_color_cf7">#00000cf7</color>
+    <color name="i_am_color_cf8">#00000cf8</color>
+    <color name="i_am_color_cf9">#00000cf9</color>
+    <color name="i_am_color_cfa">#00000cfa</color>
+    <color name="i_am_color_cfb">#00000cfb</color>
+    <color name="i_am_color_cfc">#00000cfc</color>
+    <color name="i_am_color_cfd">#00000cfd</color>
+    <color name="i_am_color_cfe">#00000cfe</color>
+    <color name="i_am_color_cff">#00000cff</color>
+    <color name="i_am_color_d00">#00000d00</color>
+    <color name="i_am_color_d01">#00000d01</color>
+    <color name="i_am_color_d02">#00000d02</color>
+    <color name="i_am_color_d03">#00000d03</color>
+    <color name="i_am_color_d04">#00000d04</color>
+    <color name="i_am_color_d05">#00000d05</color>
+    <color name="i_am_color_d06">#00000d06</color>
+    <color name="i_am_color_d07">#00000d07</color>
+    <color name="i_am_color_d08">#00000d08</color>
+    <color name="i_am_color_d09">#00000d09</color>
+    <color name="i_am_color_d0a">#00000d0a</color>
+    <color name="i_am_color_d0b">#00000d0b</color>
+    <color name="i_am_color_d0c">#00000d0c</color>
+    <color name="i_am_color_d0d">#00000d0d</color>
+    <color name="i_am_color_d0e">#00000d0e</color>
+    <color name="i_am_color_d0f">#00000d0f</color>
+    <color name="i_am_color_d10">#00000d10</color>
+    <color name="i_am_color_d11">#00000d11</color>
+    <color name="i_am_color_d12">#00000d12</color>
+    <color name="i_am_color_d13">#00000d13</color>
+    <color name="i_am_color_d14">#00000d14</color>
+    <color name="i_am_color_d15">#00000d15</color>
+    <color name="i_am_color_d16">#00000d16</color>
+    <color name="i_am_color_d17">#00000d17</color>
+    <color name="i_am_color_d18">#00000d18</color>
+    <color name="i_am_color_d19">#00000d19</color>
+    <color name="i_am_color_d1a">#00000d1a</color>
+    <color name="i_am_color_d1b">#00000d1b</color>
+    <color name="i_am_color_d1c">#00000d1c</color>
+    <color name="i_am_color_d1d">#00000d1d</color>
+    <color name="i_am_color_d1e">#00000d1e</color>
+    <color name="i_am_color_d1f">#00000d1f</color>
+    <color name="i_am_color_d20">#00000d20</color>
+    <color name="i_am_color_d21">#00000d21</color>
+    <color name="i_am_color_d22">#00000d22</color>
+    <color name="i_am_color_d23">#00000d23</color>
+    <color name="i_am_color_d24">#00000d24</color>
+    <color name="i_am_color_d25">#00000d25</color>
+    <color name="i_am_color_d26">#00000d26</color>
+    <color name="i_am_color_d27">#00000d27</color>
+    <color name="i_am_color_d28">#00000d28</color>
+    <color name="i_am_color_d29">#00000d29</color>
+    <color name="i_am_color_d2a">#00000d2a</color>
+    <color name="i_am_color_d2b">#00000d2b</color>
+    <color name="i_am_color_d2c">#00000d2c</color>
+    <color name="i_am_color_d2d">#00000d2d</color>
+    <color name="i_am_color_d2e">#00000d2e</color>
+    <color name="i_am_color_d2f">#00000d2f</color>
+    <color name="i_am_color_d30">#00000d30</color>
+    <color name="i_am_color_d31">#00000d31</color>
+    <color name="i_am_color_d32">#00000d32</color>
+    <color name="i_am_color_d33">#00000d33</color>
+    <color name="i_am_color_d34">#00000d34</color>
+    <color name="i_am_color_d35">#00000d35</color>
+    <color name="i_am_color_d36">#00000d36</color>
+    <color name="i_am_color_d37">#00000d37</color>
+    <color name="i_am_color_d38">#00000d38</color>
+    <color name="i_am_color_d39">#00000d39</color>
+    <color name="i_am_color_d3a">#00000d3a</color>
+    <color name="i_am_color_d3b">#00000d3b</color>
+    <color name="i_am_color_d3c">#00000d3c</color>
+    <color name="i_am_color_d3d">#00000d3d</color>
+    <color name="i_am_color_d3e">#00000d3e</color>
+    <color name="i_am_color_d3f">#00000d3f</color>
+    <color name="i_am_color_d40">#00000d40</color>
+    <color name="i_am_color_d41">#00000d41</color>
+    <color name="i_am_color_d42">#00000d42</color>
+    <color name="i_am_color_d43">#00000d43</color>
+    <color name="i_am_color_d44">#00000d44</color>
+    <color name="i_am_color_d45">#00000d45</color>
+    <color name="i_am_color_d46">#00000d46</color>
+    <color name="i_am_color_d47">#00000d47</color>
+    <color name="i_am_color_d48">#00000d48</color>
+    <color name="i_am_color_d49">#00000d49</color>
+    <color name="i_am_color_d4a">#00000d4a</color>
+    <color name="i_am_color_d4b">#00000d4b</color>
+    <color name="i_am_color_d4c">#00000d4c</color>
+    <color name="i_am_color_d4d">#00000d4d</color>
+    <color name="i_am_color_d4e">#00000d4e</color>
+    <color name="i_am_color_d4f">#00000d4f</color>
+    <color name="i_am_color_d50">#00000d50</color>
+    <color name="i_am_color_d51">#00000d51</color>
+    <color name="i_am_color_d52">#00000d52</color>
+    <color name="i_am_color_d53">#00000d53</color>
+    <color name="i_am_color_d54">#00000d54</color>
+    <color name="i_am_color_d55">#00000d55</color>
+    <color name="i_am_color_d56">#00000d56</color>
+    <color name="i_am_color_d57">#00000d57</color>
+    <color name="i_am_color_d58">#00000d58</color>
+    <color name="i_am_color_d59">#00000d59</color>
+    <color name="i_am_color_d5a">#00000d5a</color>
+    <color name="i_am_color_d5b">#00000d5b</color>
+    <color name="i_am_color_d5c">#00000d5c</color>
+    <color name="i_am_color_d5d">#00000d5d</color>
+    <color name="i_am_color_d5e">#00000d5e</color>
+    <color name="i_am_color_d5f">#00000d5f</color>
+    <color name="i_am_color_d60">#00000d60</color>
+    <color name="i_am_color_d61">#00000d61</color>
+    <color name="i_am_color_d62">#00000d62</color>
+    <color name="i_am_color_d63">#00000d63</color>
+    <color name="i_am_color_d64">#00000d64</color>
+    <color name="i_am_color_d65">#00000d65</color>
+    <color name="i_am_color_d66">#00000d66</color>
+    <color name="i_am_color_d67">#00000d67</color>
+    <color name="i_am_color_d68">#00000d68</color>
+    <color name="i_am_color_d69">#00000d69</color>
+    <color name="i_am_color_d6a">#00000d6a</color>
+    <color name="i_am_color_d6b">#00000d6b</color>
+    <color name="i_am_color_d6c">#00000d6c</color>
+    <color name="i_am_color_d6d">#00000d6d</color>
+    <color name="i_am_color_d6e">#00000d6e</color>
+    <color name="i_am_color_d6f">#00000d6f</color>
+    <color name="i_am_color_d70">#00000d70</color>
+    <color name="i_am_color_d71">#00000d71</color>
+    <color name="i_am_color_d72">#00000d72</color>
+    <color name="i_am_color_d73">#00000d73</color>
+    <color name="i_am_color_d74">#00000d74</color>
+    <color name="i_am_color_d75">#00000d75</color>
+    <color name="i_am_color_d76">#00000d76</color>
+    <color name="i_am_color_d77">#00000d77</color>
+    <color name="i_am_color_d78">#00000d78</color>
+    <color name="i_am_color_d79">#00000d79</color>
+    <color name="i_am_color_d7a">#00000d7a</color>
+    <color name="i_am_color_d7b">#00000d7b</color>
+    <color name="i_am_color_d7c">#00000d7c</color>
+    <color name="i_am_color_d7d">#00000d7d</color>
+    <color name="i_am_color_d7e">#00000d7e</color>
+    <color name="i_am_color_d7f">#00000d7f</color>
+    <color name="i_am_color_d80">#00000d80</color>
+    <color name="i_am_color_d81">#00000d81</color>
+    <color name="i_am_color_d82">#00000d82</color>
+    <color name="i_am_color_d83">#00000d83</color>
+    <color name="i_am_color_d84">#00000d84</color>
+    <color name="i_am_color_d85">#00000d85</color>
+    <color name="i_am_color_d86">#00000d86</color>
+    <color name="i_am_color_d87">#00000d87</color>
+    <color name="i_am_color_d88">#00000d88</color>
+    <color name="i_am_color_d89">#00000d89</color>
+    <color name="i_am_color_d8a">#00000d8a</color>
+    <color name="i_am_color_d8b">#00000d8b</color>
+    <color name="i_am_color_d8c">#00000d8c</color>
+    <color name="i_am_color_d8d">#00000d8d</color>
+    <color name="i_am_color_d8e">#00000d8e</color>
+    <color name="i_am_color_d8f">#00000d8f</color>
+    <color name="i_am_color_d90">#00000d90</color>
+    <color name="i_am_color_d91">#00000d91</color>
+    <color name="i_am_color_d92">#00000d92</color>
+    <color name="i_am_color_d93">#00000d93</color>
+    <color name="i_am_color_d94">#00000d94</color>
+    <color name="i_am_color_d95">#00000d95</color>
+    <color name="i_am_color_d96">#00000d96</color>
+    <color name="i_am_color_d97">#00000d97</color>
+    <color name="i_am_color_d98">#00000d98</color>
+    <color name="i_am_color_d99">#00000d99</color>
+    <color name="i_am_color_d9a">#00000d9a</color>
+    <color name="i_am_color_d9b">#00000d9b</color>
+    <color name="i_am_color_d9c">#00000d9c</color>
+    <color name="i_am_color_d9d">#00000d9d</color>
+    <color name="i_am_color_d9e">#00000d9e</color>
+    <color name="i_am_color_d9f">#00000d9f</color>
+    <color name="i_am_color_da0">#00000da0</color>
+    <color name="i_am_color_da1">#00000da1</color>
+    <color name="i_am_color_da2">#00000da2</color>
+    <color name="i_am_color_da3">#00000da3</color>
+    <color name="i_am_color_da4">#00000da4</color>
+    <color name="i_am_color_da5">#00000da5</color>
+    <color name="i_am_color_da6">#00000da6</color>
+    <color name="i_am_color_da7">#00000da7</color>
+    <color name="i_am_color_da8">#00000da8</color>
+    <color name="i_am_color_da9">#00000da9</color>
+    <color name="i_am_color_daa">#00000daa</color>
+    <color name="i_am_color_dab">#00000dab</color>
+    <color name="i_am_color_dac">#00000dac</color>
+    <color name="i_am_color_dad">#00000dad</color>
+    <color name="i_am_color_dae">#00000dae</color>
+    <color name="i_am_color_daf">#00000daf</color>
+    <color name="i_am_color_db0">#00000db0</color>
+    <color name="i_am_color_db1">#00000db1</color>
+    <color name="i_am_color_db2">#00000db2</color>
+    <color name="i_am_color_db3">#00000db3</color>
+    <color name="i_am_color_db4">#00000db4</color>
+    <color name="i_am_color_db5">#00000db5</color>
+    <color name="i_am_color_db6">#00000db6</color>
+    <color name="i_am_color_db7">#00000db7</color>
+    <color name="i_am_color_db8">#00000db8</color>
+    <color name="i_am_color_db9">#00000db9</color>
+    <color name="i_am_color_dba">#00000dba</color>
+    <color name="i_am_color_dbb">#00000dbb</color>
+    <color name="i_am_color_dbc">#00000dbc</color>
+    <color name="i_am_color_dbd">#00000dbd</color>
+    <color name="i_am_color_dbe">#00000dbe</color>
+    <color name="i_am_color_dbf">#00000dbf</color>
+    <color name="i_am_color_dc0">#00000dc0</color>
+    <color name="i_am_color_dc1">#00000dc1</color>
+    <color name="i_am_color_dc2">#00000dc2</color>
+    <color name="i_am_color_dc3">#00000dc3</color>
+    <color name="i_am_color_dc4">#00000dc4</color>
+    <color name="i_am_color_dc5">#00000dc5</color>
+    <color name="i_am_color_dc6">#00000dc6</color>
+    <color name="i_am_color_dc7">#00000dc7</color>
+    <color name="i_am_color_dc8">#00000dc8</color>
+    <color name="i_am_color_dc9">#00000dc9</color>
+    <color name="i_am_color_dca">#00000dca</color>
+    <color name="i_am_color_dcb">#00000dcb</color>
+    <color name="i_am_color_dcc">#00000dcc</color>
+    <color name="i_am_color_dcd">#00000dcd</color>
+    <color name="i_am_color_dce">#00000dce</color>
+    <color name="i_am_color_dcf">#00000dcf</color>
+    <color name="i_am_color_dd0">#00000dd0</color>
+    <color name="i_am_color_dd1">#00000dd1</color>
+    <color name="i_am_color_dd2">#00000dd2</color>
+    <color name="i_am_color_dd3">#00000dd3</color>
+    <color name="i_am_color_dd4">#00000dd4</color>
+    <color name="i_am_color_dd5">#00000dd5</color>
+    <color name="i_am_color_dd6">#00000dd6</color>
+    <color name="i_am_color_dd7">#00000dd7</color>
+    <color name="i_am_color_dd8">#00000dd8</color>
+    <color name="i_am_color_dd9">#00000dd9</color>
+    <color name="i_am_color_dda">#00000dda</color>
+    <color name="i_am_color_ddb">#00000ddb</color>
+    <color name="i_am_color_ddc">#00000ddc</color>
+    <color name="i_am_color_ddd">#00000ddd</color>
+    <color name="i_am_color_dde">#00000dde</color>
+    <color name="i_am_color_ddf">#00000ddf</color>
+    <color name="i_am_color_de0">#00000de0</color>
+    <color name="i_am_color_de1">#00000de1</color>
+    <color name="i_am_color_de2">#00000de2</color>
+    <color name="i_am_color_de3">#00000de3</color>
+    <color name="i_am_color_de4">#00000de4</color>
+    <color name="i_am_color_de5">#00000de5</color>
+    <color name="i_am_color_de6">#00000de6</color>
+    <color name="i_am_color_de7">#00000de7</color>
+    <color name="i_am_color_de8">#00000de8</color>
+    <color name="i_am_color_de9">#00000de9</color>
+    <color name="i_am_color_dea">#00000dea</color>
+    <color name="i_am_color_deb">#00000deb</color>
+    <color name="i_am_color_dec">#00000dec</color>
+    <color name="i_am_color_ded">#00000ded</color>
+    <color name="i_am_color_dee">#00000dee</color>
+    <color name="i_am_color_def">#00000def</color>
+    <color name="i_am_color_df0">#00000df0</color>
+    <color name="i_am_color_df1">#00000df1</color>
+    <color name="i_am_color_df2">#00000df2</color>
+    <color name="i_am_color_df3">#00000df3</color>
+    <color name="i_am_color_df4">#00000df4</color>
+    <color name="i_am_color_df5">#00000df5</color>
+    <color name="i_am_color_df6">#00000df6</color>
+    <color name="i_am_color_df7">#00000df7</color>
+    <color name="i_am_color_df8">#00000df8</color>
+    <color name="i_am_color_df9">#00000df9</color>
+    <color name="i_am_color_dfa">#00000dfa</color>
+    <color name="i_am_color_dfb">#00000dfb</color>
+    <color name="i_am_color_dfc">#00000dfc</color>
+    <color name="i_am_color_dfd">#00000dfd</color>
+    <color name="i_am_color_dfe">#00000dfe</color>
+    <color name="i_am_color_dff">#00000dff</color>
+    <color name="i_am_color_e00">#00000e00</color>
+    <color name="i_am_color_e01">#00000e01</color>
+    <color name="i_am_color_e02">#00000e02</color>
+    <color name="i_am_color_e03">#00000e03</color>
+    <color name="i_am_color_e04">#00000e04</color>
+    <color name="i_am_color_e05">#00000e05</color>
+    <color name="i_am_color_e06">#00000e06</color>
+    <color name="i_am_color_e07">#00000e07</color>
+    <color name="i_am_color_e08">#00000e08</color>
+    <color name="i_am_color_e09">#00000e09</color>
+    <color name="i_am_color_e0a">#00000e0a</color>
+    <color name="i_am_color_e0b">#00000e0b</color>
+    <color name="i_am_color_e0c">#00000e0c</color>
+    <color name="i_am_color_e0d">#00000e0d</color>
+    <color name="i_am_color_e0e">#00000e0e</color>
+    <color name="i_am_color_e0f">#00000e0f</color>
+    <color name="i_am_color_e10">#00000e10</color>
+    <color name="i_am_color_e11">#00000e11</color>
+    <color name="i_am_color_e12">#00000e12</color>
+    <color name="i_am_color_e13">#00000e13</color>
+    <color name="i_am_color_e14">#00000e14</color>
+    <color name="i_am_color_e15">#00000e15</color>
+    <color name="i_am_color_e16">#00000e16</color>
+    <color name="i_am_color_e17">#00000e17</color>
+    <color name="i_am_color_e18">#00000e18</color>
+    <color name="i_am_color_e19">#00000e19</color>
+    <color name="i_am_color_e1a">#00000e1a</color>
+    <color name="i_am_color_e1b">#00000e1b</color>
+    <color name="i_am_color_e1c">#00000e1c</color>
+    <color name="i_am_color_e1d">#00000e1d</color>
+    <color name="i_am_color_e1e">#00000e1e</color>
+    <color name="i_am_color_e1f">#00000e1f</color>
+    <color name="i_am_color_e20">#00000e20</color>
+    <color name="i_am_color_e21">#00000e21</color>
+    <color name="i_am_color_e22">#00000e22</color>
+    <color name="i_am_color_e23">#00000e23</color>
+    <color name="i_am_color_e24">#00000e24</color>
+    <color name="i_am_color_e25">#00000e25</color>
+    <color name="i_am_color_e26">#00000e26</color>
+    <color name="i_am_color_e27">#00000e27</color>
+    <color name="i_am_color_e28">#00000e28</color>
+    <color name="i_am_color_e29">#00000e29</color>
+    <color name="i_am_color_e2a">#00000e2a</color>
+    <color name="i_am_color_e2b">#00000e2b</color>
+    <color name="i_am_color_e2c">#00000e2c</color>
+    <color name="i_am_color_e2d">#00000e2d</color>
+    <color name="i_am_color_e2e">#00000e2e</color>
+    <color name="i_am_color_e2f">#00000e2f</color>
+    <color name="i_am_color_e30">#00000e30</color>
+    <color name="i_am_color_e31">#00000e31</color>
+    <color name="i_am_color_e32">#00000e32</color>
+    <color name="i_am_color_e33">#00000e33</color>
+    <color name="i_am_color_e34">#00000e34</color>
+    <color name="i_am_color_e35">#00000e35</color>
+    <color name="i_am_color_e36">#00000e36</color>
+    <color name="i_am_color_e37">#00000e37</color>
+    <color name="i_am_color_e38">#00000e38</color>
+    <color name="i_am_color_e39">#00000e39</color>
+    <color name="i_am_color_e3a">#00000e3a</color>
+    <color name="i_am_color_e3b">#00000e3b</color>
+    <color name="i_am_color_e3c">#00000e3c</color>
+    <color name="i_am_color_e3d">#00000e3d</color>
+    <color name="i_am_color_e3e">#00000e3e</color>
+    <color name="i_am_color_e3f">#00000e3f</color>
+    <color name="i_am_color_e40">#00000e40</color>
+    <color name="i_am_color_e41">#00000e41</color>
+    <color name="i_am_color_e42">#00000e42</color>
+    <color name="i_am_color_e43">#00000e43</color>
+    <color name="i_am_color_e44">#00000e44</color>
+    <color name="i_am_color_e45">#00000e45</color>
+    <color name="i_am_color_e46">#00000e46</color>
+    <color name="i_am_color_e47">#00000e47</color>
+    <color name="i_am_color_e48">#00000e48</color>
+    <color name="i_am_color_e49">#00000e49</color>
+    <color name="i_am_color_e4a">#00000e4a</color>
+    <color name="i_am_color_e4b">#00000e4b</color>
+    <color name="i_am_color_e4c">#00000e4c</color>
+    <color name="i_am_color_e4d">#00000e4d</color>
+    <color name="i_am_color_e4e">#00000e4e</color>
+    <color name="i_am_color_e4f">#00000e4f</color>
+    <color name="i_am_color_e50">#00000e50</color>
+    <color name="i_am_color_e51">#00000e51</color>
+    <color name="i_am_color_e52">#00000e52</color>
+    <color name="i_am_color_e53">#00000e53</color>
+    <color name="i_am_color_e54">#00000e54</color>
+    <color name="i_am_color_e55">#00000e55</color>
+    <color name="i_am_color_e56">#00000e56</color>
+    <color name="i_am_color_e57">#00000e57</color>
+    <color name="i_am_color_e58">#00000e58</color>
+    <color name="i_am_color_e59">#00000e59</color>
+    <color name="i_am_color_e5a">#00000e5a</color>
+    <color name="i_am_color_e5b">#00000e5b</color>
+    <color name="i_am_color_e5c">#00000e5c</color>
+    <color name="i_am_color_e5d">#00000e5d</color>
+    <color name="i_am_color_e5e">#00000e5e</color>
+    <color name="i_am_color_e5f">#00000e5f</color>
+    <color name="i_am_color_e60">#00000e60</color>
+    <color name="i_am_color_e61">#00000e61</color>
+    <color name="i_am_color_e62">#00000e62</color>
+    <color name="i_am_color_e63">#00000e63</color>
+    <color name="i_am_color_e64">#00000e64</color>
+    <color name="i_am_color_e65">#00000e65</color>
+    <color name="i_am_color_e66">#00000e66</color>
+    <color name="i_am_color_e67">#00000e67</color>
+    <color name="i_am_color_e68">#00000e68</color>
+    <color name="i_am_color_e69">#00000e69</color>
+    <color name="i_am_color_e6a">#00000e6a</color>
+    <color name="i_am_color_e6b">#00000e6b</color>
+    <color name="i_am_color_e6c">#00000e6c</color>
+    <color name="i_am_color_e6d">#00000e6d</color>
+    <color name="i_am_color_e6e">#00000e6e</color>
+    <color name="i_am_color_e6f">#00000e6f</color>
+    <color name="i_am_color_e70">#00000e70</color>
+    <color name="i_am_color_e71">#00000e71</color>
+    <color name="i_am_color_e72">#00000e72</color>
+    <color name="i_am_color_e73">#00000e73</color>
+    <color name="i_am_color_e74">#00000e74</color>
+    <color name="i_am_color_e75">#00000e75</color>
+    <color name="i_am_color_e76">#00000e76</color>
+    <color name="i_am_color_e77">#00000e77</color>
+    <color name="i_am_color_e78">#00000e78</color>
+    <color name="i_am_color_e79">#00000e79</color>
+    <color name="i_am_color_e7a">#00000e7a</color>
+    <color name="i_am_color_e7b">#00000e7b</color>
+    <color name="i_am_color_e7c">#00000e7c</color>
+    <color name="i_am_color_e7d">#00000e7d</color>
+    <color name="i_am_color_e7e">#00000e7e</color>
+    <color name="i_am_color_e7f">#00000e7f</color>
+    <color name="i_am_color_e80">#00000e80</color>
+    <color name="i_am_color_e81">#00000e81</color>
+    <color name="i_am_color_e82">#00000e82</color>
+    <color name="i_am_color_e83">#00000e83</color>
+    <color name="i_am_color_e84">#00000e84</color>
+    <color name="i_am_color_e85">#00000e85</color>
+    <color name="i_am_color_e86">#00000e86</color>
+    <color name="i_am_color_e87">#00000e87</color>
+    <color name="i_am_color_e88">#00000e88</color>
+    <color name="i_am_color_e89">#00000e89</color>
+    <color name="i_am_color_e8a">#00000e8a</color>
+    <color name="i_am_color_e8b">#00000e8b</color>
+    <color name="i_am_color_e8c">#00000e8c</color>
+    <color name="i_am_color_e8d">#00000e8d</color>
+    <color name="i_am_color_e8e">#00000e8e</color>
+    <color name="i_am_color_e8f">#00000e8f</color>
+    <color name="i_am_color_e90">#00000e90</color>
+    <color name="i_am_color_e91">#00000e91</color>
+    <color name="i_am_color_e92">#00000e92</color>
+    <color name="i_am_color_e93">#00000e93</color>
+    <color name="i_am_color_e94">#00000e94</color>
+    <color name="i_am_color_e95">#00000e95</color>
+    <color name="i_am_color_e96">#00000e96</color>
+    <color name="i_am_color_e97">#00000e97</color>
+    <color name="i_am_color_e98">#00000e98</color>
+    <color name="i_am_color_e99">#00000e99</color>
+    <color name="i_am_color_e9a">#00000e9a</color>
+    <color name="i_am_color_e9b">#00000e9b</color>
+    <color name="i_am_color_e9c">#00000e9c</color>
+    <color name="i_am_color_e9d">#00000e9d</color>
+    <color name="i_am_color_e9e">#00000e9e</color>
+    <color name="i_am_color_e9f">#00000e9f</color>
+    <color name="i_am_color_ea0">#00000ea0</color>
+    <color name="i_am_color_ea1">#00000ea1</color>
+    <color name="i_am_color_ea2">#00000ea2</color>
+    <color name="i_am_color_ea3">#00000ea3</color>
+    <color name="i_am_color_ea4">#00000ea4</color>
+    <color name="i_am_color_ea5">#00000ea5</color>
+    <color name="i_am_color_ea6">#00000ea6</color>
+    <color name="i_am_color_ea7">#00000ea7</color>
+    <color name="i_am_color_ea8">#00000ea8</color>
+    <color name="i_am_color_ea9">#00000ea9</color>
+    <color name="i_am_color_eaa">#00000eaa</color>
+    <color name="i_am_color_eab">#00000eab</color>
+    <color name="i_am_color_eac">#00000eac</color>
+    <color name="i_am_color_ead">#00000ead</color>
+    <color name="i_am_color_eae">#00000eae</color>
+    <color name="i_am_color_eaf">#00000eaf</color>
+    <color name="i_am_color_eb0">#00000eb0</color>
+    <color name="i_am_color_eb1">#00000eb1</color>
+    <color name="i_am_color_eb2">#00000eb2</color>
+    <color name="i_am_color_eb3">#00000eb3</color>
+    <color name="i_am_color_eb4">#00000eb4</color>
+    <color name="i_am_color_eb5">#00000eb5</color>
+    <color name="i_am_color_eb6">#00000eb6</color>
+    <color name="i_am_color_eb7">#00000eb7</color>
+    <color name="i_am_color_eb8">#00000eb8</color>
+    <color name="i_am_color_eb9">#00000eb9</color>
+    <color name="i_am_color_eba">#00000eba</color>
+    <color name="i_am_color_ebb">#00000ebb</color>
+    <color name="i_am_color_ebc">#00000ebc</color>
+    <color name="i_am_color_ebd">#00000ebd</color>
+    <color name="i_am_color_ebe">#00000ebe</color>
+    <color name="i_am_color_ebf">#00000ebf</color>
+    <color name="i_am_color_ec0">#00000ec0</color>
+    <color name="i_am_color_ec1">#00000ec1</color>
+    <color name="i_am_color_ec2">#00000ec2</color>
+    <color name="i_am_color_ec3">#00000ec3</color>
+    <color name="i_am_color_ec4">#00000ec4</color>
+    <color name="i_am_color_ec5">#00000ec5</color>
+    <color name="i_am_color_ec6">#00000ec6</color>
+    <color name="i_am_color_ec7">#00000ec7</color>
+    <color name="i_am_color_ec8">#00000ec8</color>
+    <color name="i_am_color_ec9">#00000ec9</color>
+    <color name="i_am_color_eca">#00000eca</color>
+    <color name="i_am_color_ecb">#00000ecb</color>
+    <color name="i_am_color_ecc">#00000ecc</color>
+    <color name="i_am_color_ecd">#00000ecd</color>
+    <color name="i_am_color_ece">#00000ece</color>
+    <color name="i_am_color_ecf">#00000ecf</color>
+    <color name="i_am_color_ed0">#00000ed0</color>
+    <color name="i_am_color_ed1">#00000ed1</color>
+    <color name="i_am_color_ed2">#00000ed2</color>
+    <color name="i_am_color_ed3">#00000ed3</color>
+    <color name="i_am_color_ed4">#00000ed4</color>
+    <color name="i_am_color_ed5">#00000ed5</color>
+    <color name="i_am_color_ed6">#00000ed6</color>
+    <color name="i_am_color_ed7">#00000ed7</color>
+    <color name="i_am_color_ed8">#00000ed8</color>
+    <color name="i_am_color_ed9">#00000ed9</color>
+    <color name="i_am_color_eda">#00000eda</color>
+    <color name="i_am_color_edb">#00000edb</color>
+    <color name="i_am_color_edc">#00000edc</color>
+    <color name="i_am_color_edd">#00000edd</color>
+    <color name="i_am_color_ede">#00000ede</color>
+    <color name="i_am_color_edf">#00000edf</color>
+    <color name="i_am_color_ee0">#00000ee0</color>
+    <color name="i_am_color_ee1">#00000ee1</color>
+    <color name="i_am_color_ee2">#00000ee2</color>
+    <color name="i_am_color_ee3">#00000ee3</color>
+    <color name="i_am_color_ee4">#00000ee4</color>
+    <color name="i_am_color_ee5">#00000ee5</color>
+    <color name="i_am_color_ee6">#00000ee6</color>
+    <color name="i_am_color_ee7">#00000ee7</color>
+    <color name="i_am_color_ee8">#00000ee8</color>
+    <color name="i_am_color_ee9">#00000ee9</color>
+    <color name="i_am_color_eea">#00000eea</color>
+    <color name="i_am_color_eeb">#00000eeb</color>
+    <color name="i_am_color_eec">#00000eec</color>
+    <color name="i_am_color_eed">#00000eed</color>
+    <color name="i_am_color_eee">#00000eee</color>
+    <color name="i_am_color_eef">#00000eef</color>
+    <color name="i_am_color_ef0">#00000ef0</color>
+    <color name="i_am_color_ef1">#00000ef1</color>
+    <color name="i_am_color_ef2">#00000ef2</color>
+    <color name="i_am_color_ef3">#00000ef3</color>
+    <color name="i_am_color_ef4">#00000ef4</color>
+    <color name="i_am_color_ef5">#00000ef5</color>
+    <color name="i_am_color_ef6">#00000ef6</color>
+    <color name="i_am_color_ef7">#00000ef7</color>
+    <color name="i_am_color_ef8">#00000ef8</color>
+    <color name="i_am_color_ef9">#00000ef9</color>
+    <color name="i_am_color_efa">#00000efa</color>
+    <color name="i_am_color_efb">#00000efb</color>
+    <color name="i_am_color_efc">#00000efc</color>
+    <color name="i_am_color_efd">#00000efd</color>
+    <color name="i_am_color_efe">#00000efe</color>
+    <color name="i_am_color_eff">#00000eff</color>
+    <color name="i_am_color_f00">#00000f00</color>
+    <color name="i_am_color_f01">#00000f01</color>
+    <color name="i_am_color_f02">#00000f02</color>
+    <color name="i_am_color_f03">#00000f03</color>
+    <color name="i_am_color_f04">#00000f04</color>
+    <color name="i_am_color_f05">#00000f05</color>
+    <color name="i_am_color_f06">#00000f06</color>
+    <color name="i_am_color_f07">#00000f07</color>
+    <color name="i_am_color_f08">#00000f08</color>
+    <color name="i_am_color_f09">#00000f09</color>
+    <color name="i_am_color_f0a">#00000f0a</color>
+    <color name="i_am_color_f0b">#00000f0b</color>
+    <color name="i_am_color_f0c">#00000f0c</color>
+    <color name="i_am_color_f0d">#00000f0d</color>
+    <color name="i_am_color_f0e">#00000f0e</color>
+    <color name="i_am_color_f0f">#00000f0f</color>
+    <color name="i_am_color_f10">#00000f10</color>
+    <color name="i_am_color_f11">#00000f11</color>
+    <color name="i_am_color_f12">#00000f12</color>
+    <color name="i_am_color_f13">#00000f13</color>
+    <color name="i_am_color_f14">#00000f14</color>
+    <color name="i_am_color_f15">#00000f15</color>
+    <color name="i_am_color_f16">#00000f16</color>
+    <color name="i_am_color_f17">#00000f17</color>
+    <color name="i_am_color_f18">#00000f18</color>
+    <color name="i_am_color_f19">#00000f19</color>
+    <color name="i_am_color_f1a">#00000f1a</color>
+    <color name="i_am_color_f1b">#00000f1b</color>
+    <color name="i_am_color_f1c">#00000f1c</color>
+    <color name="i_am_color_f1d">#00000f1d</color>
+    <color name="i_am_color_f1e">#00000f1e</color>
+    <color name="i_am_color_f1f">#00000f1f</color>
+    <color name="i_am_color_f20">#00000f20</color>
+    <color name="i_am_color_f21">#00000f21</color>
+    <color name="i_am_color_f22">#00000f22</color>
+    <color name="i_am_color_f23">#00000f23</color>
+    <color name="i_am_color_f24">#00000f24</color>
+    <color name="i_am_color_f25">#00000f25</color>
+    <color name="i_am_color_f26">#00000f26</color>
+    <color name="i_am_color_f27">#00000f27</color>
+    <color name="i_am_color_f28">#00000f28</color>
+    <color name="i_am_color_f29">#00000f29</color>
+    <color name="i_am_color_f2a">#00000f2a</color>
+    <color name="i_am_color_f2b">#00000f2b</color>
+    <color name="i_am_color_f2c">#00000f2c</color>
+    <color name="i_am_color_f2d">#00000f2d</color>
+    <color name="i_am_color_f2e">#00000f2e</color>
+    <color name="i_am_color_f2f">#00000f2f</color>
+    <color name="i_am_color_f30">#00000f30</color>
+    <color name="i_am_color_f31">#00000f31</color>
+    <color name="i_am_color_f32">#00000f32</color>
+    <color name="i_am_color_f33">#00000f33</color>
+    <color name="i_am_color_f34">#00000f34</color>
+    <color name="i_am_color_f35">#00000f35</color>
+    <color name="i_am_color_f36">#00000f36</color>
+    <color name="i_am_color_f37">#00000f37</color>
+    <color name="i_am_color_f38">#00000f38</color>
+    <color name="i_am_color_f39">#00000f39</color>
+    <color name="i_am_color_f3a">#00000f3a</color>
+    <color name="i_am_color_f3b">#00000f3b</color>
+    <color name="i_am_color_f3c">#00000f3c</color>
+    <color name="i_am_color_f3d">#00000f3d</color>
+    <color name="i_am_color_f3e">#00000f3e</color>
+    <color name="i_am_color_f3f">#00000f3f</color>
+    <color name="i_am_color_f40">#00000f40</color>
+    <color name="i_am_color_f41">#00000f41</color>
+    <color name="i_am_color_f42">#00000f42</color>
+    <color name="i_am_color_f43">#00000f43</color>
+    <color name="i_am_color_f44">#00000f44</color>
+    <color name="i_am_color_f45">#00000f45</color>
+    <color name="i_am_color_f46">#00000f46</color>
+    <color name="i_am_color_f47">#00000f47</color>
+    <color name="i_am_color_f48">#00000f48</color>
+    <color name="i_am_color_f49">#00000f49</color>
+    <color name="i_am_color_f4a">#00000f4a</color>
+    <color name="i_am_color_f4b">#00000f4b</color>
+    <color name="i_am_color_f4c">#00000f4c</color>
+    <color name="i_am_color_f4d">#00000f4d</color>
+    <color name="i_am_color_f4e">#00000f4e</color>
+    <color name="i_am_color_f4f">#00000f4f</color>
+    <color name="i_am_color_f50">#00000f50</color>
+    <color name="i_am_color_f51">#00000f51</color>
+    <color name="i_am_color_f52">#00000f52</color>
+    <color name="i_am_color_f53">#00000f53</color>
+    <color name="i_am_color_f54">#00000f54</color>
+    <color name="i_am_color_f55">#00000f55</color>
+    <color name="i_am_color_f56">#00000f56</color>
+    <color name="i_am_color_f57">#00000f57</color>
+    <color name="i_am_color_f58">#00000f58</color>
+    <color name="i_am_color_f59">#00000f59</color>
+    <color name="i_am_color_f5a">#00000f5a</color>
+    <color name="i_am_color_f5b">#00000f5b</color>
+    <color name="i_am_color_f5c">#00000f5c</color>
+    <color name="i_am_color_f5d">#00000f5d</color>
+    <color name="i_am_color_f5e">#00000f5e</color>
+    <color name="i_am_color_f5f">#00000f5f</color>
+    <color name="i_am_color_f60">#00000f60</color>
+    <color name="i_am_color_f61">#00000f61</color>
+    <color name="i_am_color_f62">#00000f62</color>
+    <color name="i_am_color_f63">#00000f63</color>
+    <color name="i_am_color_f64">#00000f64</color>
+    <color name="i_am_color_f65">#00000f65</color>
+    <color name="i_am_color_f66">#00000f66</color>
+    <color name="i_am_color_f67">#00000f67</color>
+    <color name="i_am_color_f68">#00000f68</color>
+    <color name="i_am_color_f69">#00000f69</color>
+    <color name="i_am_color_f6a">#00000f6a</color>
+    <color name="i_am_color_f6b">#00000f6b</color>
+    <color name="i_am_color_f6c">#00000f6c</color>
+    <color name="i_am_color_f6d">#00000f6d</color>
+    <color name="i_am_color_f6e">#00000f6e</color>
+    <color name="i_am_color_f6f">#00000f6f</color>
+    <color name="i_am_color_f70">#00000f70</color>
+    <color name="i_am_color_f71">#00000f71</color>
+    <color name="i_am_color_f72">#00000f72</color>
+    <color name="i_am_color_f73">#00000f73</color>
+    <color name="i_am_color_f74">#00000f74</color>
+    <color name="i_am_color_f75">#00000f75</color>
+    <color name="i_am_color_f76">#00000f76</color>
+    <color name="i_am_color_f77">#00000f77</color>
+    <color name="i_am_color_f78">#00000f78</color>
+    <color name="i_am_color_f79">#00000f79</color>
+    <color name="i_am_color_f7a">#00000f7a</color>
+    <color name="i_am_color_f7b">#00000f7b</color>
+    <color name="i_am_color_f7c">#00000f7c</color>
+    <color name="i_am_color_f7d">#00000f7d</color>
+    <color name="i_am_color_f7e">#00000f7e</color>
+    <color name="i_am_color_f7f">#00000f7f</color>
+    <color name="i_am_color_f80">#00000f80</color>
+    <color name="i_am_color_f81">#00000f81</color>
+    <color name="i_am_color_f82">#00000f82</color>
+    <color name="i_am_color_f83">#00000f83</color>
+    <color name="i_am_color_f84">#00000f84</color>
+    <color name="i_am_color_f85">#00000f85</color>
+    <color name="i_am_color_f86">#00000f86</color>
+    <color name="i_am_color_f87">#00000f87</color>
+    <color name="i_am_color_f88">#00000f88</color>
+    <color name="i_am_color_f89">#00000f89</color>
+    <color name="i_am_color_f8a">#00000f8a</color>
+    <color name="i_am_color_f8b">#00000f8b</color>
+    <color name="i_am_color_f8c">#00000f8c</color>
+    <color name="i_am_color_f8d">#00000f8d</color>
+    <color name="i_am_color_f8e">#00000f8e</color>
+    <color name="i_am_color_f8f">#00000f8f</color>
+    <color name="i_am_color_f90">#00000f90</color>
+    <color name="i_am_color_f91">#00000f91</color>
+    <color name="i_am_color_f92">#00000f92</color>
+    <color name="i_am_color_f93">#00000f93</color>
+    <color name="i_am_color_f94">#00000f94</color>
+    <color name="i_am_color_f95">#00000f95</color>
+    <color name="i_am_color_f96">#00000f96</color>
+    <color name="i_am_color_f97">#00000f97</color>
+    <color name="i_am_color_f98">#00000f98</color>
+    <color name="i_am_color_f99">#00000f99</color>
+    <color name="i_am_color_f9a">#00000f9a</color>
+    <color name="i_am_color_f9b">#00000f9b</color>
+    <color name="i_am_color_f9c">#00000f9c</color>
+    <color name="i_am_color_f9d">#00000f9d</color>
+    <color name="i_am_color_f9e">#00000f9e</color>
+    <color name="i_am_color_f9f">#00000f9f</color>
+    <color name="i_am_color_fa0">#00000fa0</color>
+    <color name="i_am_color_fa1">#00000fa1</color>
+    <color name="i_am_color_fa2">#00000fa2</color>
+    <color name="i_am_color_fa3">#00000fa3</color>
+    <color name="i_am_color_fa4">#00000fa4</color>
+    <color name="i_am_color_fa5">#00000fa5</color>
+    <color name="i_am_color_fa6">#00000fa6</color>
+    <color name="i_am_color_fa7">#00000fa7</color>
+    <color name="i_am_color_fa8">#00000fa8</color>
+    <color name="i_am_color_fa9">#00000fa9</color>
+    <color name="i_am_color_faa">#00000faa</color>
+    <color name="i_am_color_fab">#00000fab</color>
+    <color name="i_am_color_fac">#00000fac</color>
+    <color name="i_am_color_fad">#00000fad</color>
+    <color name="i_am_color_fae">#00000fae</color>
+    <color name="i_am_color_faf">#00000faf</color>
+    <color name="i_am_color_fb0">#00000fb0</color>
+    <color name="i_am_color_fb1">#00000fb1</color>
+    <color name="i_am_color_fb2">#00000fb2</color>
+    <color name="i_am_color_fb3">#00000fb3</color>
+    <color name="i_am_color_fb4">#00000fb4</color>
+    <color name="i_am_color_fb5">#00000fb5</color>
+    <color name="i_am_color_fb6">#00000fb6</color>
+    <color name="i_am_color_fb7">#00000fb7</color>
+    <color name="i_am_color_fb8">#00000fb8</color>
+    <color name="i_am_color_fb9">#00000fb9</color>
+    <color name="i_am_color_fba">#00000fba</color>
+    <color name="i_am_color_fbb">#00000fbb</color>
+    <color name="i_am_color_fbc">#00000fbc</color>
+    <color name="i_am_color_fbd">#00000fbd</color>
+    <color name="i_am_color_fbe">#00000fbe</color>
+    <color name="i_am_color_fbf">#00000fbf</color>
+    <color name="i_am_color_fc0">#00000fc0</color>
+    <color name="i_am_color_fc1">#00000fc1</color>
+    <color name="i_am_color_fc2">#00000fc2</color>
+    <color name="i_am_color_fc3">#00000fc3</color>
+    <color name="i_am_color_fc4">#00000fc4</color>
+    <color name="i_am_color_fc5">#00000fc5</color>
+    <color name="i_am_color_fc6">#00000fc6</color>
+    <color name="i_am_color_fc7">#00000fc7</color>
+    <color name="i_am_color_fc8">#00000fc8</color>
+    <color name="i_am_color_fc9">#00000fc9</color>
+    <color name="i_am_color_fca">#00000fca</color>
+    <color name="i_am_color_fcb">#00000fcb</color>
+    <color name="i_am_color_fcc">#00000fcc</color>
+    <color name="i_am_color_fcd">#00000fcd</color>
+    <color name="i_am_color_fce">#00000fce</color>
+    <color name="i_am_color_fcf">#00000fcf</color>
+    <color name="i_am_color_fd0">#00000fd0</color>
+    <color name="i_am_color_fd1">#00000fd1</color>
+    <color name="i_am_color_fd2">#00000fd2</color>
+    <color name="i_am_color_fd3">#00000fd3</color>
+    <color name="i_am_color_fd4">#00000fd4</color>
+    <color name="i_am_color_fd5">#00000fd5</color>
+    <color name="i_am_color_fd6">#00000fd6</color>
+    <color name="i_am_color_fd7">#00000fd7</color>
+    <color name="i_am_color_fd8">#00000fd8</color>
+    <color name="i_am_color_fd9">#00000fd9</color>
+    <color name="i_am_color_fda">#00000fda</color>
+    <color name="i_am_color_fdb">#00000fdb</color>
+    <color name="i_am_color_fdc">#00000fdc</color>
+    <color name="i_am_color_fdd">#00000fdd</color>
+    <color name="i_am_color_fde">#00000fde</color>
+    <color name="i_am_color_fdf">#00000fdf</color>
+    <color name="i_am_color_fe0">#00000fe0</color>
+    <color name="i_am_color_fe1">#00000fe1</color>
+    <color name="i_am_color_fe2">#00000fe2</color>
+    <color name="i_am_color_fe3">#00000fe3</color>
+    <color name="i_am_color_fe4">#00000fe4</color>
+    <color name="i_am_color_fe5">#00000fe5</color>
+    <color name="i_am_color_fe6">#00000fe6</color>
+    <color name="i_am_color_fe7">#00000fe7</color>
+    <color name="i_am_color_fe8">#00000fe8</color>
+    <color name="i_am_color_fe9">#00000fe9</color>
+    <color name="i_am_color_fea">#00000fea</color>
+    <color name="i_am_color_feb">#00000feb</color>
+    <color name="i_am_color_fec">#00000fec</color>
+    <color name="i_am_color_fed">#00000fed</color>
+    <color name="i_am_color_fee">#00000fee</color>
+    <color name="i_am_color_fef">#00000fef</color>
+    <color name="i_am_color_ff0">#00000ff0</color>
+    <color name="i_am_color_ff1">#00000ff1</color>
+    <color name="i_am_color_ff2">#00000ff2</color>
+    <color name="i_am_color_ff3">#00000ff3</color>
+    <color name="i_am_color_ff4">#00000ff4</color>
+    <color name="i_am_color_ff5">#00000ff5</color>
+    <color name="i_am_color_ff6">#00000ff6</color>
+    <color name="i_am_color_ff7">#00000ff7</color>
+    <color name="i_am_color_ff8">#00000ff8</color>
+    <color name="i_am_color_ff9">#00000ff9</color>
+    <color name="i_am_color_ffa">#00000ffa</color>
+    <color name="i_am_color_ffb">#00000ffb</color>
+    <color name="i_am_color_ffc">#00000ffc</color>
+    <color name="i_am_color_ffd">#00000ffd</color>
+    <color name="i_am_color_ffe">#00000ffe</color>
+    <color name="i_am_color_fff">#00000fff</color>
+    <color name="i_am_color_1000">#00001000</color>
+    <color name="i_am_color_1001">#00001001</color>
+    <color name="i_am_color_1002">#00001002</color>
+    <color name="i_am_color_1003">#00001003</color>
+    <color name="i_am_color_1004">#00001004</color>
+    <color name="i_am_color_1005">#00001005</color>
+    <color name="i_am_color_1006">#00001006</color>
+    <color name="i_am_color_1007">#00001007</color>
+    <color name="i_am_color_1008">#00001008</color>
+    <color name="i_am_color_1009">#00001009</color>
+    <color name="i_am_color_100a">#0000100a</color>
+    <color name="i_am_color_100b">#0000100b</color>
+    <color name="i_am_color_100c">#0000100c</color>
+    <color name="i_am_color_100d">#0000100d</color>
+    <color name="i_am_color_100e">#0000100e</color>
+    <color name="i_am_color_100f">#0000100f</color>
+    <color name="i_am_color_1010">#00001010</color>
+    <color name="i_am_color_1011">#00001011</color>
+    <color name="i_am_color_1012">#00001012</color>
+    <color name="i_am_color_1013">#00001013</color>
+    <color name="i_am_color_1014">#00001014</color>
+    <color name="i_am_color_1015">#00001015</color>
+    <color name="i_am_color_1016">#00001016</color>
+    <color name="i_am_color_1017">#00001017</color>
+    <color name="i_am_color_1018">#00001018</color>
+    <color name="i_am_color_1019">#00001019</color>
+    <color name="i_am_color_101a">#0000101a</color>
+    <color name="i_am_color_101b">#0000101b</color>
+    <color name="i_am_color_101c">#0000101c</color>
+    <color name="i_am_color_101d">#0000101d</color>
+    <color name="i_am_color_101e">#0000101e</color>
+    <color name="i_am_color_101f">#0000101f</color>
+    <color name="i_am_color_1020">#00001020</color>
+    <color name="i_am_color_1021">#00001021</color>
+    <color name="i_am_color_1022">#00001022</color>
+    <color name="i_am_color_1023">#00001023</color>
+    <color name="i_am_color_1024">#00001024</color>
+    <color name="i_am_color_1025">#00001025</color>
+    <color name="i_am_color_1026">#00001026</color>
+    <color name="i_am_color_1027">#00001027</color>
+    <color name="i_am_color_1028">#00001028</color>
+    <color name="i_am_color_1029">#00001029</color>
+    <color name="i_am_color_102a">#0000102a</color>
+    <color name="i_am_color_102b">#0000102b</color>
+    <color name="i_am_color_102c">#0000102c</color>
+    <color name="i_am_color_102d">#0000102d</color>
+    <color name="i_am_color_102e">#0000102e</color>
+    <color name="i_am_color_102f">#0000102f</color>
+    <color name="i_am_color_1030">#00001030</color>
+    <color name="i_am_color_1031">#00001031</color>
+    <color name="i_am_color_1032">#00001032</color>
+    <color name="i_am_color_1033">#00001033</color>
+    <color name="i_am_color_1034">#00001034</color>
+    <color name="i_am_color_1035">#00001035</color>
+    <color name="i_am_color_1036">#00001036</color>
+    <color name="i_am_color_1037">#00001037</color>
+    <color name="i_am_color_1038">#00001038</color>
+    <color name="i_am_color_1039">#00001039</color>
+    <color name="i_am_color_103a">#0000103a</color>
+    <color name="i_am_color_103b">#0000103b</color>
+    <color name="i_am_color_103c">#0000103c</color>
+    <color name="i_am_color_103d">#0000103d</color>
+    <color name="i_am_color_103e">#0000103e</color>
+    <color name="i_am_color_103f">#0000103f</color>
+    <color name="i_am_color_1040">#00001040</color>
+    <color name="i_am_color_1041">#00001041</color>
+    <color name="i_am_color_1042">#00001042</color>
+    <color name="i_am_color_1043">#00001043</color>
+    <color name="i_am_color_1044">#00001044</color>
+    <color name="i_am_color_1045">#00001045</color>
+    <color name="i_am_color_1046">#00001046</color>
+    <color name="i_am_color_1047">#00001047</color>
+    <color name="i_am_color_1048">#00001048</color>
+    <color name="i_am_color_1049">#00001049</color>
+    <color name="i_am_color_104a">#0000104a</color>
+    <color name="i_am_color_104b">#0000104b</color>
+    <color name="i_am_color_104c">#0000104c</color>
+    <color name="i_am_color_104d">#0000104d</color>
+    <color name="i_am_color_104e">#0000104e</color>
+    <color name="i_am_color_104f">#0000104f</color>
+    <color name="i_am_color_1050">#00001050</color>
+    <color name="i_am_color_1051">#00001051</color>
+    <color name="i_am_color_1052">#00001052</color>
+    <color name="i_am_color_1053">#00001053</color>
+    <color name="i_am_color_1054">#00001054</color>
+    <color name="i_am_color_1055">#00001055</color>
+    <color name="i_am_color_1056">#00001056</color>
+    <color name="i_am_color_1057">#00001057</color>
+    <color name="i_am_color_1058">#00001058</color>
+    <color name="i_am_color_1059">#00001059</color>
+    <color name="i_am_color_105a">#0000105a</color>
+    <color name="i_am_color_105b">#0000105b</color>
+    <color name="i_am_color_105c">#0000105c</color>
+    <color name="i_am_color_105d">#0000105d</color>
+    <color name="i_am_color_105e">#0000105e</color>
+    <color name="i_am_color_105f">#0000105f</color>
+    <color name="i_am_color_1060">#00001060</color>
+    <color name="i_am_color_1061">#00001061</color>
+    <color name="i_am_color_1062">#00001062</color>
+    <color name="i_am_color_1063">#00001063</color>
+    <color name="i_am_color_1064">#00001064</color>
+    <color name="i_am_color_1065">#00001065</color>
+    <color name="i_am_color_1066">#00001066</color>
+    <color name="i_am_color_1067">#00001067</color>
+    <color name="i_am_color_1068">#00001068</color>
+    <color name="i_am_color_1069">#00001069</color>
+    <color name="i_am_color_106a">#0000106a</color>
+    <color name="i_am_color_106b">#0000106b</color>
+    <color name="i_am_color_106c">#0000106c</color>
+    <color name="i_am_color_106d">#0000106d</color>
+    <color name="i_am_color_106e">#0000106e</color>
+    <color name="i_am_color_106f">#0000106f</color>
+    <color name="i_am_color_1070">#00001070</color>
+    <color name="i_am_color_1071">#00001071</color>
+    <color name="i_am_color_1072">#00001072</color>
+    <color name="i_am_color_1073">#00001073</color>
+    <color name="i_am_color_1074">#00001074</color>
+    <color name="i_am_color_1075">#00001075</color>
+    <color name="i_am_color_1076">#00001076</color>
+    <color name="i_am_color_1077">#00001077</color>
+    <color name="i_am_color_1078">#00001078</color>
+    <color name="i_am_color_1079">#00001079</color>
+    <color name="i_am_color_107a">#0000107a</color>
+    <color name="i_am_color_107b">#0000107b</color>
+    <color name="i_am_color_107c">#0000107c</color>
+    <color name="i_am_color_107d">#0000107d</color>
+    <color name="i_am_color_107e">#0000107e</color>
+    <color name="i_am_color_107f">#0000107f</color>
+    <color name="i_am_color_1080">#00001080</color>
+    <color name="i_am_color_1081">#00001081</color>
+    <color name="i_am_color_1082">#00001082</color>
+    <color name="i_am_color_1083">#00001083</color>
+    <color name="i_am_color_1084">#00001084</color>
+    <color name="i_am_color_1085">#00001085</color>
+    <color name="i_am_color_1086">#00001086</color>
+    <color name="i_am_color_1087">#00001087</color>
+    <color name="i_am_color_1088">#00001088</color>
+    <color name="i_am_color_1089">#00001089</color>
+    <color name="i_am_color_108a">#0000108a</color>
+    <color name="i_am_color_108b">#0000108b</color>
+    <color name="i_am_color_108c">#0000108c</color>
+    <color name="i_am_color_108d">#0000108d</color>
+    <color name="i_am_color_108e">#0000108e</color>
+    <color name="i_am_color_108f">#0000108f</color>
+    <color name="i_am_color_1090">#00001090</color>
+    <color name="i_am_color_1091">#00001091</color>
+    <color name="i_am_color_1092">#00001092</color>
+    <color name="i_am_color_1093">#00001093</color>
+    <color name="i_am_color_1094">#00001094</color>
+    <color name="i_am_color_1095">#00001095</color>
+    <color name="i_am_color_1096">#00001096</color>
+    <color name="i_am_color_1097">#00001097</color>
+    <color name="i_am_color_1098">#00001098</color>
+    <color name="i_am_color_1099">#00001099</color>
+    <color name="i_am_color_109a">#0000109a</color>
+    <color name="i_am_color_109b">#0000109b</color>
+    <color name="i_am_color_109c">#0000109c</color>
+    <color name="i_am_color_109d">#0000109d</color>
+    <color name="i_am_color_109e">#0000109e</color>
+    <color name="i_am_color_109f">#0000109f</color>
+    <color name="i_am_color_10a0">#000010a0</color>
+    <color name="i_am_color_10a1">#000010a1</color>
+    <color name="i_am_color_10a2">#000010a2</color>
+    <color name="i_am_color_10a3">#000010a3</color>
+    <color name="i_am_color_10a4">#000010a4</color>
+    <color name="i_am_color_10a5">#000010a5</color>
+    <color name="i_am_color_10a6">#000010a6</color>
+    <color name="i_am_color_10a7">#000010a7</color>
+    <color name="i_am_color_10a8">#000010a8</color>
+    <color name="i_am_color_10a9">#000010a9</color>
+    <color name="i_am_color_10aa">#000010aa</color>
+    <color name="i_am_color_10ab">#000010ab</color>
+    <color name="i_am_color_10ac">#000010ac</color>
+    <color name="i_am_color_10ad">#000010ad</color>
+    <color name="i_am_color_10ae">#000010ae</color>
+    <color name="i_am_color_10af">#000010af</color>
+    <color name="i_am_color_10b0">#000010b0</color>
+    <color name="i_am_color_10b1">#000010b1</color>
+    <color name="i_am_color_10b2">#000010b2</color>
+    <color name="i_am_color_10b3">#000010b3</color>
+    <color name="i_am_color_10b4">#000010b4</color>
+    <color name="i_am_color_10b5">#000010b5</color>
+    <color name="i_am_color_10b6">#000010b6</color>
+    <color name="i_am_color_10b7">#000010b7</color>
+    <color name="i_am_color_10b8">#000010b8</color>
+    <color name="i_am_color_10b9">#000010b9</color>
+    <color name="i_am_color_10ba">#000010ba</color>
+    <color name="i_am_color_10bb">#000010bb</color>
+    <color name="i_am_color_10bc">#000010bc</color>
+    <color name="i_am_color_10bd">#000010bd</color>
+    <color name="i_am_color_10be">#000010be</color>
+    <color name="i_am_color_10bf">#000010bf</color>
+    <color name="i_am_color_10c0">#000010c0</color>
+    <color name="i_am_color_10c1">#000010c1</color>
+    <color name="i_am_color_10c2">#000010c2</color>
+    <color name="i_am_color_10c3">#000010c3</color>
+    <color name="i_am_color_10c4">#000010c4</color>
+    <color name="i_am_color_10c5">#000010c5</color>
+    <color name="i_am_color_10c6">#000010c6</color>
+    <color name="i_am_color_10c7">#000010c7</color>
+    <color name="i_am_color_10c8">#000010c8</color>
+    <color name="i_am_color_10c9">#000010c9</color>
+    <color name="i_am_color_10ca">#000010ca</color>
+    <color name="i_am_color_10cb">#000010cb</color>
+    <color name="i_am_color_10cc">#000010cc</color>
+    <color name="i_am_color_10cd">#000010cd</color>
+    <color name="i_am_color_10ce">#000010ce</color>
+    <color name="i_am_color_10cf">#000010cf</color>
+    <color name="i_am_color_10d0">#000010d0</color>
+    <color name="i_am_color_10d1">#000010d1</color>
+    <color name="i_am_color_10d2">#000010d2</color>
+    <color name="i_am_color_10d3">#000010d3</color>
+    <color name="i_am_color_10d4">#000010d4</color>
+    <color name="i_am_color_10d5">#000010d5</color>
+    <color name="i_am_color_10d6">#000010d6</color>
+    <color name="i_am_color_10d7">#000010d7</color>
+    <color name="i_am_color_10d8">#000010d8</color>
+    <color name="i_am_color_10d9">#000010d9</color>
+    <color name="i_am_color_10da">#000010da</color>
+    <color name="i_am_color_10db">#000010db</color>
+    <color name="i_am_color_10dc">#000010dc</color>
+    <color name="i_am_color_10dd">#000010dd</color>
+    <color name="i_am_color_10de">#000010de</color>
+    <color name="i_am_color_10df">#000010df</color>
+    <color name="i_am_color_10e0">#000010e0</color>
+    <color name="i_am_color_10e1">#000010e1</color>
+    <color name="i_am_color_10e2">#000010e2</color>
+    <color name="i_am_color_10e3">#000010e3</color>
+    <color name="i_am_color_10e4">#000010e4</color>
+    <color name="i_am_color_10e5">#000010e5</color>
+    <color name="i_am_color_10e6">#000010e6</color>
+    <color name="i_am_color_10e7">#000010e7</color>
+    <color name="i_am_color_10e8">#000010e8</color>
+    <color name="i_am_color_10e9">#000010e9</color>
+    <color name="i_am_color_10ea">#000010ea</color>
+    <color name="i_am_color_10eb">#000010eb</color>
+    <color name="i_am_color_10ec">#000010ec</color>
+    <color name="i_am_color_10ed">#000010ed</color>
+    <color name="i_am_color_10ee">#000010ee</color>
+    <color name="i_am_color_10ef">#000010ef</color>
+    <color name="i_am_color_10f0">#000010f0</color>
+    <color name="i_am_color_10f1">#000010f1</color>
+    <color name="i_am_color_10f2">#000010f2</color>
+    <color name="i_am_color_10f3">#000010f3</color>
+    <color name="i_am_color_10f4">#000010f4</color>
+    <color name="i_am_color_10f5">#000010f5</color>
+    <color name="i_am_color_10f6">#000010f6</color>
+    <color name="i_am_color_10f7">#000010f7</color>
+    <color name="i_am_color_10f8">#000010f8</color>
+    <color name="i_am_color_10f9">#000010f9</color>
+    <color name="i_am_color_10fa">#000010fa</color>
+    <color name="i_am_color_10fb">#000010fb</color>
+    <color name="i_am_color_10fc">#000010fc</color>
+    <color name="i_am_color_10fd">#000010fd</color>
+    <color name="i_am_color_10fe">#000010fe</color>
+    <color name="i_am_color_10ff">#000010ff</color>
+    <color name="i_am_color_1100">#00001100</color>
+    <color name="i_am_color_1101">#00001101</color>
+    <color name="i_am_color_1102">#00001102</color>
+    <color name="i_am_color_1103">#00001103</color>
+    <color name="i_am_color_1104">#00001104</color>
+    <color name="i_am_color_1105">#00001105</color>
+    <color name="i_am_color_1106">#00001106</color>
+    <color name="i_am_color_1107">#00001107</color>
+    <color name="i_am_color_1108">#00001108</color>
+    <color name="i_am_color_1109">#00001109</color>
+    <color name="i_am_color_110a">#0000110a</color>
+    <color name="i_am_color_110b">#0000110b</color>
+    <color name="i_am_color_110c">#0000110c</color>
+    <color name="i_am_color_110d">#0000110d</color>
+    <color name="i_am_color_110e">#0000110e</color>
+    <color name="i_am_color_110f">#0000110f</color>
+    <color name="i_am_color_1110">#00001110</color>
+    <color name="i_am_color_1111">#00001111</color>
+    <color name="i_am_color_1112">#00001112</color>
+    <color name="i_am_color_1113">#00001113</color>
+    <color name="i_am_color_1114">#00001114</color>
+    <color name="i_am_color_1115">#00001115</color>
+    <color name="i_am_color_1116">#00001116</color>
+    <color name="i_am_color_1117">#00001117</color>
+    <color name="i_am_color_1118">#00001118</color>
+    <color name="i_am_color_1119">#00001119</color>
+    <color name="i_am_color_111a">#0000111a</color>
+    <color name="i_am_color_111b">#0000111b</color>
+    <color name="i_am_color_111c">#0000111c</color>
+    <color name="i_am_color_111d">#0000111d</color>
+    <color name="i_am_color_111e">#0000111e</color>
+    <color name="i_am_color_111f">#0000111f</color>
+    <color name="i_am_color_1120">#00001120</color>
+    <color name="i_am_color_1121">#00001121</color>
+    <color name="i_am_color_1122">#00001122</color>
+    <color name="i_am_color_1123">#00001123</color>
+    <color name="i_am_color_1124">#00001124</color>
+    <color name="i_am_color_1125">#00001125</color>
+    <color name="i_am_color_1126">#00001126</color>
+    <color name="i_am_color_1127">#00001127</color>
+    <color name="i_am_color_1128">#00001128</color>
+    <color name="i_am_color_1129">#00001129</color>
+    <color name="i_am_color_112a">#0000112a</color>
+    <color name="i_am_color_112b">#0000112b</color>
+    <color name="i_am_color_112c">#0000112c</color>
+    <color name="i_am_color_112d">#0000112d</color>
+    <color name="i_am_color_112e">#0000112e</color>
+    <color name="i_am_color_112f">#0000112f</color>
+    <color name="i_am_color_1130">#00001130</color>
+    <color name="i_am_color_1131">#00001131</color>
+    <color name="i_am_color_1132">#00001132</color>
+    <color name="i_am_color_1133">#00001133</color>
+    <color name="i_am_color_1134">#00001134</color>
+    <color name="i_am_color_1135">#00001135</color>
+    <color name="i_am_color_1136">#00001136</color>
+    <color name="i_am_color_1137">#00001137</color>
+    <color name="i_am_color_1138">#00001138</color>
+    <color name="i_am_color_1139">#00001139</color>
+    <color name="i_am_color_113a">#0000113a</color>
+    <color name="i_am_color_113b">#0000113b</color>
+    <color name="i_am_color_113c">#0000113c</color>
+    <color name="i_am_color_113d">#0000113d</color>
+    <color name="i_am_color_113e">#0000113e</color>
+    <color name="i_am_color_113f">#0000113f</color>
+    <color name="i_am_color_1140">#00001140</color>
+    <color name="i_am_color_1141">#00001141</color>
+    <color name="i_am_color_1142">#00001142</color>
+    <color name="i_am_color_1143">#00001143</color>
+    <color name="i_am_color_1144">#00001144</color>
+    <color name="i_am_color_1145">#00001145</color>
+    <color name="i_am_color_1146">#00001146</color>
+    <color name="i_am_color_1147">#00001147</color>
+    <color name="i_am_color_1148">#00001148</color>
+    <color name="i_am_color_1149">#00001149</color>
+    <color name="i_am_color_114a">#0000114a</color>
+    <color name="i_am_color_114b">#0000114b</color>
+    <color name="i_am_color_114c">#0000114c</color>
+    <color name="i_am_color_114d">#0000114d</color>
+    <color name="i_am_color_114e">#0000114e</color>
+    <color name="i_am_color_114f">#0000114f</color>
+    <color name="i_am_color_1150">#00001150</color>
+    <color name="i_am_color_1151">#00001151</color>
+    <color name="i_am_color_1152">#00001152</color>
+    <color name="i_am_color_1153">#00001153</color>
+    <color name="i_am_color_1154">#00001154</color>
+    <color name="i_am_color_1155">#00001155</color>
+    <color name="i_am_color_1156">#00001156</color>
+    <color name="i_am_color_1157">#00001157</color>
+    <color name="i_am_color_1158">#00001158</color>
+    <color name="i_am_color_1159">#00001159</color>
+    <color name="i_am_color_115a">#0000115a</color>
+    <color name="i_am_color_115b">#0000115b</color>
+    <color name="i_am_color_115c">#0000115c</color>
+    <color name="i_am_color_115d">#0000115d</color>
+    <color name="i_am_color_115e">#0000115e</color>
+    <color name="i_am_color_115f">#0000115f</color>
+    <color name="i_am_color_1160">#00001160</color>
+    <color name="i_am_color_1161">#00001161</color>
+    <color name="i_am_color_1162">#00001162</color>
+    <color name="i_am_color_1163">#00001163</color>
+    <color name="i_am_color_1164">#00001164</color>
+    <color name="i_am_color_1165">#00001165</color>
+    <color name="i_am_color_1166">#00001166</color>
+    <color name="i_am_color_1167">#00001167</color>
+    <color name="i_am_color_1168">#00001168</color>
+    <color name="i_am_color_1169">#00001169</color>
+    <color name="i_am_color_116a">#0000116a</color>
+    <color name="i_am_color_116b">#0000116b</color>
+    <color name="i_am_color_116c">#0000116c</color>
+    <color name="i_am_color_116d">#0000116d</color>
+    <color name="i_am_color_116e">#0000116e</color>
+    <color name="i_am_color_116f">#0000116f</color>
+    <color name="i_am_color_1170">#00001170</color>
+    <color name="i_am_color_1171">#00001171</color>
+    <color name="i_am_color_1172">#00001172</color>
+    <color name="i_am_color_1173">#00001173</color>
+    <color name="i_am_color_1174">#00001174</color>
+    <color name="i_am_color_1175">#00001175</color>
+    <color name="i_am_color_1176">#00001176</color>
+    <color name="i_am_color_1177">#00001177</color>
+    <color name="i_am_color_1178">#00001178</color>
+    <color name="i_am_color_1179">#00001179</color>
+    <color name="i_am_color_117a">#0000117a</color>
+    <color name="i_am_color_117b">#0000117b</color>
+    <color name="i_am_color_117c">#0000117c</color>
+    <color name="i_am_color_117d">#0000117d</color>
+    <color name="i_am_color_117e">#0000117e</color>
+    <color name="i_am_color_117f">#0000117f</color>
+    <color name="i_am_color_1180">#00001180</color>
+    <color name="i_am_color_1181">#00001181</color>
+    <color name="i_am_color_1182">#00001182</color>
+    <color name="i_am_color_1183">#00001183</color>
+    <color name="i_am_color_1184">#00001184</color>
+    <color name="i_am_color_1185">#00001185</color>
+    <color name="i_am_color_1186">#00001186</color>
+    <color name="i_am_color_1187">#00001187</color>
+    <color name="i_am_color_1188">#00001188</color>
+    <color name="i_am_color_1189">#00001189</color>
+    <color name="i_am_color_118a">#0000118a</color>
+    <color name="i_am_color_118b">#0000118b</color>
+    <color name="i_am_color_118c">#0000118c</color>
+    <color name="i_am_color_118d">#0000118d</color>
+    <color name="i_am_color_118e">#0000118e</color>
+    <color name="i_am_color_118f">#0000118f</color>
+    <color name="i_am_color_1190">#00001190</color>
+    <color name="i_am_color_1191">#00001191</color>
+    <color name="i_am_color_1192">#00001192</color>
+    <color name="i_am_color_1193">#00001193</color>
+    <color name="i_am_color_1194">#00001194</color>
+    <color name="i_am_color_1195">#00001195</color>
+    <color name="i_am_color_1196">#00001196</color>
+    <color name="i_am_color_1197">#00001197</color>
+    <color name="i_am_color_1198">#00001198</color>
+    <color name="i_am_color_1199">#00001199</color>
+    <color name="i_am_color_119a">#0000119a</color>
+    <color name="i_am_color_119b">#0000119b</color>
+    <color name="i_am_color_119c">#0000119c</color>
+    <color name="i_am_color_119d">#0000119d</color>
+    <color name="i_am_color_119e">#0000119e</color>
+    <color name="i_am_color_119f">#0000119f</color>
+    <color name="i_am_color_11a0">#000011a0</color>
+    <color name="i_am_color_11a1">#000011a1</color>
+    <color name="i_am_color_11a2">#000011a2</color>
+    <color name="i_am_color_11a3">#000011a3</color>
+    <color name="i_am_color_11a4">#000011a4</color>
+    <color name="i_am_color_11a5">#000011a5</color>
+    <color name="i_am_color_11a6">#000011a6</color>
+    <color name="i_am_color_11a7">#000011a7</color>
+    <color name="i_am_color_11a8">#000011a8</color>
+    <color name="i_am_color_11a9">#000011a9</color>
+    <color name="i_am_color_11aa">#000011aa</color>
+    <color name="i_am_color_11ab">#000011ab</color>
+    <color name="i_am_color_11ac">#000011ac</color>
+    <color name="i_am_color_11ad">#000011ad</color>
+    <color name="i_am_color_11ae">#000011ae</color>
+    <color name="i_am_color_11af">#000011af</color>
+    <color name="i_am_color_11b0">#000011b0</color>
+    <color name="i_am_color_11b1">#000011b1</color>
+    <color name="i_am_color_11b2">#000011b2</color>
+    <color name="i_am_color_11b3">#000011b3</color>
+    <color name="i_am_color_11b4">#000011b4</color>
+    <color name="i_am_color_11b5">#000011b5</color>
+    <color name="i_am_color_11b6">#000011b6</color>
+    <color name="i_am_color_11b7">#000011b7</color>
+    <color name="i_am_color_11b8">#000011b8</color>
+    <color name="i_am_color_11b9">#000011b9</color>
+    <color name="i_am_color_11ba">#000011ba</color>
+    <color name="i_am_color_11bb">#000011bb</color>
+    <color name="i_am_color_11bc">#000011bc</color>
+    <color name="i_am_color_11bd">#000011bd</color>
+    <color name="i_am_color_11be">#000011be</color>
+    <color name="i_am_color_11bf">#000011bf</color>
+    <color name="i_am_color_11c0">#000011c0</color>
+    <color name="i_am_color_11c1">#000011c1</color>
+    <color name="i_am_color_11c2">#000011c2</color>
+    <color name="i_am_color_11c3">#000011c3</color>
+    <color name="i_am_color_11c4">#000011c4</color>
+    <color name="i_am_color_11c5">#000011c5</color>
+    <color name="i_am_color_11c6">#000011c6</color>
+    <color name="i_am_color_11c7">#000011c7</color>
+    <color name="i_am_color_11c8">#000011c8</color>
+    <color name="i_am_color_11c9">#000011c9</color>
+    <color name="i_am_color_11ca">#000011ca</color>
+    <color name="i_am_color_11cb">#000011cb</color>
+    <color name="i_am_color_11cc">#000011cc</color>
+    <color name="i_am_color_11cd">#000011cd</color>
+    <color name="i_am_color_11ce">#000011ce</color>
+    <color name="i_am_color_11cf">#000011cf</color>
+    <color name="i_am_color_11d0">#000011d0</color>
+    <color name="i_am_color_11d1">#000011d1</color>
+    <color name="i_am_color_11d2">#000011d2</color>
+    <color name="i_am_color_11d3">#000011d3</color>
+    <color name="i_am_color_11d4">#000011d4</color>
+    <color name="i_am_color_11d5">#000011d5</color>
+    <color name="i_am_color_11d6">#000011d6</color>
+    <color name="i_am_color_11d7">#000011d7</color>
+    <color name="i_am_color_11d8">#000011d8</color>
+    <color name="i_am_color_11d9">#000011d9</color>
+    <color name="i_am_color_11da">#000011da</color>
+    <color name="i_am_color_11db">#000011db</color>
+    <color name="i_am_color_11dc">#000011dc</color>
+    <color name="i_am_color_11dd">#000011dd</color>
+    <color name="i_am_color_11de">#000011de</color>
+    <color name="i_am_color_11df">#000011df</color>
+    <color name="i_am_color_11e0">#000011e0</color>
+    <color name="i_am_color_11e1">#000011e1</color>
+    <color name="i_am_color_11e2">#000011e2</color>
+    <color name="i_am_color_11e3">#000011e3</color>
+    <color name="i_am_color_11e4">#000011e4</color>
+    <color name="i_am_color_11e5">#000011e5</color>
+    <color name="i_am_color_11e6">#000011e6</color>
+    <color name="i_am_color_11e7">#000011e7</color>
+    <color name="i_am_color_11e8">#000011e8</color>
+    <color name="i_am_color_11e9">#000011e9</color>
+    <color name="i_am_color_11ea">#000011ea</color>
+    <color name="i_am_color_11eb">#000011eb</color>
+    <color name="i_am_color_11ec">#000011ec</color>
+    <color name="i_am_color_11ed">#000011ed</color>
+    <color name="i_am_color_11ee">#000011ee</color>
+    <color name="i_am_color_11ef">#000011ef</color>
+    <color name="i_am_color_11f0">#000011f0</color>
+    <color name="i_am_color_11f1">#000011f1</color>
+    <color name="i_am_color_11f2">#000011f2</color>
+    <color name="i_am_color_11f3">#000011f3</color>
+    <color name="i_am_color_11f4">#000011f4</color>
+    <color name="i_am_color_11f5">#000011f5</color>
+    <color name="i_am_color_11f6">#000011f6</color>
+    <color name="i_am_color_11f7">#000011f7</color>
+    <color name="i_am_color_11f8">#000011f8</color>
+    <color name="i_am_color_11f9">#000011f9</color>
+    <color name="i_am_color_11fa">#000011fa</color>
+    <color name="i_am_color_11fb">#000011fb</color>
+    <color name="i_am_color_11fc">#000011fc</color>
+    <color name="i_am_color_11fd">#000011fd</color>
+    <color name="i_am_color_11fe">#000011fe</color>
+    <color name="i_am_color_11ff">#000011ff</color>
+    <color name="i_am_color_1200">#00001200</color>
+    <color name="i_am_color_1201">#00001201</color>
+    <color name="i_am_color_1202">#00001202</color>
+    <color name="i_am_color_1203">#00001203</color>
+    <color name="i_am_color_1204">#00001204</color>
+    <color name="i_am_color_1205">#00001205</color>
+    <color name="i_am_color_1206">#00001206</color>
+    <color name="i_am_color_1207">#00001207</color>
+    <color name="i_am_color_1208">#00001208</color>
+    <color name="i_am_color_1209">#00001209</color>
+    <color name="i_am_color_120a">#0000120a</color>
+    <color name="i_am_color_120b">#0000120b</color>
+    <color name="i_am_color_120c">#0000120c</color>
+    <color name="i_am_color_120d">#0000120d</color>
+    <color name="i_am_color_120e">#0000120e</color>
+    <color name="i_am_color_120f">#0000120f</color>
+    <color name="i_am_color_1210">#00001210</color>
+    <color name="i_am_color_1211">#00001211</color>
+    <color name="i_am_color_1212">#00001212</color>
+    <color name="i_am_color_1213">#00001213</color>
+    <color name="i_am_color_1214">#00001214</color>
+    <color name="i_am_color_1215">#00001215</color>
+    <color name="i_am_color_1216">#00001216</color>
+    <color name="i_am_color_1217">#00001217</color>
+    <color name="i_am_color_1218">#00001218</color>
+    <color name="i_am_color_1219">#00001219</color>
+    <color name="i_am_color_121a">#0000121a</color>
+    <color name="i_am_color_121b">#0000121b</color>
+    <color name="i_am_color_121c">#0000121c</color>
+    <color name="i_am_color_121d">#0000121d</color>
+    <color name="i_am_color_121e">#0000121e</color>
+    <color name="i_am_color_121f">#0000121f</color>
+    <color name="i_am_color_1220">#00001220</color>
+    <color name="i_am_color_1221">#00001221</color>
+    <color name="i_am_color_1222">#00001222</color>
+    <color name="i_am_color_1223">#00001223</color>
+    <color name="i_am_color_1224">#00001224</color>
+    <color name="i_am_color_1225">#00001225</color>
+    <color name="i_am_color_1226">#00001226</color>
+    <color name="i_am_color_1227">#00001227</color>
+    <color name="i_am_color_1228">#00001228</color>
+    <color name="i_am_color_1229">#00001229</color>
+    <color name="i_am_color_122a">#0000122a</color>
+    <color name="i_am_color_122b">#0000122b</color>
+    <color name="i_am_color_122c">#0000122c</color>
+    <color name="i_am_color_122d">#0000122d</color>
+    <color name="i_am_color_122e">#0000122e</color>
+    <color name="i_am_color_122f">#0000122f</color>
+    <color name="i_am_color_1230">#00001230</color>
+    <color name="i_am_color_1231">#00001231</color>
+    <color name="i_am_color_1232">#00001232</color>
+    <color name="i_am_color_1233">#00001233</color>
+    <color name="i_am_color_1234">#00001234</color>
+    <color name="i_am_color_1235">#00001235</color>
+    <color name="i_am_color_1236">#00001236</color>
+    <color name="i_am_color_1237">#00001237</color>
+    <color name="i_am_color_1238">#00001238</color>
+    <color name="i_am_color_1239">#00001239</color>
+    <color name="i_am_color_123a">#0000123a</color>
+    <color name="i_am_color_123b">#0000123b</color>
+    <color name="i_am_color_123c">#0000123c</color>
+    <color name="i_am_color_123d">#0000123d</color>
+    <color name="i_am_color_123e">#0000123e</color>
+    <color name="i_am_color_123f">#0000123f</color>
+    <color name="i_am_color_1240">#00001240</color>
+    <color name="i_am_color_1241">#00001241</color>
+    <color name="i_am_color_1242">#00001242</color>
+    <color name="i_am_color_1243">#00001243</color>
+    <color name="i_am_color_1244">#00001244</color>
+    <color name="i_am_color_1245">#00001245</color>
+    <color name="i_am_color_1246">#00001246</color>
+    <color name="i_am_color_1247">#00001247</color>
+    <color name="i_am_color_1248">#00001248</color>
+    <color name="i_am_color_1249">#00001249</color>
+    <color name="i_am_color_124a">#0000124a</color>
+    <color name="i_am_color_124b">#0000124b</color>
+    <color name="i_am_color_124c">#0000124c</color>
+    <color name="i_am_color_124d">#0000124d</color>
+    <color name="i_am_color_124e">#0000124e</color>
+    <color name="i_am_color_124f">#0000124f</color>
+    <color name="i_am_color_1250">#00001250</color>
+    <color name="i_am_color_1251">#00001251</color>
+    <color name="i_am_color_1252">#00001252</color>
+    <color name="i_am_color_1253">#00001253</color>
+    <color name="i_am_color_1254">#00001254</color>
+    <color name="i_am_color_1255">#00001255</color>
+    <color name="i_am_color_1256">#00001256</color>
+    <color name="i_am_color_1257">#00001257</color>
+    <color name="i_am_color_1258">#00001258</color>
+    <color name="i_am_color_1259">#00001259</color>
+    <color name="i_am_color_125a">#0000125a</color>
+    <color name="i_am_color_125b">#0000125b</color>
+    <color name="i_am_color_125c">#0000125c</color>
+    <color name="i_am_color_125d">#0000125d</color>
+    <color name="i_am_color_125e">#0000125e</color>
+    <color name="i_am_color_125f">#0000125f</color>
+    <color name="i_am_color_1260">#00001260</color>
+    <color name="i_am_color_1261">#00001261</color>
+    <color name="i_am_color_1262">#00001262</color>
+    <color name="i_am_color_1263">#00001263</color>
+    <color name="i_am_color_1264">#00001264</color>
+    <color name="i_am_color_1265">#00001265</color>
+    <color name="i_am_color_1266">#00001266</color>
+    <color name="i_am_color_1267">#00001267</color>
+    <color name="i_am_color_1268">#00001268</color>
+    <color name="i_am_color_1269">#00001269</color>
+    <color name="i_am_color_126a">#0000126a</color>
+    <color name="i_am_color_126b">#0000126b</color>
+    <color name="i_am_color_126c">#0000126c</color>
+    <color name="i_am_color_126d">#0000126d</color>
+    <color name="i_am_color_126e">#0000126e</color>
+    <color name="i_am_color_126f">#0000126f</color>
+    <color name="i_am_color_1270">#00001270</color>
+    <color name="i_am_color_1271">#00001271</color>
+    <color name="i_am_color_1272">#00001272</color>
+    <color name="i_am_color_1273">#00001273</color>
+    <color name="i_am_color_1274">#00001274</color>
+    <color name="i_am_color_1275">#00001275</color>
+    <color name="i_am_color_1276">#00001276</color>
+    <color name="i_am_color_1277">#00001277</color>
+    <color name="i_am_color_1278">#00001278</color>
+    <color name="i_am_color_1279">#00001279</color>
+    <color name="i_am_color_127a">#0000127a</color>
+    <color name="i_am_color_127b">#0000127b</color>
+    <color name="i_am_color_127c">#0000127c</color>
+    <color name="i_am_color_127d">#0000127d</color>
+    <color name="i_am_color_127e">#0000127e</color>
+    <color name="i_am_color_127f">#0000127f</color>
+    <color name="i_am_color_1280">#00001280</color>
+    <color name="i_am_color_1281">#00001281</color>
+    <color name="i_am_color_1282">#00001282</color>
+    <color name="i_am_color_1283">#00001283</color>
+    <color name="i_am_color_1284">#00001284</color>
+    <color name="i_am_color_1285">#00001285</color>
+    <color name="i_am_color_1286">#00001286</color>
+    <color name="i_am_color_1287">#00001287</color>
+    <color name="i_am_color_1288">#00001288</color>
+    <color name="i_am_color_1289">#00001289</color>
+    <color name="i_am_color_128a">#0000128a</color>
+    <color name="i_am_color_128b">#0000128b</color>
+    <color name="i_am_color_128c">#0000128c</color>
+    <color name="i_am_color_128d">#0000128d</color>
+    <color name="i_am_color_128e">#0000128e</color>
+    <color name="i_am_color_128f">#0000128f</color>
+    <color name="i_am_color_1290">#00001290</color>
+    <color name="i_am_color_1291">#00001291</color>
+    <color name="i_am_color_1292">#00001292</color>
+    <color name="i_am_color_1293">#00001293</color>
+    <color name="i_am_color_1294">#00001294</color>
+    <color name="i_am_color_1295">#00001295</color>
+    <color name="i_am_color_1296">#00001296</color>
+    <color name="i_am_color_1297">#00001297</color>
+    <color name="i_am_color_1298">#00001298</color>
+    <color name="i_am_color_1299">#00001299</color>
+    <color name="i_am_color_129a">#0000129a</color>
+    <color name="i_am_color_129b">#0000129b</color>
+    <color name="i_am_color_129c">#0000129c</color>
+    <color name="i_am_color_129d">#0000129d</color>
+    <color name="i_am_color_129e">#0000129e</color>
+    <color name="i_am_color_129f">#0000129f</color>
+    <color name="i_am_color_12a0">#000012a0</color>
+    <color name="i_am_color_12a1">#000012a1</color>
+    <color name="i_am_color_12a2">#000012a2</color>
+    <color name="i_am_color_12a3">#000012a3</color>
+    <color name="i_am_color_12a4">#000012a4</color>
+    <color name="i_am_color_12a5">#000012a5</color>
+    <color name="i_am_color_12a6">#000012a6</color>
+    <color name="i_am_color_12a7">#000012a7</color>
+    <color name="i_am_color_12a8">#000012a8</color>
+    <color name="i_am_color_12a9">#000012a9</color>
+    <color name="i_am_color_12aa">#000012aa</color>
+    <color name="i_am_color_12ab">#000012ab</color>
+    <color name="i_am_color_12ac">#000012ac</color>
+    <color name="i_am_color_12ad">#000012ad</color>
+    <color name="i_am_color_12ae">#000012ae</color>
+    <color name="i_am_color_12af">#000012af</color>
+    <color name="i_am_color_12b0">#000012b0</color>
+    <color name="i_am_color_12b1">#000012b1</color>
+    <color name="i_am_color_12b2">#000012b2</color>
+    <color name="i_am_color_12b3">#000012b3</color>
+    <color name="i_am_color_12b4">#000012b4</color>
+    <color name="i_am_color_12b5">#000012b5</color>
+    <color name="i_am_color_12b6">#000012b6</color>
+    <color name="i_am_color_12b7">#000012b7</color>
+    <color name="i_am_color_12b8">#000012b8</color>
+    <color name="i_am_color_12b9">#000012b9</color>
+    <color name="i_am_color_12ba">#000012ba</color>
+    <color name="i_am_color_12bb">#000012bb</color>
+    <color name="i_am_color_12bc">#000012bc</color>
+    <color name="i_am_color_12bd">#000012bd</color>
+    <color name="i_am_color_12be">#000012be</color>
+    <color name="i_am_color_12bf">#000012bf</color>
+    <color name="i_am_color_12c0">#000012c0</color>
+    <color name="i_am_color_12c1">#000012c1</color>
+    <color name="i_am_color_12c2">#000012c2</color>
+    <color name="i_am_color_12c3">#000012c3</color>
+    <color name="i_am_color_12c4">#000012c4</color>
+    <color name="i_am_color_12c5">#000012c5</color>
+    <color name="i_am_color_12c6">#000012c6</color>
+    <color name="i_am_color_12c7">#000012c7</color>
+    <color name="i_am_color_12c8">#000012c8</color>
+    <color name="i_am_color_12c9">#000012c9</color>
+    <color name="i_am_color_12ca">#000012ca</color>
+    <color name="i_am_color_12cb">#000012cb</color>
+    <color name="i_am_color_12cc">#000012cc</color>
+    <color name="i_am_color_12cd">#000012cd</color>
+    <color name="i_am_color_12ce">#000012ce</color>
+    <color name="i_am_color_12cf">#000012cf</color>
+    <color name="i_am_color_12d0">#000012d0</color>
+    <color name="i_am_color_12d1">#000012d1</color>
+    <color name="i_am_color_12d2">#000012d2</color>
+    <color name="i_am_color_12d3">#000012d3</color>
+    <color name="i_am_color_12d4">#000012d4</color>
+    <color name="i_am_color_12d5">#000012d5</color>
+    <color name="i_am_color_12d6">#000012d6</color>
+    <color name="i_am_color_12d7">#000012d7</color>
+    <color name="i_am_color_12d8">#000012d8</color>
+    <color name="i_am_color_12d9">#000012d9</color>
+    <color name="i_am_color_12da">#000012da</color>
+    <color name="i_am_color_12db">#000012db</color>
+    <color name="i_am_color_12dc">#000012dc</color>
+    <color name="i_am_color_12dd">#000012dd</color>
+    <color name="i_am_color_12de">#000012de</color>
+    <color name="i_am_color_12df">#000012df</color>
+    <color name="i_am_color_12e0">#000012e0</color>
+    <color name="i_am_color_12e1">#000012e1</color>
+    <color name="i_am_color_12e2">#000012e2</color>
+    <color name="i_am_color_12e3">#000012e3</color>
+    <color name="i_am_color_12e4">#000012e4</color>
+    <color name="i_am_color_12e5">#000012e5</color>
+    <color name="i_am_color_12e6">#000012e6</color>
+    <color name="i_am_color_12e7">#000012e7</color>
+    <color name="i_am_color_12e8">#000012e8</color>
+    <color name="i_am_color_12e9">#000012e9</color>
+    <color name="i_am_color_12ea">#000012ea</color>
+    <color name="i_am_color_12eb">#000012eb</color>
+    <color name="i_am_color_12ec">#000012ec</color>
+    <color name="i_am_color_12ed">#000012ed</color>
+    <color name="i_am_color_12ee">#000012ee</color>
+    <color name="i_am_color_12ef">#000012ef</color>
+    <color name="i_am_color_12f0">#000012f0</color>
+    <color name="i_am_color_12f1">#000012f1</color>
+    <color name="i_am_color_12f2">#000012f2</color>
+    <color name="i_am_color_12f3">#000012f3</color>
+    <color name="i_am_color_12f4">#000012f4</color>
+    <color name="i_am_color_12f5">#000012f5</color>
+    <color name="i_am_color_12f6">#000012f6</color>
+    <color name="i_am_color_12f7">#000012f7</color>
+    <color name="i_am_color_12f8">#000012f8</color>
+    <color name="i_am_color_12f9">#000012f9</color>
+    <color name="i_am_color_12fa">#000012fa</color>
+    <color name="i_am_color_12fb">#000012fb</color>
+    <color name="i_am_color_12fc">#000012fc</color>
+    <color name="i_am_color_12fd">#000012fd</color>
+    <color name="i_am_color_12fe">#000012fe</color>
+    <color name="i_am_color_12ff">#000012ff</color>
+    <color name="i_am_color_1300">#00001300</color>
+    <color name="i_am_color_1301">#00001301</color>
+    <color name="i_am_color_1302">#00001302</color>
+    <color name="i_am_color_1303">#00001303</color>
+    <color name="i_am_color_1304">#00001304</color>
+    <color name="i_am_color_1305">#00001305</color>
+    <color name="i_am_color_1306">#00001306</color>
+    <color name="i_am_color_1307">#00001307</color>
+    <color name="i_am_color_1308">#00001308</color>
+    <color name="i_am_color_1309">#00001309</color>
+    <color name="i_am_color_130a">#0000130a</color>
+    <color name="i_am_color_130b">#0000130b</color>
+    <color name="i_am_color_130c">#0000130c</color>
+    <color name="i_am_color_130d">#0000130d</color>
+    <color name="i_am_color_130e">#0000130e</color>
+    <color name="i_am_color_130f">#0000130f</color>
+    <color name="i_am_color_1310">#00001310</color>
+    <color name="i_am_color_1311">#00001311</color>
+    <color name="i_am_color_1312">#00001312</color>
+    <color name="i_am_color_1313">#00001313</color>
+    <color name="i_am_color_1314">#00001314</color>
+    <color name="i_am_color_1315">#00001315</color>
+    <color name="i_am_color_1316">#00001316</color>
+    <color name="i_am_color_1317">#00001317</color>
+    <color name="i_am_color_1318">#00001318</color>
+    <color name="i_am_color_1319">#00001319</color>
+    <color name="i_am_color_131a">#0000131a</color>
+    <color name="i_am_color_131b">#0000131b</color>
+    <color name="i_am_color_131c">#0000131c</color>
+    <color name="i_am_color_131d">#0000131d</color>
+    <color name="i_am_color_131e">#0000131e</color>
+    <color name="i_am_color_131f">#0000131f</color>
+    <color name="i_am_color_1320">#00001320</color>
+    <color name="i_am_color_1321">#00001321</color>
+    <color name="i_am_color_1322">#00001322</color>
+    <color name="i_am_color_1323">#00001323</color>
+    <color name="i_am_color_1324">#00001324</color>
+    <color name="i_am_color_1325">#00001325</color>
+    <color name="i_am_color_1326">#00001326</color>
+    <color name="i_am_color_1327">#00001327</color>
+    <color name="i_am_color_1328">#00001328</color>
+    <color name="i_am_color_1329">#00001329</color>
+    <color name="i_am_color_132a">#0000132a</color>
+    <color name="i_am_color_132b">#0000132b</color>
+    <color name="i_am_color_132c">#0000132c</color>
+    <color name="i_am_color_132d">#0000132d</color>
+    <color name="i_am_color_132e">#0000132e</color>
+    <color name="i_am_color_132f">#0000132f</color>
+    <color name="i_am_color_1330">#00001330</color>
+    <color name="i_am_color_1331">#00001331</color>
+    <color name="i_am_color_1332">#00001332</color>
+    <color name="i_am_color_1333">#00001333</color>
+    <color name="i_am_color_1334">#00001334</color>
+    <color name="i_am_color_1335">#00001335</color>
+    <color name="i_am_color_1336">#00001336</color>
+    <color name="i_am_color_1337">#00001337</color>
+    <color name="i_am_color_1338">#00001338</color>
+    <color name="i_am_color_1339">#00001339</color>
+    <color name="i_am_color_133a">#0000133a</color>
+    <color name="i_am_color_133b">#0000133b</color>
+    <color name="i_am_color_133c">#0000133c</color>
+    <color name="i_am_color_133d">#0000133d</color>
+    <color name="i_am_color_133e">#0000133e</color>
+    <color name="i_am_color_133f">#0000133f</color>
+    <color name="i_am_color_1340">#00001340</color>
+    <color name="i_am_color_1341">#00001341</color>
+    <color name="i_am_color_1342">#00001342</color>
+    <color name="i_am_color_1343">#00001343</color>
+    <color name="i_am_color_1344">#00001344</color>
+    <color name="i_am_color_1345">#00001345</color>
+    <color name="i_am_color_1346">#00001346</color>
+    <color name="i_am_color_1347">#00001347</color>
+    <color name="i_am_color_1348">#00001348</color>
+    <color name="i_am_color_1349">#00001349</color>
+    <color name="i_am_color_134a">#0000134a</color>
+    <color name="i_am_color_134b">#0000134b</color>
+    <color name="i_am_color_134c">#0000134c</color>
+    <color name="i_am_color_134d">#0000134d</color>
+    <color name="i_am_color_134e">#0000134e</color>
+    <color name="i_am_color_134f">#0000134f</color>
+    <color name="i_am_color_1350">#00001350</color>
+    <color name="i_am_color_1351">#00001351</color>
+    <color name="i_am_color_1352">#00001352</color>
+    <color name="i_am_color_1353">#00001353</color>
+    <color name="i_am_color_1354">#00001354</color>
+    <color name="i_am_color_1355">#00001355</color>
+    <color name="i_am_color_1356">#00001356</color>
+    <color name="i_am_color_1357">#00001357</color>
+    <color name="i_am_color_1358">#00001358</color>
+    <color name="i_am_color_1359">#00001359</color>
+    <color name="i_am_color_135a">#0000135a</color>
+    <color name="i_am_color_135b">#0000135b</color>
+    <color name="i_am_color_135c">#0000135c</color>
+    <color name="i_am_color_135d">#0000135d</color>
+    <color name="i_am_color_135e">#0000135e</color>
+    <color name="i_am_color_135f">#0000135f</color>
+    <color name="i_am_color_1360">#00001360</color>
+    <color name="i_am_color_1361">#00001361</color>
+    <color name="i_am_color_1362">#00001362</color>
+    <color name="i_am_color_1363">#00001363</color>
+    <color name="i_am_color_1364">#00001364</color>
+    <color name="i_am_color_1365">#00001365</color>
+    <color name="i_am_color_1366">#00001366</color>
+    <color name="i_am_color_1367">#00001367</color>
+    <color name="i_am_color_1368">#00001368</color>
+    <color name="i_am_color_1369">#00001369</color>
+    <color name="i_am_color_136a">#0000136a</color>
+    <color name="i_am_color_136b">#0000136b</color>
+    <color name="i_am_color_136c">#0000136c</color>
+    <color name="i_am_color_136d">#0000136d</color>
+    <color name="i_am_color_136e">#0000136e</color>
+    <color name="i_am_color_136f">#0000136f</color>
+    <color name="i_am_color_1370">#00001370</color>
+    <color name="i_am_color_1371">#00001371</color>
+    <color name="i_am_color_1372">#00001372</color>
+    <color name="i_am_color_1373">#00001373</color>
+    <color name="i_am_color_1374">#00001374</color>
+    <color name="i_am_color_1375">#00001375</color>
+    <color name="i_am_color_1376">#00001376</color>
+    <color name="i_am_color_1377">#00001377</color>
+    <color name="i_am_color_1378">#00001378</color>
+    <color name="i_am_color_1379">#00001379</color>
+    <color name="i_am_color_137a">#0000137a</color>
+    <color name="i_am_color_137b">#0000137b</color>
+    <color name="i_am_color_137c">#0000137c</color>
+    <color name="i_am_color_137d">#0000137d</color>
+    <color name="i_am_color_137e">#0000137e</color>
+    <color name="i_am_color_137f">#0000137f</color>
+    <color name="i_am_color_1380">#00001380</color>
+    <color name="i_am_color_1381">#00001381</color>
+    <color name="i_am_color_1382">#00001382</color>
+    <color name="i_am_color_1383">#00001383</color>
+    <color name="i_am_color_1384">#00001384</color>
+    <color name="i_am_color_1385">#00001385</color>
+    <color name="i_am_color_1386">#00001386</color>
+    <color name="i_am_color_1387">#00001387</color>
+    <color name="i_am_color_1388">#00001388</color>
+    <color name="i_am_color_1389">#00001389</color>
+    <color name="i_am_color_138a">#0000138a</color>
+    <color name="i_am_color_138b">#0000138b</color>
+    <color name="i_am_color_138c">#0000138c</color>
+    <color name="i_am_color_138d">#0000138d</color>
+    <color name="i_am_color_138e">#0000138e</color>
+    <color name="i_am_color_138f">#0000138f</color>
+    <color name="i_am_color_1390">#00001390</color>
+    <color name="i_am_color_1391">#00001391</color>
+    <color name="i_am_color_1392">#00001392</color>
+    <color name="i_am_color_1393">#00001393</color>
+    <color name="i_am_color_1394">#00001394</color>
+    <color name="i_am_color_1395">#00001395</color>
+    <color name="i_am_color_1396">#00001396</color>
+    <color name="i_am_color_1397">#00001397</color>
+    <color name="i_am_color_1398">#00001398</color>
+    <color name="i_am_color_1399">#00001399</color>
+    <color name="i_am_color_139a">#0000139a</color>
+    <color name="i_am_color_139b">#0000139b</color>
+    <color name="i_am_color_139c">#0000139c</color>
+    <color name="i_am_color_139d">#0000139d</color>
+    <color name="i_am_color_139e">#0000139e</color>
+    <color name="i_am_color_139f">#0000139f</color>
+    <color name="i_am_color_13a0">#000013a0</color>
+    <color name="i_am_color_13a1">#000013a1</color>
+    <color name="i_am_color_13a2">#000013a2</color>
+    <color name="i_am_color_13a3">#000013a3</color>
+    <color name="i_am_color_13a4">#000013a4</color>
+    <color name="i_am_color_13a5">#000013a5</color>
+    <color name="i_am_color_13a6">#000013a6</color>
+    <color name="i_am_color_13a7">#000013a7</color>
+    <color name="i_am_color_13a8">#000013a8</color>
+    <color name="i_am_color_13a9">#000013a9</color>
+    <color name="i_am_color_13aa">#000013aa</color>
+    <color name="i_am_color_13ab">#000013ab</color>
+    <color name="i_am_color_13ac">#000013ac</color>
+    <color name="i_am_color_13ad">#000013ad</color>
+    <color name="i_am_color_13ae">#000013ae</color>
+    <color name="i_am_color_13af">#000013af</color>
+    <color name="i_am_color_13b0">#000013b0</color>
+    <color name="i_am_color_13b1">#000013b1</color>
+    <color name="i_am_color_13b2">#000013b2</color>
+    <color name="i_am_color_13b3">#000013b3</color>
+    <color name="i_am_color_13b4">#000013b4</color>
+    <color name="i_am_color_13b5">#000013b5</color>
+    <color name="i_am_color_13b6">#000013b6</color>
+    <color name="i_am_color_13b7">#000013b7</color>
+    <color name="i_am_color_13b8">#000013b8</color>
+    <color name="i_am_color_13b9">#000013b9</color>
+    <color name="i_am_color_13ba">#000013ba</color>
+    <color name="i_am_color_13bb">#000013bb</color>
+    <color name="i_am_color_13bc">#000013bc</color>
+    <color name="i_am_color_13bd">#000013bd</color>
+    <color name="i_am_color_13be">#000013be</color>
+    <color name="i_am_color_13bf">#000013bf</color>
+    <color name="i_am_color_13c0">#000013c0</color>
+    <color name="i_am_color_13c1">#000013c1</color>
+    <color name="i_am_color_13c2">#000013c2</color>
+    <color name="i_am_color_13c3">#000013c3</color>
+    <color name="i_am_color_13c4">#000013c4</color>
+    <color name="i_am_color_13c5">#000013c5</color>
+    <color name="i_am_color_13c6">#000013c6</color>
+    <color name="i_am_color_13c7">#000013c7</color>
+    <color name="i_am_color_13c8">#000013c8</color>
+    <color name="i_am_color_13c9">#000013c9</color>
+    <color name="i_am_color_13ca">#000013ca</color>
+    <color name="i_am_color_13cb">#000013cb</color>
+    <color name="i_am_color_13cc">#000013cc</color>
+    <color name="i_am_color_13cd">#000013cd</color>
+    <color name="i_am_color_13ce">#000013ce</color>
+    <color name="i_am_color_13cf">#000013cf</color>
+    <color name="i_am_color_13d0">#000013d0</color>
+    <color name="i_am_color_13d1">#000013d1</color>
+    <color name="i_am_color_13d2">#000013d2</color>
+    <color name="i_am_color_13d3">#000013d3</color>
+    <color name="i_am_color_13d4">#000013d4</color>
+    <color name="i_am_color_13d5">#000013d5</color>
+    <color name="i_am_color_13d6">#000013d6</color>
+    <color name="i_am_color_13d7">#000013d7</color>
+    <color name="i_am_color_13d8">#000013d8</color>
+    <color name="i_am_color_13d9">#000013d9</color>
+    <color name="i_am_color_13da">#000013da</color>
+    <color name="i_am_color_13db">#000013db</color>
+    <color name="i_am_color_13dc">#000013dc</color>
+    <color name="i_am_color_13dd">#000013dd</color>
+    <color name="i_am_color_13de">#000013de</color>
+    <color name="i_am_color_13df">#000013df</color>
+    <color name="i_am_color_13e0">#000013e0</color>
+    <color name="i_am_color_13e1">#000013e1</color>
+    <color name="i_am_color_13e2">#000013e2</color>
+    <color name="i_am_color_13e3">#000013e3</color>
+    <color name="i_am_color_13e4">#000013e4</color>
+    <color name="i_am_color_13e5">#000013e5</color>
+    <color name="i_am_color_13e6">#000013e6</color>
+    <color name="i_am_color_13e7">#000013e7</color>
+    <color name="i_am_color_13e8">#000013e8</color>
+    <color name="i_am_color_13e9">#000013e9</color>
+    <color name="i_am_color_13ea">#000013ea</color>
+    <color name="i_am_color_13eb">#000013eb</color>
+    <color name="i_am_color_13ec">#000013ec</color>
+    <color name="i_am_color_13ed">#000013ed</color>
+    <color name="i_am_color_13ee">#000013ee</color>
+    <color name="i_am_color_13ef">#000013ef</color>
+    <color name="i_am_color_13f0">#000013f0</color>
+    <color name="i_am_color_13f1">#000013f1</color>
+    <color name="i_am_color_13f2">#000013f2</color>
+    <color name="i_am_color_13f3">#000013f3</color>
+    <color name="i_am_color_13f4">#000013f4</color>
+    <color name="i_am_color_13f5">#000013f5</color>
+    <color name="i_am_color_13f6">#000013f6</color>
+    <color name="i_am_color_13f7">#000013f7</color>
+    <color name="i_am_color_13f8">#000013f8</color>
+    <color name="i_am_color_13f9">#000013f9</color>
+    <color name="i_am_color_13fa">#000013fa</color>
+    <color name="i_am_color_13fb">#000013fb</color>
+    <color name="i_am_color_13fc">#000013fc</color>
+    <color name="i_am_color_13fd">#000013fd</color>
+    <color name="i_am_color_13fe">#000013fe</color>
+    <color name="i_am_color_13ff">#000013ff</color>
+    <color name="i_am_color_1400">#00001400</color>
+    <color name="i_am_color_1401">#00001401</color>
+    <color name="i_am_color_1402">#00001402</color>
+    <color name="i_am_color_1403">#00001403</color>
+    <color name="i_am_color_1404">#00001404</color>
+    <color name="i_am_color_1405">#00001405</color>
+    <color name="i_am_color_1406">#00001406</color>
+    <color name="i_am_color_1407">#00001407</color>
+    <color name="i_am_color_1408">#00001408</color>
+    <color name="i_am_color_1409">#00001409</color>
+    <color name="i_am_color_140a">#0000140a</color>
+    <color name="i_am_color_140b">#0000140b</color>
+    <color name="i_am_color_140c">#0000140c</color>
+    <color name="i_am_color_140d">#0000140d</color>
+    <color name="i_am_color_140e">#0000140e</color>
+    <color name="i_am_color_140f">#0000140f</color>
+    <color name="i_am_color_1410">#00001410</color>
+    <color name="i_am_color_1411">#00001411</color>
+    <color name="i_am_color_1412">#00001412</color>
+    <color name="i_am_color_1413">#00001413</color>
+    <color name="i_am_color_1414">#00001414</color>
+    <color name="i_am_color_1415">#00001415</color>
+    <color name="i_am_color_1416">#00001416</color>
+    <color name="i_am_color_1417">#00001417</color>
+    <color name="i_am_color_1418">#00001418</color>
+    <color name="i_am_color_1419">#00001419</color>
+    <color name="i_am_color_141a">#0000141a</color>
+    <color name="i_am_color_141b">#0000141b</color>
+    <color name="i_am_color_141c">#0000141c</color>
+    <color name="i_am_color_141d">#0000141d</color>
+    <color name="i_am_color_141e">#0000141e</color>
+    <color name="i_am_color_141f">#0000141f</color>
+    <color name="i_am_color_1420">#00001420</color>
+    <color name="i_am_color_1421">#00001421</color>
+    <color name="i_am_color_1422">#00001422</color>
+    <color name="i_am_color_1423">#00001423</color>
+    <color name="i_am_color_1424">#00001424</color>
+    <color name="i_am_color_1425">#00001425</color>
+    <color name="i_am_color_1426">#00001426</color>
+    <color name="i_am_color_1427">#00001427</color>
+    <color name="i_am_color_1428">#00001428</color>
+    <color name="i_am_color_1429">#00001429</color>
+    <color name="i_am_color_142a">#0000142a</color>
+    <color name="i_am_color_142b">#0000142b</color>
+    <color name="i_am_color_142c">#0000142c</color>
+    <color name="i_am_color_142d">#0000142d</color>
+    <color name="i_am_color_142e">#0000142e</color>
+    <color name="i_am_color_142f">#0000142f</color>
+    <color name="i_am_color_1430">#00001430</color>
+    <color name="i_am_color_1431">#00001431</color>
+    <color name="i_am_color_1432">#00001432</color>
+    <color name="i_am_color_1433">#00001433</color>
+    <color name="i_am_color_1434">#00001434</color>
+    <color name="i_am_color_1435">#00001435</color>
+    <color name="i_am_color_1436">#00001436</color>
+    <color name="i_am_color_1437">#00001437</color>
+    <color name="i_am_color_1438">#00001438</color>
+    <color name="i_am_color_1439">#00001439</color>
+    <color name="i_am_color_143a">#0000143a</color>
+    <color name="i_am_color_143b">#0000143b</color>
+    <color name="i_am_color_143c">#0000143c</color>
+    <color name="i_am_color_143d">#0000143d</color>
+    <color name="i_am_color_143e">#0000143e</color>
+    <color name="i_am_color_143f">#0000143f</color>
+    <color name="i_am_color_1440">#00001440</color>
+    <color name="i_am_color_1441">#00001441</color>
+    <color name="i_am_color_1442">#00001442</color>
+    <color name="i_am_color_1443">#00001443</color>
+    <color name="i_am_color_1444">#00001444</color>
+    <color name="i_am_color_1445">#00001445</color>
+    <color name="i_am_color_1446">#00001446</color>
+    <color name="i_am_color_1447">#00001447</color>
+    <color name="i_am_color_1448">#00001448</color>
+    <color name="i_am_color_1449">#00001449</color>
+    <color name="i_am_color_144a">#0000144a</color>
+    <color name="i_am_color_144b">#0000144b</color>
+    <color name="i_am_color_144c">#0000144c</color>
+    <color name="i_am_color_144d">#0000144d</color>
+    <color name="i_am_color_144e">#0000144e</color>
+    <color name="i_am_color_144f">#0000144f</color>
+    <color name="i_am_color_1450">#00001450</color>
+    <color name="i_am_color_1451">#00001451</color>
+    <color name="i_am_color_1452">#00001452</color>
+    <color name="i_am_color_1453">#00001453</color>
+    <color name="i_am_color_1454">#00001454</color>
+    <color name="i_am_color_1455">#00001455</color>
+    <color name="i_am_color_1456">#00001456</color>
+    <color name="i_am_color_1457">#00001457</color>
+    <color name="i_am_color_1458">#00001458</color>
+    <color name="i_am_color_1459">#00001459</color>
+    <color name="i_am_color_145a">#0000145a</color>
+    <color name="i_am_color_145b">#0000145b</color>
+    <color name="i_am_color_145c">#0000145c</color>
+    <color name="i_am_color_145d">#0000145d</color>
+    <color name="i_am_color_145e">#0000145e</color>
+    <color name="i_am_color_145f">#0000145f</color>
+    <color name="i_am_color_1460">#00001460</color>
+    <color name="i_am_color_1461">#00001461</color>
+    <color name="i_am_color_1462">#00001462</color>
+    <color name="i_am_color_1463">#00001463</color>
+    <color name="i_am_color_1464">#00001464</color>
+    <color name="i_am_color_1465">#00001465</color>
+    <color name="i_am_color_1466">#00001466</color>
+    <color name="i_am_color_1467">#00001467</color>
+    <color name="i_am_color_1468">#00001468</color>
+    <color name="i_am_color_1469">#00001469</color>
+    <color name="i_am_color_146a">#0000146a</color>
+    <color name="i_am_color_146b">#0000146b</color>
+    <color name="i_am_color_146c">#0000146c</color>
+    <color name="i_am_color_146d">#0000146d</color>
+    <color name="i_am_color_146e">#0000146e</color>
+    <color name="i_am_color_146f">#0000146f</color>
+    <color name="i_am_color_1470">#00001470</color>
+    <color name="i_am_color_1471">#00001471</color>
+    <color name="i_am_color_1472">#00001472</color>
+    <color name="i_am_color_1473">#00001473</color>
+    <color name="i_am_color_1474">#00001474</color>
+    <color name="i_am_color_1475">#00001475</color>
+    <color name="i_am_color_1476">#00001476</color>
+    <color name="i_am_color_1477">#00001477</color>
+    <color name="i_am_color_1478">#00001478</color>
+    <color name="i_am_color_1479">#00001479</color>
+    <color name="i_am_color_147a">#0000147a</color>
+    <color name="i_am_color_147b">#0000147b</color>
+    <color name="i_am_color_147c">#0000147c</color>
+    <color name="i_am_color_147d">#0000147d</color>
+    <color name="i_am_color_147e">#0000147e</color>
+    <color name="i_am_color_147f">#0000147f</color>
+    <color name="i_am_color_1480">#00001480</color>
+    <color name="i_am_color_1481">#00001481</color>
+    <color name="i_am_color_1482">#00001482</color>
+    <color name="i_am_color_1483">#00001483</color>
+    <color name="i_am_color_1484">#00001484</color>
+    <color name="i_am_color_1485">#00001485</color>
+    <color name="i_am_color_1486">#00001486</color>
+    <color name="i_am_color_1487">#00001487</color>
+    <color name="i_am_color_1488">#00001488</color>
+    <color name="i_am_color_1489">#00001489</color>
+    <color name="i_am_color_148a">#0000148a</color>
+    <color name="i_am_color_148b">#0000148b</color>
+    <color name="i_am_color_148c">#0000148c</color>
+    <color name="i_am_color_148d">#0000148d</color>
+    <color name="i_am_color_148e">#0000148e</color>
+    <color name="i_am_color_148f">#0000148f</color>
+    <color name="i_am_color_1490">#00001490</color>
+    <color name="i_am_color_1491">#00001491</color>
+    <color name="i_am_color_1492">#00001492</color>
+    <color name="i_am_color_1493">#00001493</color>
+    <color name="i_am_color_1494">#00001494</color>
+    <color name="i_am_color_1495">#00001495</color>
+    <color name="i_am_color_1496">#00001496</color>
+    <color name="i_am_color_1497">#00001497</color>
+    <color name="i_am_color_1498">#00001498</color>
+    <color name="i_am_color_1499">#00001499</color>
+    <color name="i_am_color_149a">#0000149a</color>
+    <color name="i_am_color_149b">#0000149b</color>
+    <color name="i_am_color_149c">#0000149c</color>
+    <color name="i_am_color_149d">#0000149d</color>
+    <color name="i_am_color_149e">#0000149e</color>
+    <color name="i_am_color_149f">#0000149f</color>
+    <color name="i_am_color_14a0">#000014a0</color>
+    <color name="i_am_color_14a1">#000014a1</color>
+    <color name="i_am_color_14a2">#000014a2</color>
+    <color name="i_am_color_14a3">#000014a3</color>
+    <color name="i_am_color_14a4">#000014a4</color>
+    <color name="i_am_color_14a5">#000014a5</color>
+    <color name="i_am_color_14a6">#000014a6</color>
+    <color name="i_am_color_14a7">#000014a7</color>
+    <color name="i_am_color_14a8">#000014a8</color>
+    <color name="i_am_color_14a9">#000014a9</color>
+    <color name="i_am_color_14aa">#000014aa</color>
+    <color name="i_am_color_14ab">#000014ab</color>
+    <color name="i_am_color_14ac">#000014ac</color>
+    <color name="i_am_color_14ad">#000014ad</color>
+    <color name="i_am_color_14ae">#000014ae</color>
+    <color name="i_am_color_14af">#000014af</color>
+    <color name="i_am_color_14b0">#000014b0</color>
+    <color name="i_am_color_14b1">#000014b1</color>
+    <color name="i_am_color_14b2">#000014b2</color>
+    <color name="i_am_color_14b3">#000014b3</color>
+    <color name="i_am_color_14b4">#000014b4</color>
+    <color name="i_am_color_14b5">#000014b5</color>
+    <color name="i_am_color_14b6">#000014b6</color>
+    <color name="i_am_color_14b7">#000014b7</color>
+    <color name="i_am_color_14b8">#000014b8</color>
+    <color name="i_am_color_14b9">#000014b9</color>
+    <color name="i_am_color_14ba">#000014ba</color>
+    <color name="i_am_color_14bb">#000014bb</color>
+    <color name="i_am_color_14bc">#000014bc</color>
+    <color name="i_am_color_14bd">#000014bd</color>
+    <color name="i_am_color_14be">#000014be</color>
+    <color name="i_am_color_14bf">#000014bf</color>
+    <color name="i_am_color_14c0">#000014c0</color>
+    <color name="i_am_color_14c1">#000014c1</color>
+    <color name="i_am_color_14c2">#000014c2</color>
+    <color name="i_am_color_14c3">#000014c3</color>
+    <color name="i_am_color_14c4">#000014c4</color>
+    <color name="i_am_color_14c5">#000014c5</color>
+    <color name="i_am_color_14c6">#000014c6</color>
+    <color name="i_am_color_14c7">#000014c7</color>
+    <color name="i_am_color_14c8">#000014c8</color>
+    <color name="i_am_color_14c9">#000014c9</color>
+    <color name="i_am_color_14ca">#000014ca</color>
+    <color name="i_am_color_14cb">#000014cb</color>
+    <color name="i_am_color_14cc">#000014cc</color>
+    <color name="i_am_color_14cd">#000014cd</color>
+    <color name="i_am_color_14ce">#000014ce</color>
+    <color name="i_am_color_14cf">#000014cf</color>
+    <color name="i_am_color_14d0">#000014d0</color>
+    <color name="i_am_color_14d1">#000014d1</color>
+    <color name="i_am_color_14d2">#000014d2</color>
+    <color name="i_am_color_14d3">#000014d3</color>
+    <color name="i_am_color_14d4">#000014d4</color>
+    <color name="i_am_color_14d5">#000014d5</color>
+    <color name="i_am_color_14d6">#000014d6</color>
+    <color name="i_am_color_14d7">#000014d7</color>
+    <color name="i_am_color_14d8">#000014d8</color>
+    <color name="i_am_color_14d9">#000014d9</color>
+    <color name="i_am_color_14da">#000014da</color>
+    <color name="i_am_color_14db">#000014db</color>
+    <color name="i_am_color_14dc">#000014dc</color>
+    <color name="i_am_color_14dd">#000014dd</color>
+    <color name="i_am_color_14de">#000014de</color>
+    <color name="i_am_color_14df">#000014df</color>
+    <color name="i_am_color_14e0">#000014e0</color>
+    <color name="i_am_color_14e1">#000014e1</color>
+    <color name="i_am_color_14e2">#000014e2</color>
+    <color name="i_am_color_14e3">#000014e3</color>
+    <color name="i_am_color_14e4">#000014e4</color>
+    <color name="i_am_color_14e5">#000014e5</color>
+    <color name="i_am_color_14e6">#000014e6</color>
+    <color name="i_am_color_14e7">#000014e7</color>
+    <color name="i_am_color_14e8">#000014e8</color>
+    <color name="i_am_color_14e9">#000014e9</color>
+    <color name="i_am_color_14ea">#000014ea</color>
+    <color name="i_am_color_14eb">#000014eb</color>
+    <color name="i_am_color_14ec">#000014ec</color>
+    <color name="i_am_color_14ed">#000014ed</color>
+    <color name="i_am_color_14ee">#000014ee</color>
+    <color name="i_am_color_14ef">#000014ef</color>
+    <color name="i_am_color_14f0">#000014f0</color>
+    <color name="i_am_color_14f1">#000014f1</color>
+    <color name="i_am_color_14f2">#000014f2</color>
+    <color name="i_am_color_14f3">#000014f3</color>
+    <color name="i_am_color_14f4">#000014f4</color>
+    <color name="i_am_color_14f5">#000014f5</color>
+    <color name="i_am_color_14f6">#000014f6</color>
+    <color name="i_am_color_14f7">#000014f7</color>
+    <color name="i_am_color_14f8">#000014f8</color>
+    <color name="i_am_color_14f9">#000014f9</color>
+    <color name="i_am_color_14fa">#000014fa</color>
+    <color name="i_am_color_14fb">#000014fb</color>
+    <color name="i_am_color_14fc">#000014fc</color>
+    <color name="i_am_color_14fd">#000014fd</color>
+    <color name="i_am_color_14fe">#000014fe</color>
+    <color name="i_am_color_14ff">#000014ff</color>
+    <color name="i_am_color_1500">#00001500</color>
+    <color name="i_am_color_1501">#00001501</color>
+    <color name="i_am_color_1502">#00001502</color>
+    <color name="i_am_color_1503">#00001503</color>
+    <color name="i_am_color_1504">#00001504</color>
+    <color name="i_am_color_1505">#00001505</color>
+    <color name="i_am_color_1506">#00001506</color>
+    <color name="i_am_color_1507">#00001507</color>
+    <color name="i_am_color_1508">#00001508</color>
+    <color name="i_am_color_1509">#00001509</color>
+    <color name="i_am_color_150a">#0000150a</color>
+    <color name="i_am_color_150b">#0000150b</color>
+    <color name="i_am_color_150c">#0000150c</color>
+    <color name="i_am_color_150d">#0000150d</color>
+    <color name="i_am_color_150e">#0000150e</color>
+    <color name="i_am_color_150f">#0000150f</color>
+    <color name="i_am_color_1510">#00001510</color>
+    <color name="i_am_color_1511">#00001511</color>
+    <color name="i_am_color_1512">#00001512</color>
+    <color name="i_am_color_1513">#00001513</color>
+    <color name="i_am_color_1514">#00001514</color>
+    <color name="i_am_color_1515">#00001515</color>
+    <color name="i_am_color_1516">#00001516</color>
+    <color name="i_am_color_1517">#00001517</color>
+    <color name="i_am_color_1518">#00001518</color>
+    <color name="i_am_color_1519">#00001519</color>
+    <color name="i_am_color_151a">#0000151a</color>
+    <color name="i_am_color_151b">#0000151b</color>
+    <color name="i_am_color_151c">#0000151c</color>
+    <color name="i_am_color_151d">#0000151d</color>
+    <color name="i_am_color_151e">#0000151e</color>
+    <color name="i_am_color_151f">#0000151f</color>
+    <color name="i_am_color_1520">#00001520</color>
+    <color name="i_am_color_1521">#00001521</color>
+    <color name="i_am_color_1522">#00001522</color>
+    <color name="i_am_color_1523">#00001523</color>
+    <color name="i_am_color_1524">#00001524</color>
+    <color name="i_am_color_1525">#00001525</color>
+    <color name="i_am_color_1526">#00001526</color>
+    <color name="i_am_color_1527">#00001527</color>
+    <color name="i_am_color_1528">#00001528</color>
+    <color name="i_am_color_1529">#00001529</color>
+    <color name="i_am_color_152a">#0000152a</color>
+    <color name="i_am_color_152b">#0000152b</color>
+    <color name="i_am_color_152c">#0000152c</color>
+    <color name="i_am_color_152d">#0000152d</color>
+    <color name="i_am_color_152e">#0000152e</color>
+    <color name="i_am_color_152f">#0000152f</color>
+    <color name="i_am_color_1530">#00001530</color>
+    <color name="i_am_color_1531">#00001531</color>
+    <color name="i_am_color_1532">#00001532</color>
+    <color name="i_am_color_1533">#00001533</color>
+    <color name="i_am_color_1534">#00001534</color>
+    <color name="i_am_color_1535">#00001535</color>
+    <color name="i_am_color_1536">#00001536</color>
+    <color name="i_am_color_1537">#00001537</color>
+    <color name="i_am_color_1538">#00001538</color>
+    <color name="i_am_color_1539">#00001539</color>
+    <color name="i_am_color_153a">#0000153a</color>
+    <color name="i_am_color_153b">#0000153b</color>
+    <color name="i_am_color_153c">#0000153c</color>
+    <color name="i_am_color_153d">#0000153d</color>
+    <color name="i_am_color_153e">#0000153e</color>
+    <color name="i_am_color_153f">#0000153f</color>
+    <color name="i_am_color_1540">#00001540</color>
+    <color name="i_am_color_1541">#00001541</color>
+    <color name="i_am_color_1542">#00001542</color>
+    <color name="i_am_color_1543">#00001543</color>
+    <color name="i_am_color_1544">#00001544</color>
+    <color name="i_am_color_1545">#00001545</color>
+    <color name="i_am_color_1546">#00001546</color>
+    <color name="i_am_color_1547">#00001547</color>
+    <color name="i_am_color_1548">#00001548</color>
+    <color name="i_am_color_1549">#00001549</color>
+    <color name="i_am_color_154a">#0000154a</color>
+    <color name="i_am_color_154b">#0000154b</color>
+    <color name="i_am_color_154c">#0000154c</color>
+    <color name="i_am_color_154d">#0000154d</color>
+    <color name="i_am_color_154e">#0000154e</color>
+    <color name="i_am_color_154f">#0000154f</color>
+    <color name="i_am_color_1550">#00001550</color>
+    <color name="i_am_color_1551">#00001551</color>
+    <color name="i_am_color_1552">#00001552</color>
+    <color name="i_am_color_1553">#00001553</color>
+    <color name="i_am_color_1554">#00001554</color>
+    <color name="i_am_color_1555">#00001555</color>
+    <color name="i_am_color_1556">#00001556</color>
+    <color name="i_am_color_1557">#00001557</color>
+    <color name="i_am_color_1558">#00001558</color>
+    <color name="i_am_color_1559">#00001559</color>
+    <color name="i_am_color_155a">#0000155a</color>
+    <color name="i_am_color_155b">#0000155b</color>
+    <color name="i_am_color_155c">#0000155c</color>
+    <color name="i_am_color_155d">#0000155d</color>
+    <color name="i_am_color_155e">#0000155e</color>
+    <color name="i_am_color_155f">#0000155f</color>
+    <color name="i_am_color_1560">#00001560</color>
+    <color name="i_am_color_1561">#00001561</color>
+    <color name="i_am_color_1562">#00001562</color>
+    <color name="i_am_color_1563">#00001563</color>
+    <color name="i_am_color_1564">#00001564</color>
+    <color name="i_am_color_1565">#00001565</color>
+    <color name="i_am_color_1566">#00001566</color>
+    <color name="i_am_color_1567">#00001567</color>
+    <color name="i_am_color_1568">#00001568</color>
+    <color name="i_am_color_1569">#00001569</color>
+    <color name="i_am_color_156a">#0000156a</color>
+    <color name="i_am_color_156b">#0000156b</color>
+    <color name="i_am_color_156c">#0000156c</color>
+    <color name="i_am_color_156d">#0000156d</color>
+    <color name="i_am_color_156e">#0000156e</color>
+    <color name="i_am_color_156f">#0000156f</color>
+    <color name="i_am_color_1570">#00001570</color>
+    <color name="i_am_color_1571">#00001571</color>
+    <color name="i_am_color_1572">#00001572</color>
+    <color name="i_am_color_1573">#00001573</color>
+    <color name="i_am_color_1574">#00001574</color>
+    <color name="i_am_color_1575">#00001575</color>
+    <color name="i_am_color_1576">#00001576</color>
+    <color name="i_am_color_1577">#00001577</color>
+    <color name="i_am_color_1578">#00001578</color>
+    <color name="i_am_color_1579">#00001579</color>
+    <color name="i_am_color_157a">#0000157a</color>
+    <color name="i_am_color_157b">#0000157b</color>
+    <color name="i_am_color_157c">#0000157c</color>
+    <color name="i_am_color_157d">#0000157d</color>
+    <color name="i_am_color_157e">#0000157e</color>
+    <color name="i_am_color_157f">#0000157f</color>
+    <color name="i_am_color_1580">#00001580</color>
+    <color name="i_am_color_1581">#00001581</color>
+    <color name="i_am_color_1582">#00001582</color>
+    <color name="i_am_color_1583">#00001583</color>
+    <color name="i_am_color_1584">#00001584</color>
+    <color name="i_am_color_1585">#00001585</color>
+    <color name="i_am_color_1586">#00001586</color>
+    <color name="i_am_color_1587">#00001587</color>
+    <color name="i_am_color_1588">#00001588</color>
+    <color name="i_am_color_1589">#00001589</color>
+    <color name="i_am_color_158a">#0000158a</color>
+    <color name="i_am_color_158b">#0000158b</color>
+    <color name="i_am_color_158c">#0000158c</color>
+    <color name="i_am_color_158d">#0000158d</color>
+    <color name="i_am_color_158e">#0000158e</color>
+    <color name="i_am_color_158f">#0000158f</color>
+    <color name="i_am_color_1590">#00001590</color>
+    <color name="i_am_color_1591">#00001591</color>
+    <color name="i_am_color_1592">#00001592</color>
+    <color name="i_am_color_1593">#00001593</color>
+    <color name="i_am_color_1594">#00001594</color>
+    <color name="i_am_color_1595">#00001595</color>
+    <color name="i_am_color_1596">#00001596</color>
+    <color name="i_am_color_1597">#00001597</color>
+    <color name="i_am_color_1598">#00001598</color>
+    <color name="i_am_color_1599">#00001599</color>
+    <color name="i_am_color_159a">#0000159a</color>
+    <color name="i_am_color_159b">#0000159b</color>
+    <color name="i_am_color_159c">#0000159c</color>
+    <color name="i_am_color_159d">#0000159d</color>
+    <color name="i_am_color_159e">#0000159e</color>
+    <color name="i_am_color_159f">#0000159f</color>
+    <color name="i_am_color_15a0">#000015a0</color>
+    <color name="i_am_color_15a1">#000015a1</color>
+    <color name="i_am_color_15a2">#000015a2</color>
+    <color name="i_am_color_15a3">#000015a3</color>
+    <color name="i_am_color_15a4">#000015a4</color>
+    <color name="i_am_color_15a5">#000015a5</color>
+    <color name="i_am_color_15a6">#000015a6</color>
+    <color name="i_am_color_15a7">#000015a7</color>
+    <color name="i_am_color_15a8">#000015a8</color>
+    <color name="i_am_color_15a9">#000015a9</color>
+    <color name="i_am_color_15aa">#000015aa</color>
+    <color name="i_am_color_15ab">#000015ab</color>
+    <color name="i_am_color_15ac">#000015ac</color>
+    <color name="i_am_color_15ad">#000015ad</color>
+    <color name="i_am_color_15ae">#000015ae</color>
+    <color name="i_am_color_15af">#000015af</color>
+    <color name="i_am_color_15b0">#000015b0</color>
+    <color name="i_am_color_15b1">#000015b1</color>
+    <color name="i_am_color_15b2">#000015b2</color>
+    <color name="i_am_color_15b3">#000015b3</color>
+    <color name="i_am_color_15b4">#000015b4</color>
+    <color name="i_am_color_15b5">#000015b5</color>
+    <color name="i_am_color_15b6">#000015b6</color>
+    <color name="i_am_color_15b7">#000015b7</color>
+    <color name="i_am_color_15b8">#000015b8</color>
+    <color name="i_am_color_15b9">#000015b9</color>
+    <color name="i_am_color_15ba">#000015ba</color>
+    <color name="i_am_color_15bb">#000015bb</color>
+    <color name="i_am_color_15bc">#000015bc</color>
+    <color name="i_am_color_15bd">#000015bd</color>
+    <color name="i_am_color_15be">#000015be</color>
+    <color name="i_am_color_15bf">#000015bf</color>
+    <color name="i_am_color_15c0">#000015c0</color>
+    <color name="i_am_color_15c1">#000015c1</color>
+    <color name="i_am_color_15c2">#000015c2</color>
+    <color name="i_am_color_15c3">#000015c3</color>
+    <color name="i_am_color_15c4">#000015c4</color>
+    <color name="i_am_color_15c5">#000015c5</color>
+    <color name="i_am_color_15c6">#000015c6</color>
+    <color name="i_am_color_15c7">#000015c7</color>
+    <color name="i_am_color_15c8">#000015c8</color>
+    <color name="i_am_color_15c9">#000015c9</color>
+    <color name="i_am_color_15ca">#000015ca</color>
+    <color name="i_am_color_15cb">#000015cb</color>
+    <color name="i_am_color_15cc">#000015cc</color>
+    <color name="i_am_color_15cd">#000015cd</color>
+    <color name="i_am_color_15ce">#000015ce</color>
+    <color name="i_am_color_15cf">#000015cf</color>
+    <color name="i_am_color_15d0">#000015d0</color>
+    <color name="i_am_color_15d1">#000015d1</color>
+    <color name="i_am_color_15d2">#000015d2</color>
+    <color name="i_am_color_15d3">#000015d3</color>
+    <color name="i_am_color_15d4">#000015d4</color>
+    <color name="i_am_color_15d5">#000015d5</color>
+    <color name="i_am_color_15d6">#000015d6</color>
+    <color name="i_am_color_15d7">#000015d7</color>
+    <color name="i_am_color_15d8">#000015d8</color>
+    <color name="i_am_color_15d9">#000015d9</color>
+    <color name="i_am_color_15da">#000015da</color>
+    <color name="i_am_color_15db">#000015db</color>
+    <color name="i_am_color_15dc">#000015dc</color>
+    <color name="i_am_color_15dd">#000015dd</color>
+    <color name="i_am_color_15de">#000015de</color>
+    <color name="i_am_color_15df">#000015df</color>
+    <color name="i_am_color_15e0">#000015e0</color>
+    <color name="i_am_color_15e1">#000015e1</color>
+    <color name="i_am_color_15e2">#000015e2</color>
+    <color name="i_am_color_15e3">#000015e3</color>
+    <color name="i_am_color_15e4">#000015e4</color>
+    <color name="i_am_color_15e5">#000015e5</color>
+    <color name="i_am_color_15e6">#000015e6</color>
+    <color name="i_am_color_15e7">#000015e7</color>
+    <color name="i_am_color_15e8">#000015e8</color>
+    <color name="i_am_color_15e9">#000015e9</color>
+    <color name="i_am_color_15ea">#000015ea</color>
+    <color name="i_am_color_15eb">#000015eb</color>
+    <color name="i_am_color_15ec">#000015ec</color>
+    <color name="i_am_color_15ed">#000015ed</color>
+    <color name="i_am_color_15ee">#000015ee</color>
+    <color name="i_am_color_15ef">#000015ef</color>
+    <color name="i_am_color_15f0">#000015f0</color>
+    <color name="i_am_color_15f1">#000015f1</color>
+    <color name="i_am_color_15f2">#000015f2</color>
+    <color name="i_am_color_15f3">#000015f3</color>
+    <color name="i_am_color_15f4">#000015f4</color>
+    <color name="i_am_color_15f5">#000015f5</color>
+    <color name="i_am_color_15f6">#000015f6</color>
+    <color name="i_am_color_15f7">#000015f7</color>
+    <color name="i_am_color_15f8">#000015f8</color>
+    <color name="i_am_color_15f9">#000015f9</color>
+    <color name="i_am_color_15fa">#000015fa</color>
+    <color name="i_am_color_15fb">#000015fb</color>
+    <color name="i_am_color_15fc">#000015fc</color>
+    <color name="i_am_color_15fd">#000015fd</color>
+    <color name="i_am_color_15fe">#000015fe</color>
+    <color name="i_am_color_15ff">#000015ff</color>
+    <color name="i_am_color_1600">#00001600</color>
+    <color name="i_am_color_1601">#00001601</color>
+    <color name="i_am_color_1602">#00001602</color>
+    <color name="i_am_color_1603">#00001603</color>
+    <color name="i_am_color_1604">#00001604</color>
+    <color name="i_am_color_1605">#00001605</color>
+    <color name="i_am_color_1606">#00001606</color>
+    <color name="i_am_color_1607">#00001607</color>
+    <color name="i_am_color_1608">#00001608</color>
+    <color name="i_am_color_1609">#00001609</color>
+    <color name="i_am_color_160a">#0000160a</color>
+    <color name="i_am_color_160b">#0000160b</color>
+    <color name="i_am_color_160c">#0000160c</color>
+    <color name="i_am_color_160d">#0000160d</color>
+    <color name="i_am_color_160e">#0000160e</color>
+    <color name="i_am_color_160f">#0000160f</color>
+    <color name="i_am_color_1610">#00001610</color>
+    <color name="i_am_color_1611">#00001611</color>
+    <color name="i_am_color_1612">#00001612</color>
+    <color name="i_am_color_1613">#00001613</color>
+    <color name="i_am_color_1614">#00001614</color>
+    <color name="i_am_color_1615">#00001615</color>
+    <color name="i_am_color_1616">#00001616</color>
+    <color name="i_am_color_1617">#00001617</color>
+    <color name="i_am_color_1618">#00001618</color>
+    <color name="i_am_color_1619">#00001619</color>
+    <color name="i_am_color_161a">#0000161a</color>
+    <color name="i_am_color_161b">#0000161b</color>
+    <color name="i_am_color_161c">#0000161c</color>
+    <color name="i_am_color_161d">#0000161d</color>
+    <color name="i_am_color_161e">#0000161e</color>
+    <color name="i_am_color_161f">#0000161f</color>
+    <color name="i_am_color_1620">#00001620</color>
+    <color name="i_am_color_1621">#00001621</color>
+    <color name="i_am_color_1622">#00001622</color>
+    <color name="i_am_color_1623">#00001623</color>
+    <color name="i_am_color_1624">#00001624</color>
+    <color name="i_am_color_1625">#00001625</color>
+    <color name="i_am_color_1626">#00001626</color>
+    <color name="i_am_color_1627">#00001627</color>
+    <color name="i_am_color_1628">#00001628</color>
+    <color name="i_am_color_1629">#00001629</color>
+    <color name="i_am_color_162a">#0000162a</color>
+    <color name="i_am_color_162b">#0000162b</color>
+    <color name="i_am_color_162c">#0000162c</color>
+    <color name="i_am_color_162d">#0000162d</color>
+    <color name="i_am_color_162e">#0000162e</color>
+    <color name="i_am_color_162f">#0000162f</color>
+    <color name="i_am_color_1630">#00001630</color>
+    <color name="i_am_color_1631">#00001631</color>
+    <color name="i_am_color_1632">#00001632</color>
+    <color name="i_am_color_1633">#00001633</color>
+    <color name="i_am_color_1634">#00001634</color>
+    <color name="i_am_color_1635">#00001635</color>
+    <color name="i_am_color_1636">#00001636</color>
+    <color name="i_am_color_1637">#00001637</color>
+    <color name="i_am_color_1638">#00001638</color>
+    <color name="i_am_color_1639">#00001639</color>
+    <color name="i_am_color_163a">#0000163a</color>
+    <color name="i_am_color_163b">#0000163b</color>
+    <color name="i_am_color_163c">#0000163c</color>
+    <color name="i_am_color_163d">#0000163d</color>
+    <color name="i_am_color_163e">#0000163e</color>
+    <color name="i_am_color_163f">#0000163f</color>
+    <color name="i_am_color_1640">#00001640</color>
+    <color name="i_am_color_1641">#00001641</color>
+    <color name="i_am_color_1642">#00001642</color>
+    <color name="i_am_color_1643">#00001643</color>
+    <color name="i_am_color_1644">#00001644</color>
+    <color name="i_am_color_1645">#00001645</color>
+    <color name="i_am_color_1646">#00001646</color>
+    <color name="i_am_color_1647">#00001647</color>
+    <color name="i_am_color_1648">#00001648</color>
+    <color name="i_am_color_1649">#00001649</color>
+    <color name="i_am_color_164a">#0000164a</color>
+    <color name="i_am_color_164b">#0000164b</color>
+    <color name="i_am_color_164c">#0000164c</color>
+    <color name="i_am_color_164d">#0000164d</color>
+    <color name="i_am_color_164e">#0000164e</color>
+    <color name="i_am_color_164f">#0000164f</color>
+    <color name="i_am_color_1650">#00001650</color>
+    <color name="i_am_color_1651">#00001651</color>
+    <color name="i_am_color_1652">#00001652</color>
+    <color name="i_am_color_1653">#00001653</color>
+    <color name="i_am_color_1654">#00001654</color>
+    <color name="i_am_color_1655">#00001655</color>
+    <color name="i_am_color_1656">#00001656</color>
+    <color name="i_am_color_1657">#00001657</color>
+    <color name="i_am_color_1658">#00001658</color>
+    <color name="i_am_color_1659">#00001659</color>
+    <color name="i_am_color_165a">#0000165a</color>
+    <color name="i_am_color_165b">#0000165b</color>
+    <color name="i_am_color_165c">#0000165c</color>
+    <color name="i_am_color_165d">#0000165d</color>
+    <color name="i_am_color_165e">#0000165e</color>
+    <color name="i_am_color_165f">#0000165f</color>
+    <color name="i_am_color_1660">#00001660</color>
+    <color name="i_am_color_1661">#00001661</color>
+    <color name="i_am_color_1662">#00001662</color>
+    <color name="i_am_color_1663">#00001663</color>
+    <color name="i_am_color_1664">#00001664</color>
+    <color name="i_am_color_1665">#00001665</color>
+    <color name="i_am_color_1666">#00001666</color>
+    <color name="i_am_color_1667">#00001667</color>
+    <color name="i_am_color_1668">#00001668</color>
+    <color name="i_am_color_1669">#00001669</color>
+    <color name="i_am_color_166a">#0000166a</color>
+    <color name="i_am_color_166b">#0000166b</color>
+    <color name="i_am_color_166c">#0000166c</color>
+    <color name="i_am_color_166d">#0000166d</color>
+    <color name="i_am_color_166e">#0000166e</color>
+    <color name="i_am_color_166f">#0000166f</color>
+    <color name="i_am_color_1670">#00001670</color>
+    <color name="i_am_color_1671">#00001671</color>
+    <color name="i_am_color_1672">#00001672</color>
+    <color name="i_am_color_1673">#00001673</color>
+    <color name="i_am_color_1674">#00001674</color>
+    <color name="i_am_color_1675">#00001675</color>
+    <color name="i_am_color_1676">#00001676</color>
+    <color name="i_am_color_1677">#00001677</color>
+    <color name="i_am_color_1678">#00001678</color>
+    <color name="i_am_color_1679">#00001679</color>
+    <color name="i_am_color_167a">#0000167a</color>
+    <color name="i_am_color_167b">#0000167b</color>
+    <color name="i_am_color_167c">#0000167c</color>
+    <color name="i_am_color_167d">#0000167d</color>
+    <color name="i_am_color_167e">#0000167e</color>
+    <color name="i_am_color_167f">#0000167f</color>
+    <color name="i_am_color_1680">#00001680</color>
+    <color name="i_am_color_1681">#00001681</color>
+    <color name="i_am_color_1682">#00001682</color>
+    <color name="i_am_color_1683">#00001683</color>
+    <color name="i_am_color_1684">#00001684</color>
+    <color name="i_am_color_1685">#00001685</color>
+    <color name="i_am_color_1686">#00001686</color>
+    <color name="i_am_color_1687">#00001687</color>
+    <color name="i_am_color_1688">#00001688</color>
+    <color name="i_am_color_1689">#00001689</color>
+    <color name="i_am_color_168a">#0000168a</color>
+    <color name="i_am_color_168b">#0000168b</color>
+    <color name="i_am_color_168c">#0000168c</color>
+    <color name="i_am_color_168d">#0000168d</color>
+    <color name="i_am_color_168e">#0000168e</color>
+    <color name="i_am_color_168f">#0000168f</color>
+    <color name="i_am_color_1690">#00001690</color>
+    <color name="i_am_color_1691">#00001691</color>
+    <color name="i_am_color_1692">#00001692</color>
+    <color name="i_am_color_1693">#00001693</color>
+    <color name="i_am_color_1694">#00001694</color>
+    <color name="i_am_color_1695">#00001695</color>
+    <color name="i_am_color_1696">#00001696</color>
+    <color name="i_am_color_1697">#00001697</color>
+    <color name="i_am_color_1698">#00001698</color>
+    <color name="i_am_color_1699">#00001699</color>
+    <color name="i_am_color_169a">#0000169a</color>
+    <color name="i_am_color_169b">#0000169b</color>
+    <color name="i_am_color_169c">#0000169c</color>
+    <color name="i_am_color_169d">#0000169d</color>
+    <color name="i_am_color_169e">#0000169e</color>
+    <color name="i_am_color_169f">#0000169f</color>
+    <color name="i_am_color_16a0">#000016a0</color>
+    <color name="i_am_color_16a1">#000016a1</color>
+    <color name="i_am_color_16a2">#000016a2</color>
+    <color name="i_am_color_16a3">#000016a3</color>
+    <color name="i_am_color_16a4">#000016a4</color>
+    <color name="i_am_color_16a5">#000016a5</color>
+    <color name="i_am_color_16a6">#000016a6</color>
+    <color name="i_am_color_16a7">#000016a7</color>
+    <color name="i_am_color_16a8">#000016a8</color>
+    <color name="i_am_color_16a9">#000016a9</color>
+    <color name="i_am_color_16aa">#000016aa</color>
+    <color name="i_am_color_16ab">#000016ab</color>
+    <color name="i_am_color_16ac">#000016ac</color>
+    <color name="i_am_color_16ad">#000016ad</color>
+    <color name="i_am_color_16ae">#000016ae</color>
+    <color name="i_am_color_16af">#000016af</color>
+    <color name="i_am_color_16b0">#000016b0</color>
+    <color name="i_am_color_16b1">#000016b1</color>
+    <color name="i_am_color_16b2">#000016b2</color>
+    <color name="i_am_color_16b3">#000016b3</color>
+    <color name="i_am_color_16b4">#000016b4</color>
+    <color name="i_am_color_16b5">#000016b5</color>
+    <color name="i_am_color_16b6">#000016b6</color>
+    <color name="i_am_color_16b7">#000016b7</color>
+    <color name="i_am_color_16b8">#000016b8</color>
+    <color name="i_am_color_16b9">#000016b9</color>
+    <color name="i_am_color_16ba">#000016ba</color>
+    <color name="i_am_color_16bb">#000016bb</color>
+    <color name="i_am_color_16bc">#000016bc</color>
+    <color name="i_am_color_16bd">#000016bd</color>
+    <color name="i_am_color_16be">#000016be</color>
+    <color name="i_am_color_16bf">#000016bf</color>
+    <color name="i_am_color_16c0">#000016c0</color>
+    <color name="i_am_color_16c1">#000016c1</color>
+    <color name="i_am_color_16c2">#000016c2</color>
+    <color name="i_am_color_16c3">#000016c3</color>
+    <color name="i_am_color_16c4">#000016c4</color>
+    <color name="i_am_color_16c5">#000016c5</color>
+    <color name="i_am_color_16c6">#000016c6</color>
+    <color name="i_am_color_16c7">#000016c7</color>
+    <color name="i_am_color_16c8">#000016c8</color>
+    <color name="i_am_color_16c9">#000016c9</color>
+    <color name="i_am_color_16ca">#000016ca</color>
+    <color name="i_am_color_16cb">#000016cb</color>
+    <color name="i_am_color_16cc">#000016cc</color>
+    <color name="i_am_color_16cd">#000016cd</color>
+    <color name="i_am_color_16ce">#000016ce</color>
+    <color name="i_am_color_16cf">#000016cf</color>
+    <color name="i_am_color_16d0">#000016d0</color>
+    <color name="i_am_color_16d1">#000016d1</color>
+    <color name="i_am_color_16d2">#000016d2</color>
+    <color name="i_am_color_16d3">#000016d3</color>
+    <color name="i_am_color_16d4">#000016d4</color>
+    <color name="i_am_color_16d5">#000016d5</color>
+    <color name="i_am_color_16d6">#000016d6</color>
+    <color name="i_am_color_16d7">#000016d7</color>
+    <color name="i_am_color_16d8">#000016d8</color>
+    <color name="i_am_color_16d9">#000016d9</color>
+    <color name="i_am_color_16da">#000016da</color>
+    <color name="i_am_color_16db">#000016db</color>
+    <color name="i_am_color_16dc">#000016dc</color>
+    <color name="i_am_color_16dd">#000016dd</color>
+    <color name="i_am_color_16de">#000016de</color>
+    <color name="i_am_color_16df">#000016df</color>
+    <color name="i_am_color_16e0">#000016e0</color>
+    <color name="i_am_color_16e1">#000016e1</color>
+    <color name="i_am_color_16e2">#000016e2</color>
+    <color name="i_am_color_16e3">#000016e3</color>
+    <color name="i_am_color_16e4">#000016e4</color>
+    <color name="i_am_color_16e5">#000016e5</color>
+    <color name="i_am_color_16e6">#000016e6</color>
+    <color name="i_am_color_16e7">#000016e7</color>
+    <color name="i_am_color_16e8">#000016e8</color>
+    <color name="i_am_color_16e9">#000016e9</color>
+    <color name="i_am_color_16ea">#000016ea</color>
+    <color name="i_am_color_16eb">#000016eb</color>
+    <color name="i_am_color_16ec">#000016ec</color>
+    <color name="i_am_color_16ed">#000016ed</color>
+    <color name="i_am_color_16ee">#000016ee</color>
+    <color name="i_am_color_16ef">#000016ef</color>
+    <color name="i_am_color_16f0">#000016f0</color>
+    <color name="i_am_color_16f1">#000016f1</color>
+    <color name="i_am_color_16f2">#000016f2</color>
+    <color name="i_am_color_16f3">#000016f3</color>
+    <color name="i_am_color_16f4">#000016f4</color>
+    <color name="i_am_color_16f5">#000016f5</color>
+    <color name="i_am_color_16f6">#000016f6</color>
+    <color name="i_am_color_16f7">#000016f7</color>
+    <color name="i_am_color_16f8">#000016f8</color>
+    <color name="i_am_color_16f9">#000016f9</color>
+    <color name="i_am_color_16fa">#000016fa</color>
+    <color name="i_am_color_16fb">#000016fb</color>
+    <color name="i_am_color_16fc">#000016fc</color>
+    <color name="i_am_color_16fd">#000016fd</color>
+    <color name="i_am_color_16fe">#000016fe</color>
+    <color name="i_am_color_16ff">#000016ff</color>
+    <color name="i_am_color_1700">#00001700</color>
+    <color name="i_am_color_1701">#00001701</color>
+    <color name="i_am_color_1702">#00001702</color>
+    <color name="i_am_color_1703">#00001703</color>
+    <color name="i_am_color_1704">#00001704</color>
+    <color name="i_am_color_1705">#00001705</color>
+    <color name="i_am_color_1706">#00001706</color>
+    <color name="i_am_color_1707">#00001707</color>
+    <color name="i_am_color_1708">#00001708</color>
+    <color name="i_am_color_1709">#00001709</color>
+    <color name="i_am_color_170a">#0000170a</color>
+    <color name="i_am_color_170b">#0000170b</color>
+    <color name="i_am_color_170c">#0000170c</color>
+    <color name="i_am_color_170d">#0000170d</color>
+    <color name="i_am_color_170e">#0000170e</color>
+    <color name="i_am_color_170f">#0000170f</color>
+    <color name="i_am_color_1710">#00001710</color>
+    <color name="i_am_color_1711">#00001711</color>
+    <color name="i_am_color_1712">#00001712</color>
+    <color name="i_am_color_1713">#00001713</color>
+    <color name="i_am_color_1714">#00001714</color>
+    <color name="i_am_color_1715">#00001715</color>
+    <color name="i_am_color_1716">#00001716</color>
+    <color name="i_am_color_1717">#00001717</color>
+    <color name="i_am_color_1718">#00001718</color>
+    <color name="i_am_color_1719">#00001719</color>
+    <color name="i_am_color_171a">#0000171a</color>
+    <color name="i_am_color_171b">#0000171b</color>
+    <color name="i_am_color_171c">#0000171c</color>
+    <color name="i_am_color_171d">#0000171d</color>
+    <color name="i_am_color_171e">#0000171e</color>
+    <color name="i_am_color_171f">#0000171f</color>
+    <color name="i_am_color_1720">#00001720</color>
+    <color name="i_am_color_1721">#00001721</color>
+    <color name="i_am_color_1722">#00001722</color>
+    <color name="i_am_color_1723">#00001723</color>
+    <color name="i_am_color_1724">#00001724</color>
+    <color name="i_am_color_1725">#00001725</color>
+    <color name="i_am_color_1726">#00001726</color>
+    <color name="i_am_color_1727">#00001727</color>
+    <color name="i_am_color_1728">#00001728</color>
+    <color name="i_am_color_1729">#00001729</color>
+    <color name="i_am_color_172a">#0000172a</color>
+    <color name="i_am_color_172b">#0000172b</color>
+    <color name="i_am_color_172c">#0000172c</color>
+    <color name="i_am_color_172d">#0000172d</color>
+    <color name="i_am_color_172e">#0000172e</color>
+    <color name="i_am_color_172f">#0000172f</color>
+    <color name="i_am_color_1730">#00001730</color>
+    <color name="i_am_color_1731">#00001731</color>
+    <color name="i_am_color_1732">#00001732</color>
+    <color name="i_am_color_1733">#00001733</color>
+    <color name="i_am_color_1734">#00001734</color>
+    <color name="i_am_color_1735">#00001735</color>
+    <color name="i_am_color_1736">#00001736</color>
+    <color name="i_am_color_1737">#00001737</color>
+    <color name="i_am_color_1738">#00001738</color>
+    <color name="i_am_color_1739">#00001739</color>
+    <color name="i_am_color_173a">#0000173a</color>
+    <color name="i_am_color_173b">#0000173b</color>
+    <color name="i_am_color_173c">#0000173c</color>
+    <color name="i_am_color_173d">#0000173d</color>
+    <color name="i_am_color_173e">#0000173e</color>
+    <color name="i_am_color_173f">#0000173f</color>
+    <color name="i_am_color_1740">#00001740</color>
+    <color name="i_am_color_1741">#00001741</color>
+    <color name="i_am_color_1742">#00001742</color>
+    <color name="i_am_color_1743">#00001743</color>
+    <color name="i_am_color_1744">#00001744</color>
+    <color name="i_am_color_1745">#00001745</color>
+    <color name="i_am_color_1746">#00001746</color>
+    <color name="i_am_color_1747">#00001747</color>
+    <color name="i_am_color_1748">#00001748</color>
+    <color name="i_am_color_1749">#00001749</color>
+    <color name="i_am_color_174a">#0000174a</color>
+    <color name="i_am_color_174b">#0000174b</color>
+    <color name="i_am_color_174c">#0000174c</color>
+    <color name="i_am_color_174d">#0000174d</color>
+    <color name="i_am_color_174e">#0000174e</color>
+    <color name="i_am_color_174f">#0000174f</color>
+    <color name="i_am_color_1750">#00001750</color>
+    <color name="i_am_color_1751">#00001751</color>
+    <color name="i_am_color_1752">#00001752</color>
+    <color name="i_am_color_1753">#00001753</color>
+    <color name="i_am_color_1754">#00001754</color>
+    <color name="i_am_color_1755">#00001755</color>
+    <color name="i_am_color_1756">#00001756</color>
+    <color name="i_am_color_1757">#00001757</color>
+    <color name="i_am_color_1758">#00001758</color>
+    <color name="i_am_color_1759">#00001759</color>
+    <color name="i_am_color_175a">#0000175a</color>
+    <color name="i_am_color_175b">#0000175b</color>
+    <color name="i_am_color_175c">#0000175c</color>
+    <color name="i_am_color_175d">#0000175d</color>
+    <color name="i_am_color_175e">#0000175e</color>
+    <color name="i_am_color_175f">#0000175f</color>
+    <color name="i_am_color_1760">#00001760</color>
+    <color name="i_am_color_1761">#00001761</color>
+    <color name="i_am_color_1762">#00001762</color>
+    <color name="i_am_color_1763">#00001763</color>
+    <color name="i_am_color_1764">#00001764</color>
+    <color name="i_am_color_1765">#00001765</color>
+    <color name="i_am_color_1766">#00001766</color>
+    <color name="i_am_color_1767">#00001767</color>
+    <color name="i_am_color_1768">#00001768</color>
+    <color name="i_am_color_1769">#00001769</color>
+    <color name="i_am_color_176a">#0000176a</color>
+    <color name="i_am_color_176b">#0000176b</color>
+    <color name="i_am_color_176c">#0000176c</color>
+    <color name="i_am_color_176d">#0000176d</color>
+    <color name="i_am_color_176e">#0000176e</color>
+    <color name="i_am_color_176f">#0000176f</color>
+    <color name="i_am_color_1770">#00001770</color>
+    <color name="i_am_color_1771">#00001771</color>
+    <color name="i_am_color_1772">#00001772</color>
+    <color name="i_am_color_1773">#00001773</color>
+    <color name="i_am_color_1774">#00001774</color>
+    <color name="i_am_color_1775">#00001775</color>
+    <color name="i_am_color_1776">#00001776</color>
+    <color name="i_am_color_1777">#00001777</color>
+    <color name="i_am_color_1778">#00001778</color>
+    <color name="i_am_color_1779">#00001779</color>
+    <color name="i_am_color_177a">#0000177a</color>
+    <color name="i_am_color_177b">#0000177b</color>
+    <color name="i_am_color_177c">#0000177c</color>
+    <color name="i_am_color_177d">#0000177d</color>
+    <color name="i_am_color_177e">#0000177e</color>
+    <color name="i_am_color_177f">#0000177f</color>
+    <color name="i_am_color_1780">#00001780</color>
+    <color name="i_am_color_1781">#00001781</color>
+    <color name="i_am_color_1782">#00001782</color>
+    <color name="i_am_color_1783">#00001783</color>
+    <color name="i_am_color_1784">#00001784</color>
+    <color name="i_am_color_1785">#00001785</color>
+    <color name="i_am_color_1786">#00001786</color>
+    <color name="i_am_color_1787">#00001787</color>
+    <color name="i_am_color_1788">#00001788</color>
+    <color name="i_am_color_1789">#00001789</color>
+    <color name="i_am_color_178a">#0000178a</color>
+    <color name="i_am_color_178b">#0000178b</color>
+    <color name="i_am_color_178c">#0000178c</color>
+    <color name="i_am_color_178d">#0000178d</color>
+    <color name="i_am_color_178e">#0000178e</color>
+    <color name="i_am_color_178f">#0000178f</color>
+    <color name="i_am_color_1790">#00001790</color>
+    <color name="i_am_color_1791">#00001791</color>
+    <color name="i_am_color_1792">#00001792</color>
+    <color name="i_am_color_1793">#00001793</color>
+    <color name="i_am_color_1794">#00001794</color>
+    <color name="i_am_color_1795">#00001795</color>
+    <color name="i_am_color_1796">#00001796</color>
+    <color name="i_am_color_1797">#00001797</color>
+    <color name="i_am_color_1798">#00001798</color>
+    <color name="i_am_color_1799">#00001799</color>
+    <color name="i_am_color_179a">#0000179a</color>
+    <color name="i_am_color_179b">#0000179b</color>
+    <color name="i_am_color_179c">#0000179c</color>
+    <color name="i_am_color_179d">#0000179d</color>
+    <color name="i_am_color_179e">#0000179e</color>
+    <color name="i_am_color_179f">#0000179f</color>
+    <color name="i_am_color_17a0">#000017a0</color>
+    <color name="i_am_color_17a1">#000017a1</color>
+    <color name="i_am_color_17a2">#000017a2</color>
+    <color name="i_am_color_17a3">#000017a3</color>
+    <color name="i_am_color_17a4">#000017a4</color>
+    <color name="i_am_color_17a5">#000017a5</color>
+    <color name="i_am_color_17a6">#000017a6</color>
+    <color name="i_am_color_17a7">#000017a7</color>
+    <color name="i_am_color_17a8">#000017a8</color>
+    <color name="i_am_color_17a9">#000017a9</color>
+    <color name="i_am_color_17aa">#000017aa</color>
+    <color name="i_am_color_17ab">#000017ab</color>
+    <color name="i_am_color_17ac">#000017ac</color>
+    <color name="i_am_color_17ad">#000017ad</color>
+    <color name="i_am_color_17ae">#000017ae</color>
+    <color name="i_am_color_17af">#000017af</color>
+    <color name="i_am_color_17b0">#000017b0</color>
+    <color name="i_am_color_17b1">#000017b1</color>
+    <color name="i_am_color_17b2">#000017b2</color>
+    <color name="i_am_color_17b3">#000017b3</color>
+    <color name="i_am_color_17b4">#000017b4</color>
+    <color name="i_am_color_17b5">#000017b5</color>
+    <color name="i_am_color_17b6">#000017b6</color>
+    <color name="i_am_color_17b7">#000017b7</color>
+    <color name="i_am_color_17b8">#000017b8</color>
+    <color name="i_am_color_17b9">#000017b9</color>
+    <color name="i_am_color_17ba">#000017ba</color>
+    <color name="i_am_color_17bb">#000017bb</color>
+    <color name="i_am_color_17bc">#000017bc</color>
+    <color name="i_am_color_17bd">#000017bd</color>
+    <color name="i_am_color_17be">#000017be</color>
+    <color name="i_am_color_17bf">#000017bf</color>
+    <color name="i_am_color_17c0">#000017c0</color>
+    <color name="i_am_color_17c1">#000017c1</color>
+    <color name="i_am_color_17c2">#000017c2</color>
+    <color name="i_am_color_17c3">#000017c3</color>
+    <color name="i_am_color_17c4">#000017c4</color>
+    <color name="i_am_color_17c5">#000017c5</color>
+    <color name="i_am_color_17c6">#000017c6</color>
+    <color name="i_am_color_17c7">#000017c7</color>
+    <color name="i_am_color_17c8">#000017c8</color>
+    <color name="i_am_color_17c9">#000017c9</color>
+    <color name="i_am_color_17ca">#000017ca</color>
+    <color name="i_am_color_17cb">#000017cb</color>
+    <color name="i_am_color_17cc">#000017cc</color>
+    <color name="i_am_color_17cd">#000017cd</color>
+    <color name="i_am_color_17ce">#000017ce</color>
+    <color name="i_am_color_17cf">#000017cf</color>
+    <color name="i_am_color_17d0">#000017d0</color>
+    <color name="i_am_color_17d1">#000017d1</color>
+    <color name="i_am_color_17d2">#000017d2</color>
+    <color name="i_am_color_17d3">#000017d3</color>
+    <color name="i_am_color_17d4">#000017d4</color>
+    <color name="i_am_color_17d5">#000017d5</color>
+    <color name="i_am_color_17d6">#000017d6</color>
+    <color name="i_am_color_17d7">#000017d7</color>
+    <color name="i_am_color_17d8">#000017d8</color>
+    <color name="i_am_color_17d9">#000017d9</color>
+    <color name="i_am_color_17da">#000017da</color>
+    <color name="i_am_color_17db">#000017db</color>
+    <color name="i_am_color_17dc">#000017dc</color>
+    <color name="i_am_color_17dd">#000017dd</color>
+    <color name="i_am_color_17de">#000017de</color>
+    <color name="i_am_color_17df">#000017df</color>
+    <color name="i_am_color_17e0">#000017e0</color>
+    <color name="i_am_color_17e1">#000017e1</color>
+    <color name="i_am_color_17e2">#000017e2</color>
+    <color name="i_am_color_17e3">#000017e3</color>
+    <color name="i_am_color_17e4">#000017e4</color>
+    <color name="i_am_color_17e5">#000017e5</color>
+    <color name="i_am_color_17e6">#000017e6</color>
+    <color name="i_am_color_17e7">#000017e7</color>
+    <color name="i_am_color_17e8">#000017e8</color>
+    <color name="i_am_color_17e9">#000017e9</color>
+    <color name="i_am_color_17ea">#000017ea</color>
+    <color name="i_am_color_17eb">#000017eb</color>
+    <color name="i_am_color_17ec">#000017ec</color>
+    <color name="i_am_color_17ed">#000017ed</color>
+    <color name="i_am_color_17ee">#000017ee</color>
+    <color name="i_am_color_17ef">#000017ef</color>
+    <color name="i_am_color_17f0">#000017f0</color>
+    <color name="i_am_color_17f1">#000017f1</color>
+    <color name="i_am_color_17f2">#000017f2</color>
+    <color name="i_am_color_17f3">#000017f3</color>
+    <color name="i_am_color_17f4">#000017f4</color>
+    <color name="i_am_color_17f5">#000017f5</color>
+    <color name="i_am_color_17f6">#000017f6</color>
+    <color name="i_am_color_17f7">#000017f7</color>
+    <color name="i_am_color_17f8">#000017f8</color>
+    <color name="i_am_color_17f9">#000017f9</color>
+    <color name="i_am_color_17fa">#000017fa</color>
+    <color name="i_am_color_17fb">#000017fb</color>
+    <color name="i_am_color_17fc">#000017fc</color>
+    <color name="i_am_color_17fd">#000017fd</color>
+    <color name="i_am_color_17fe">#000017fe</color>
+    <color name="i_am_color_17ff">#000017ff</color>
+    <color name="i_am_color_1800">#00001800</color>
+    <color name="i_am_color_1801">#00001801</color>
+    <color name="i_am_color_1802">#00001802</color>
+    <color name="i_am_color_1803">#00001803</color>
+    <color name="i_am_color_1804">#00001804</color>
+    <color name="i_am_color_1805">#00001805</color>
+    <color name="i_am_color_1806">#00001806</color>
+    <color name="i_am_color_1807">#00001807</color>
+    <color name="i_am_color_1808">#00001808</color>
+    <color name="i_am_color_1809">#00001809</color>
+    <color name="i_am_color_180a">#0000180a</color>
+    <color name="i_am_color_180b">#0000180b</color>
+    <color name="i_am_color_180c">#0000180c</color>
+    <color name="i_am_color_180d">#0000180d</color>
+    <color name="i_am_color_180e">#0000180e</color>
+    <color name="i_am_color_180f">#0000180f</color>
+    <color name="i_am_color_1810">#00001810</color>
+    <color name="i_am_color_1811">#00001811</color>
+    <color name="i_am_color_1812">#00001812</color>
+    <color name="i_am_color_1813">#00001813</color>
+    <color name="i_am_color_1814">#00001814</color>
+    <color name="i_am_color_1815">#00001815</color>
+    <color name="i_am_color_1816">#00001816</color>
+    <color name="i_am_color_1817">#00001817</color>
+    <color name="i_am_color_1818">#00001818</color>
+    <color name="i_am_color_1819">#00001819</color>
+    <color name="i_am_color_181a">#0000181a</color>
+    <color name="i_am_color_181b">#0000181b</color>
+    <color name="i_am_color_181c">#0000181c</color>
+    <color name="i_am_color_181d">#0000181d</color>
+    <color name="i_am_color_181e">#0000181e</color>
+    <color name="i_am_color_181f">#0000181f</color>
+    <color name="i_am_color_1820">#00001820</color>
+    <color name="i_am_color_1821">#00001821</color>
+    <color name="i_am_color_1822">#00001822</color>
+    <color name="i_am_color_1823">#00001823</color>
+    <color name="i_am_color_1824">#00001824</color>
+    <color name="i_am_color_1825">#00001825</color>
+    <color name="i_am_color_1826">#00001826</color>
+    <color name="i_am_color_1827">#00001827</color>
+    <color name="i_am_color_1828">#00001828</color>
+    <color name="i_am_color_1829">#00001829</color>
+    <color name="i_am_color_182a">#0000182a</color>
+    <color name="i_am_color_182b">#0000182b</color>
+    <color name="i_am_color_182c">#0000182c</color>
+    <color name="i_am_color_182d">#0000182d</color>
+    <color name="i_am_color_182e">#0000182e</color>
+    <color name="i_am_color_182f">#0000182f</color>
+    <color name="i_am_color_1830">#00001830</color>
+    <color name="i_am_color_1831">#00001831</color>
+    <color name="i_am_color_1832">#00001832</color>
+    <color name="i_am_color_1833">#00001833</color>
+    <color name="i_am_color_1834">#00001834</color>
+    <color name="i_am_color_1835">#00001835</color>
+    <color name="i_am_color_1836">#00001836</color>
+    <color name="i_am_color_1837">#00001837</color>
+    <color name="i_am_color_1838">#00001838</color>
+    <color name="i_am_color_1839">#00001839</color>
+    <color name="i_am_color_183a">#0000183a</color>
+    <color name="i_am_color_183b">#0000183b</color>
+    <color name="i_am_color_183c">#0000183c</color>
+    <color name="i_am_color_183d">#0000183d</color>
+    <color name="i_am_color_183e">#0000183e</color>
+    <color name="i_am_color_183f">#0000183f</color>
+    <color name="i_am_color_1840">#00001840</color>
+    <color name="i_am_color_1841">#00001841</color>
+    <color name="i_am_color_1842">#00001842</color>
+    <color name="i_am_color_1843">#00001843</color>
+    <color name="i_am_color_1844">#00001844</color>
+    <color name="i_am_color_1845">#00001845</color>
+    <color name="i_am_color_1846">#00001846</color>
+    <color name="i_am_color_1847">#00001847</color>
+    <color name="i_am_color_1848">#00001848</color>
+    <color name="i_am_color_1849">#00001849</color>
+    <color name="i_am_color_184a">#0000184a</color>
+    <color name="i_am_color_184b">#0000184b</color>
+    <color name="i_am_color_184c">#0000184c</color>
+    <color name="i_am_color_184d">#0000184d</color>
+    <color name="i_am_color_184e">#0000184e</color>
+    <color name="i_am_color_184f">#0000184f</color>
+    <color name="i_am_color_1850">#00001850</color>
+    <color name="i_am_color_1851">#00001851</color>
+    <color name="i_am_color_1852">#00001852</color>
+    <color name="i_am_color_1853">#00001853</color>
+    <color name="i_am_color_1854">#00001854</color>
+    <color name="i_am_color_1855">#00001855</color>
+    <color name="i_am_color_1856">#00001856</color>
+    <color name="i_am_color_1857">#00001857</color>
+    <color name="i_am_color_1858">#00001858</color>
+    <color name="i_am_color_1859">#00001859</color>
+    <color name="i_am_color_185a">#0000185a</color>
+    <color name="i_am_color_185b">#0000185b</color>
+    <color name="i_am_color_185c">#0000185c</color>
+    <color name="i_am_color_185d">#0000185d</color>
+    <color name="i_am_color_185e">#0000185e</color>
+    <color name="i_am_color_185f">#0000185f</color>
+    <color name="i_am_color_1860">#00001860</color>
+    <color name="i_am_color_1861">#00001861</color>
+    <color name="i_am_color_1862">#00001862</color>
+    <color name="i_am_color_1863">#00001863</color>
+    <color name="i_am_color_1864">#00001864</color>
+    <color name="i_am_color_1865">#00001865</color>
+    <color name="i_am_color_1866">#00001866</color>
+    <color name="i_am_color_1867">#00001867</color>
+    <color name="i_am_color_1868">#00001868</color>
+    <color name="i_am_color_1869">#00001869</color>
+    <color name="i_am_color_186a">#0000186a</color>
+    <color name="i_am_color_186b">#0000186b</color>
+    <color name="i_am_color_186c">#0000186c</color>
+    <color name="i_am_color_186d">#0000186d</color>
+    <color name="i_am_color_186e">#0000186e</color>
+    <color name="i_am_color_186f">#0000186f</color>
+    <color name="i_am_color_1870">#00001870</color>
+    <color name="i_am_color_1871">#00001871</color>
+    <color name="i_am_color_1872">#00001872</color>
+    <color name="i_am_color_1873">#00001873</color>
+    <color name="i_am_color_1874">#00001874</color>
+    <color name="i_am_color_1875">#00001875</color>
+    <color name="i_am_color_1876">#00001876</color>
+    <color name="i_am_color_1877">#00001877</color>
+    <color name="i_am_color_1878">#00001878</color>
+    <color name="i_am_color_1879">#00001879</color>
+    <color name="i_am_color_187a">#0000187a</color>
+    <color name="i_am_color_187b">#0000187b</color>
+    <color name="i_am_color_187c">#0000187c</color>
+    <color name="i_am_color_187d">#0000187d</color>
+    <color name="i_am_color_187e">#0000187e</color>
+    <color name="i_am_color_187f">#0000187f</color>
+    <color name="i_am_color_1880">#00001880</color>
+    <color name="i_am_color_1881">#00001881</color>
+    <color name="i_am_color_1882">#00001882</color>
+    <color name="i_am_color_1883">#00001883</color>
+    <color name="i_am_color_1884">#00001884</color>
+    <color name="i_am_color_1885">#00001885</color>
+    <color name="i_am_color_1886">#00001886</color>
+    <color name="i_am_color_1887">#00001887</color>
+    <color name="i_am_color_1888">#00001888</color>
+    <color name="i_am_color_1889">#00001889</color>
+    <color name="i_am_color_188a">#0000188a</color>
+    <color name="i_am_color_188b">#0000188b</color>
+    <color name="i_am_color_188c">#0000188c</color>
+    <color name="i_am_color_188d">#0000188d</color>
+    <color name="i_am_color_188e">#0000188e</color>
+    <color name="i_am_color_188f">#0000188f</color>
+    <color name="i_am_color_1890">#00001890</color>
+    <color name="i_am_color_1891">#00001891</color>
+    <color name="i_am_color_1892">#00001892</color>
+    <color name="i_am_color_1893">#00001893</color>
+    <color name="i_am_color_1894">#00001894</color>
+    <color name="i_am_color_1895">#00001895</color>
+    <color name="i_am_color_1896">#00001896</color>
+    <color name="i_am_color_1897">#00001897</color>
+    <color name="i_am_color_1898">#00001898</color>
+    <color name="i_am_color_1899">#00001899</color>
+    <color name="i_am_color_189a">#0000189a</color>
+    <color name="i_am_color_189b">#0000189b</color>
+    <color name="i_am_color_189c">#0000189c</color>
+    <color name="i_am_color_189d">#0000189d</color>
+    <color name="i_am_color_189e">#0000189e</color>
+    <color name="i_am_color_189f">#0000189f</color>
+    <color name="i_am_color_18a0">#000018a0</color>
+    <color name="i_am_color_18a1">#000018a1</color>
+    <color name="i_am_color_18a2">#000018a2</color>
+    <color name="i_am_color_18a3">#000018a3</color>
+    <color name="i_am_color_18a4">#000018a4</color>
+    <color name="i_am_color_18a5">#000018a5</color>
+    <color name="i_am_color_18a6">#000018a6</color>
+    <color name="i_am_color_18a7">#000018a7</color>
+    <color name="i_am_color_18a8">#000018a8</color>
+    <color name="i_am_color_18a9">#000018a9</color>
+    <color name="i_am_color_18aa">#000018aa</color>
+    <color name="i_am_color_18ab">#000018ab</color>
+    <color name="i_am_color_18ac">#000018ac</color>
+    <color name="i_am_color_18ad">#000018ad</color>
+    <color name="i_am_color_18ae">#000018ae</color>
+    <color name="i_am_color_18af">#000018af</color>
+    <color name="i_am_color_18b0">#000018b0</color>
+    <color name="i_am_color_18b1">#000018b1</color>
+    <color name="i_am_color_18b2">#000018b2</color>
+    <color name="i_am_color_18b3">#000018b3</color>
+    <color name="i_am_color_18b4">#000018b4</color>
+    <color name="i_am_color_18b5">#000018b5</color>
+    <color name="i_am_color_18b6">#000018b6</color>
+    <color name="i_am_color_18b7">#000018b7</color>
+    <color name="i_am_color_18b8">#000018b8</color>
+    <color name="i_am_color_18b9">#000018b9</color>
+    <color name="i_am_color_18ba">#000018ba</color>
+    <color name="i_am_color_18bb">#000018bb</color>
+    <color name="i_am_color_18bc">#000018bc</color>
+    <color name="i_am_color_18bd">#000018bd</color>
+    <color name="i_am_color_18be">#000018be</color>
+    <color name="i_am_color_18bf">#000018bf</color>
+    <color name="i_am_color_18c0">#000018c0</color>
+    <color name="i_am_color_18c1">#000018c1</color>
+    <color name="i_am_color_18c2">#000018c2</color>
+    <color name="i_am_color_18c3">#000018c3</color>
+    <color name="i_am_color_18c4">#000018c4</color>
+    <color name="i_am_color_18c5">#000018c5</color>
+    <color name="i_am_color_18c6">#000018c6</color>
+    <color name="i_am_color_18c7">#000018c7</color>
+    <color name="i_am_color_18c8">#000018c8</color>
+    <color name="i_am_color_18c9">#000018c9</color>
+    <color name="i_am_color_18ca">#000018ca</color>
+    <color name="i_am_color_18cb">#000018cb</color>
+    <color name="i_am_color_18cc">#000018cc</color>
+    <color name="i_am_color_18cd">#000018cd</color>
+    <color name="i_am_color_18ce">#000018ce</color>
+    <color name="i_am_color_18cf">#000018cf</color>
+    <color name="i_am_color_18d0">#000018d0</color>
+    <color name="i_am_color_18d1">#000018d1</color>
+    <color name="i_am_color_18d2">#000018d2</color>
+    <color name="i_am_color_18d3">#000018d3</color>
+    <color name="i_am_color_18d4">#000018d4</color>
+    <color name="i_am_color_18d5">#000018d5</color>
+    <color name="i_am_color_18d6">#000018d6</color>
+    <color name="i_am_color_18d7">#000018d7</color>
+    <color name="i_am_color_18d8">#000018d8</color>
+    <color name="i_am_color_18d9">#000018d9</color>
+    <color name="i_am_color_18da">#000018da</color>
+    <color name="i_am_color_18db">#000018db</color>
+    <color name="i_am_color_18dc">#000018dc</color>
+    <color name="i_am_color_18dd">#000018dd</color>
+    <color name="i_am_color_18de">#000018de</color>
+    <color name="i_am_color_18df">#000018df</color>
+    <color name="i_am_color_18e0">#000018e0</color>
+    <color name="i_am_color_18e1">#000018e1</color>
+    <color name="i_am_color_18e2">#000018e2</color>
+    <color name="i_am_color_18e3">#000018e3</color>
+    <color name="i_am_color_18e4">#000018e4</color>
+    <color name="i_am_color_18e5">#000018e5</color>
+    <color name="i_am_color_18e6">#000018e6</color>
+    <color name="i_am_color_18e7">#000018e7</color>
+    <color name="i_am_color_18e8">#000018e8</color>
+    <color name="i_am_color_18e9">#000018e9</color>
+    <color name="i_am_color_18ea">#000018ea</color>
+    <color name="i_am_color_18eb">#000018eb</color>
+    <color name="i_am_color_18ec">#000018ec</color>
+    <color name="i_am_color_18ed">#000018ed</color>
+    <color name="i_am_color_18ee">#000018ee</color>
+    <color name="i_am_color_18ef">#000018ef</color>
+    <color name="i_am_color_18f0">#000018f0</color>
+    <color name="i_am_color_18f1">#000018f1</color>
+    <color name="i_am_color_18f2">#000018f2</color>
+    <color name="i_am_color_18f3">#000018f3</color>
+    <color name="i_am_color_18f4">#000018f4</color>
+    <color name="i_am_color_18f5">#000018f5</color>
+    <color name="i_am_color_18f6">#000018f6</color>
+    <color name="i_am_color_18f7">#000018f7</color>
+    <color name="i_am_color_18f8">#000018f8</color>
+    <color name="i_am_color_18f9">#000018f9</color>
+    <color name="i_am_color_18fa">#000018fa</color>
+    <color name="i_am_color_18fb">#000018fb</color>
+    <color name="i_am_color_18fc">#000018fc</color>
+    <color name="i_am_color_18fd">#000018fd</color>
+    <color name="i_am_color_18fe">#000018fe</color>
+    <color name="i_am_color_18ff">#000018ff</color>
+    <color name="i_am_color_1900">#00001900</color>
+    <color name="i_am_color_1901">#00001901</color>
+    <color name="i_am_color_1902">#00001902</color>
+    <color name="i_am_color_1903">#00001903</color>
+    <color name="i_am_color_1904">#00001904</color>
+    <color name="i_am_color_1905">#00001905</color>
+    <color name="i_am_color_1906">#00001906</color>
+    <color name="i_am_color_1907">#00001907</color>
+    <color name="i_am_color_1908">#00001908</color>
+    <color name="i_am_color_1909">#00001909</color>
+    <color name="i_am_color_190a">#0000190a</color>
+    <color name="i_am_color_190b">#0000190b</color>
+    <color name="i_am_color_190c">#0000190c</color>
+    <color name="i_am_color_190d">#0000190d</color>
+    <color name="i_am_color_190e">#0000190e</color>
+    <color name="i_am_color_190f">#0000190f</color>
+    <color name="i_am_color_1910">#00001910</color>
+    <color name="i_am_color_1911">#00001911</color>
+    <color name="i_am_color_1912">#00001912</color>
+    <color name="i_am_color_1913">#00001913</color>
+    <color name="i_am_color_1914">#00001914</color>
+    <color name="i_am_color_1915">#00001915</color>
+    <color name="i_am_color_1916">#00001916</color>
+    <color name="i_am_color_1917">#00001917</color>
+    <color name="i_am_color_1918">#00001918</color>
+    <color name="i_am_color_1919">#00001919</color>
+    <color name="i_am_color_191a">#0000191a</color>
+    <color name="i_am_color_191b">#0000191b</color>
+    <color name="i_am_color_191c">#0000191c</color>
+    <color name="i_am_color_191d">#0000191d</color>
+    <color name="i_am_color_191e">#0000191e</color>
+    <color name="i_am_color_191f">#0000191f</color>
+    <color name="i_am_color_1920">#00001920</color>
+    <color name="i_am_color_1921">#00001921</color>
+    <color name="i_am_color_1922">#00001922</color>
+    <color name="i_am_color_1923">#00001923</color>
+    <color name="i_am_color_1924">#00001924</color>
+    <color name="i_am_color_1925">#00001925</color>
+    <color name="i_am_color_1926">#00001926</color>
+    <color name="i_am_color_1927">#00001927</color>
+    <color name="i_am_color_1928">#00001928</color>
+    <color name="i_am_color_1929">#00001929</color>
+    <color name="i_am_color_192a">#0000192a</color>
+    <color name="i_am_color_192b">#0000192b</color>
+    <color name="i_am_color_192c">#0000192c</color>
+    <color name="i_am_color_192d">#0000192d</color>
+    <color name="i_am_color_192e">#0000192e</color>
+    <color name="i_am_color_192f">#0000192f</color>
+    <color name="i_am_color_1930">#00001930</color>
+    <color name="i_am_color_1931">#00001931</color>
+    <color name="i_am_color_1932">#00001932</color>
+    <color name="i_am_color_1933">#00001933</color>
+    <color name="i_am_color_1934">#00001934</color>
+    <color name="i_am_color_1935">#00001935</color>
+    <color name="i_am_color_1936">#00001936</color>
+    <color name="i_am_color_1937">#00001937</color>
+    <color name="i_am_color_1938">#00001938</color>
+    <color name="i_am_color_1939">#00001939</color>
+    <color name="i_am_color_193a">#0000193a</color>
+    <color name="i_am_color_193b">#0000193b</color>
+    <color name="i_am_color_193c">#0000193c</color>
+    <color name="i_am_color_193d">#0000193d</color>
+    <color name="i_am_color_193e">#0000193e</color>
+    <color name="i_am_color_193f">#0000193f</color>
+    <color name="i_am_color_1940">#00001940</color>
+    <color name="i_am_color_1941">#00001941</color>
+    <color name="i_am_color_1942">#00001942</color>
+    <color name="i_am_color_1943">#00001943</color>
+    <color name="i_am_color_1944">#00001944</color>
+    <color name="i_am_color_1945">#00001945</color>
+    <color name="i_am_color_1946">#00001946</color>
+    <color name="i_am_color_1947">#00001947</color>
+    <color name="i_am_color_1948">#00001948</color>
+    <color name="i_am_color_1949">#00001949</color>
+    <color name="i_am_color_194a">#0000194a</color>
+    <color name="i_am_color_194b">#0000194b</color>
+    <color name="i_am_color_194c">#0000194c</color>
+    <color name="i_am_color_194d">#0000194d</color>
+    <color name="i_am_color_194e">#0000194e</color>
+    <color name="i_am_color_194f">#0000194f</color>
+    <color name="i_am_color_1950">#00001950</color>
+    <color name="i_am_color_1951">#00001951</color>
+    <color name="i_am_color_1952">#00001952</color>
+    <color name="i_am_color_1953">#00001953</color>
+    <color name="i_am_color_1954">#00001954</color>
+    <color name="i_am_color_1955">#00001955</color>
+    <color name="i_am_color_1956">#00001956</color>
+    <color name="i_am_color_1957">#00001957</color>
+    <color name="i_am_color_1958">#00001958</color>
+    <color name="i_am_color_1959">#00001959</color>
+    <color name="i_am_color_195a">#0000195a</color>
+    <color name="i_am_color_195b">#0000195b</color>
+    <color name="i_am_color_195c">#0000195c</color>
+    <color name="i_am_color_195d">#0000195d</color>
+    <color name="i_am_color_195e">#0000195e</color>
+    <color name="i_am_color_195f">#0000195f</color>
+    <color name="i_am_color_1960">#00001960</color>
+    <color name="i_am_color_1961">#00001961</color>
+    <color name="i_am_color_1962">#00001962</color>
+    <color name="i_am_color_1963">#00001963</color>
+    <color name="i_am_color_1964">#00001964</color>
+    <color name="i_am_color_1965">#00001965</color>
+    <color name="i_am_color_1966">#00001966</color>
+    <color name="i_am_color_1967">#00001967</color>
+    <color name="i_am_color_1968">#00001968</color>
+    <color name="i_am_color_1969">#00001969</color>
+    <color name="i_am_color_196a">#0000196a</color>
+    <color name="i_am_color_196b">#0000196b</color>
+    <color name="i_am_color_196c">#0000196c</color>
+    <color name="i_am_color_196d">#0000196d</color>
+    <color name="i_am_color_196e">#0000196e</color>
+    <color name="i_am_color_196f">#0000196f</color>
+    <color name="i_am_color_1970">#00001970</color>
+    <color name="i_am_color_1971">#00001971</color>
+    <color name="i_am_color_1972">#00001972</color>
+    <color name="i_am_color_1973">#00001973</color>
+    <color name="i_am_color_1974">#00001974</color>
+    <color name="i_am_color_1975">#00001975</color>
+    <color name="i_am_color_1976">#00001976</color>
+    <color name="i_am_color_1977">#00001977</color>
+    <color name="i_am_color_1978">#00001978</color>
+    <color name="i_am_color_1979">#00001979</color>
+    <color name="i_am_color_197a">#0000197a</color>
+    <color name="i_am_color_197b">#0000197b</color>
+    <color name="i_am_color_197c">#0000197c</color>
+    <color name="i_am_color_197d">#0000197d</color>
+    <color name="i_am_color_197e">#0000197e</color>
+    <color name="i_am_color_197f">#0000197f</color>
+    <color name="i_am_color_1980">#00001980</color>
+    <color name="i_am_color_1981">#00001981</color>
+    <color name="i_am_color_1982">#00001982</color>
+    <color name="i_am_color_1983">#00001983</color>
+    <color name="i_am_color_1984">#00001984</color>
+    <color name="i_am_color_1985">#00001985</color>
+    <color name="i_am_color_1986">#00001986</color>
+    <color name="i_am_color_1987">#00001987</color>
+    <color name="i_am_color_1988">#00001988</color>
+    <color name="i_am_color_1989">#00001989</color>
+    <color name="i_am_color_198a">#0000198a</color>
+    <color name="i_am_color_198b">#0000198b</color>
+    <color name="i_am_color_198c">#0000198c</color>
+    <color name="i_am_color_198d">#0000198d</color>
+    <color name="i_am_color_198e">#0000198e</color>
+    <color name="i_am_color_198f">#0000198f</color>
+    <color name="i_am_color_1990">#00001990</color>
+    <color name="i_am_color_1991">#00001991</color>
+    <color name="i_am_color_1992">#00001992</color>
+    <color name="i_am_color_1993">#00001993</color>
+    <color name="i_am_color_1994">#00001994</color>
+    <color name="i_am_color_1995">#00001995</color>
+    <color name="i_am_color_1996">#00001996</color>
+    <color name="i_am_color_1997">#00001997</color>
+    <color name="i_am_color_1998">#00001998</color>
+    <color name="i_am_color_1999">#00001999</color>
+    <color name="i_am_color_199a">#0000199a</color>
+    <color name="i_am_color_199b">#0000199b</color>
+    <color name="i_am_color_199c">#0000199c</color>
+    <color name="i_am_color_199d">#0000199d</color>
+    <color name="i_am_color_199e">#0000199e</color>
+    <color name="i_am_color_199f">#0000199f</color>
+    <color name="i_am_color_19a0">#000019a0</color>
+    <color name="i_am_color_19a1">#000019a1</color>
+    <color name="i_am_color_19a2">#000019a2</color>
+    <color name="i_am_color_19a3">#000019a3</color>
+    <color name="i_am_color_19a4">#000019a4</color>
+    <color name="i_am_color_19a5">#000019a5</color>
+    <color name="i_am_color_19a6">#000019a6</color>
+    <color name="i_am_color_19a7">#000019a7</color>
+    <color name="i_am_color_19a8">#000019a8</color>
+    <color name="i_am_color_19a9">#000019a9</color>
+    <color name="i_am_color_19aa">#000019aa</color>
+    <color name="i_am_color_19ab">#000019ab</color>
+    <color name="i_am_color_19ac">#000019ac</color>
+    <color name="i_am_color_19ad">#000019ad</color>
+    <color name="i_am_color_19ae">#000019ae</color>
+    <color name="i_am_color_19af">#000019af</color>
+    <color name="i_am_color_19b0">#000019b0</color>
+    <color name="i_am_color_19b1">#000019b1</color>
+    <color name="i_am_color_19b2">#000019b2</color>
+    <color name="i_am_color_19b3">#000019b3</color>
+    <color name="i_am_color_19b4">#000019b4</color>
+    <color name="i_am_color_19b5">#000019b5</color>
+    <color name="i_am_color_19b6">#000019b6</color>
+    <color name="i_am_color_19b7">#000019b7</color>
+    <color name="i_am_color_19b8">#000019b8</color>
+    <color name="i_am_color_19b9">#000019b9</color>
+    <color name="i_am_color_19ba">#000019ba</color>
+    <color name="i_am_color_19bb">#000019bb</color>
+    <color name="i_am_color_19bc">#000019bc</color>
+    <color name="i_am_color_19bd">#000019bd</color>
+    <color name="i_am_color_19be">#000019be</color>
+    <color name="i_am_color_19bf">#000019bf</color>
+    <color name="i_am_color_19c0">#000019c0</color>
+    <color name="i_am_color_19c1">#000019c1</color>
+    <color name="i_am_color_19c2">#000019c2</color>
+    <color name="i_am_color_19c3">#000019c3</color>
+    <color name="i_am_color_19c4">#000019c4</color>
+    <color name="i_am_color_19c5">#000019c5</color>
+    <color name="i_am_color_19c6">#000019c6</color>
+    <color name="i_am_color_19c7">#000019c7</color>
+    <color name="i_am_color_19c8">#000019c8</color>
+    <color name="i_am_color_19c9">#000019c9</color>
+    <color name="i_am_color_19ca">#000019ca</color>
+    <color name="i_am_color_19cb">#000019cb</color>
+    <color name="i_am_color_19cc">#000019cc</color>
+    <color name="i_am_color_19cd">#000019cd</color>
+    <color name="i_am_color_19ce">#000019ce</color>
+    <color name="i_am_color_19cf">#000019cf</color>
+    <color name="i_am_color_19d0">#000019d0</color>
+    <color name="i_am_color_19d1">#000019d1</color>
+    <color name="i_am_color_19d2">#000019d2</color>
+    <color name="i_am_color_19d3">#000019d3</color>
+    <color name="i_am_color_19d4">#000019d4</color>
+    <color name="i_am_color_19d5">#000019d5</color>
+    <color name="i_am_color_19d6">#000019d6</color>
+    <color name="i_am_color_19d7">#000019d7</color>
+    <color name="i_am_color_19d8">#000019d8</color>
+    <color name="i_am_color_19d9">#000019d9</color>
+    <color name="i_am_color_19da">#000019da</color>
+    <color name="i_am_color_19db">#000019db</color>
+    <color name="i_am_color_19dc">#000019dc</color>
+    <color name="i_am_color_19dd">#000019dd</color>
+    <color name="i_am_color_19de">#000019de</color>
+    <color name="i_am_color_19df">#000019df</color>
+    <color name="i_am_color_19e0">#000019e0</color>
+    <color name="i_am_color_19e1">#000019e1</color>
+    <color name="i_am_color_19e2">#000019e2</color>
+    <color name="i_am_color_19e3">#000019e3</color>
+    <color name="i_am_color_19e4">#000019e4</color>
+    <color name="i_am_color_19e5">#000019e5</color>
+    <color name="i_am_color_19e6">#000019e6</color>
+    <color name="i_am_color_19e7">#000019e7</color>
+    <color name="i_am_color_19e8">#000019e8</color>
+    <color name="i_am_color_19e9">#000019e9</color>
+    <color name="i_am_color_19ea">#000019ea</color>
+    <color name="i_am_color_19eb">#000019eb</color>
+    <color name="i_am_color_19ec">#000019ec</color>
+    <color name="i_am_color_19ed">#000019ed</color>
+    <color name="i_am_color_19ee">#000019ee</color>
+    <color name="i_am_color_19ef">#000019ef</color>
+    <color name="i_am_color_19f0">#000019f0</color>
+    <color name="i_am_color_19f1">#000019f1</color>
+    <color name="i_am_color_19f2">#000019f2</color>
+    <color name="i_am_color_19f3">#000019f3</color>
+    <color name="i_am_color_19f4">#000019f4</color>
+    <color name="i_am_color_19f5">#000019f5</color>
+    <color name="i_am_color_19f6">#000019f6</color>
+    <color name="i_am_color_19f7">#000019f7</color>
+    <color name="i_am_color_19f8">#000019f8</color>
+    <color name="i_am_color_19f9">#000019f9</color>
+    <color name="i_am_color_19fa">#000019fa</color>
+    <color name="i_am_color_19fb">#000019fb</color>
+    <color name="i_am_color_19fc">#000019fc</color>
+    <color name="i_am_color_19fd">#000019fd</color>
+    <color name="i_am_color_19fe">#000019fe</color>
+    <color name="i_am_color_19ff">#000019ff</color>
+    <color name="i_am_color_1a00">#00001a00</color>
+    <color name="i_am_color_1a01">#00001a01</color>
+    <color name="i_am_color_1a02">#00001a02</color>
+    <color name="i_am_color_1a03">#00001a03</color>
+    <color name="i_am_color_1a04">#00001a04</color>
+    <color name="i_am_color_1a05">#00001a05</color>
+    <color name="i_am_color_1a06">#00001a06</color>
+    <color name="i_am_color_1a07">#00001a07</color>
+    <color name="i_am_color_1a08">#00001a08</color>
+    <color name="i_am_color_1a09">#00001a09</color>
+    <color name="i_am_color_1a0a">#00001a0a</color>
+    <color name="i_am_color_1a0b">#00001a0b</color>
+    <color name="i_am_color_1a0c">#00001a0c</color>
+    <color name="i_am_color_1a0d">#00001a0d</color>
+    <color name="i_am_color_1a0e">#00001a0e</color>
+    <color name="i_am_color_1a0f">#00001a0f</color>
+    <color name="i_am_color_1a10">#00001a10</color>
+    <color name="i_am_color_1a11">#00001a11</color>
+    <color name="i_am_color_1a12">#00001a12</color>
+    <color name="i_am_color_1a13">#00001a13</color>
+    <color name="i_am_color_1a14">#00001a14</color>
+    <color name="i_am_color_1a15">#00001a15</color>
+    <color name="i_am_color_1a16">#00001a16</color>
+    <color name="i_am_color_1a17">#00001a17</color>
+    <color name="i_am_color_1a18">#00001a18</color>
+    <color name="i_am_color_1a19">#00001a19</color>
+    <color name="i_am_color_1a1a">#00001a1a</color>
+    <color name="i_am_color_1a1b">#00001a1b</color>
+    <color name="i_am_color_1a1c">#00001a1c</color>
+    <color name="i_am_color_1a1d">#00001a1d</color>
+    <color name="i_am_color_1a1e">#00001a1e</color>
+    <color name="i_am_color_1a1f">#00001a1f</color>
+    <color name="i_am_color_1a20">#00001a20</color>
+    <color name="i_am_color_1a21">#00001a21</color>
+    <color name="i_am_color_1a22">#00001a22</color>
+    <color name="i_am_color_1a23">#00001a23</color>
+    <color name="i_am_color_1a24">#00001a24</color>
+    <color name="i_am_color_1a25">#00001a25</color>
+    <color name="i_am_color_1a26">#00001a26</color>
+    <color name="i_am_color_1a27">#00001a27</color>
+    <color name="i_am_color_1a28">#00001a28</color>
+    <color name="i_am_color_1a29">#00001a29</color>
+    <color name="i_am_color_1a2a">#00001a2a</color>
+    <color name="i_am_color_1a2b">#00001a2b</color>
+    <color name="i_am_color_1a2c">#00001a2c</color>
+    <color name="i_am_color_1a2d">#00001a2d</color>
+    <color name="i_am_color_1a2e">#00001a2e</color>
+    <color name="i_am_color_1a2f">#00001a2f</color>
+    <color name="i_am_color_1a30">#00001a30</color>
+    <color name="i_am_color_1a31">#00001a31</color>
+    <color name="i_am_color_1a32">#00001a32</color>
+    <color name="i_am_color_1a33">#00001a33</color>
+    <color name="i_am_color_1a34">#00001a34</color>
+    <color name="i_am_color_1a35">#00001a35</color>
+    <color name="i_am_color_1a36">#00001a36</color>
+    <color name="i_am_color_1a37">#00001a37</color>
+    <color name="i_am_color_1a38">#00001a38</color>
+    <color name="i_am_color_1a39">#00001a39</color>
+    <color name="i_am_color_1a3a">#00001a3a</color>
+    <color name="i_am_color_1a3b">#00001a3b</color>
+    <color name="i_am_color_1a3c">#00001a3c</color>
+    <color name="i_am_color_1a3d">#00001a3d</color>
+    <color name="i_am_color_1a3e">#00001a3e</color>
+    <color name="i_am_color_1a3f">#00001a3f</color>
+    <color name="i_am_color_1a40">#00001a40</color>
+    <color name="i_am_color_1a41">#00001a41</color>
+    <color name="i_am_color_1a42">#00001a42</color>
+    <color name="i_am_color_1a43">#00001a43</color>
+    <color name="i_am_color_1a44">#00001a44</color>
+    <color name="i_am_color_1a45">#00001a45</color>
+    <color name="i_am_color_1a46">#00001a46</color>
+    <color name="i_am_color_1a47">#00001a47</color>
+    <color name="i_am_color_1a48">#00001a48</color>
+    <color name="i_am_color_1a49">#00001a49</color>
+    <color name="i_am_color_1a4a">#00001a4a</color>
+    <color name="i_am_color_1a4b">#00001a4b</color>
+    <color name="i_am_color_1a4c">#00001a4c</color>
+    <color name="i_am_color_1a4d">#00001a4d</color>
+    <color name="i_am_color_1a4e">#00001a4e</color>
+    <color name="i_am_color_1a4f">#00001a4f</color>
+    <color name="i_am_color_1a50">#00001a50</color>
+    <color name="i_am_color_1a51">#00001a51</color>
+    <color name="i_am_color_1a52">#00001a52</color>
+    <color name="i_am_color_1a53">#00001a53</color>
+    <color name="i_am_color_1a54">#00001a54</color>
+    <color name="i_am_color_1a55">#00001a55</color>
+    <color name="i_am_color_1a56">#00001a56</color>
+    <color name="i_am_color_1a57">#00001a57</color>
+    <color name="i_am_color_1a58">#00001a58</color>
+    <color name="i_am_color_1a59">#00001a59</color>
+    <color name="i_am_color_1a5a">#00001a5a</color>
+    <color name="i_am_color_1a5b">#00001a5b</color>
+    <color name="i_am_color_1a5c">#00001a5c</color>
+    <color name="i_am_color_1a5d">#00001a5d</color>
+    <color name="i_am_color_1a5e">#00001a5e</color>
+    <color name="i_am_color_1a5f">#00001a5f</color>
+    <color name="i_am_color_1a60">#00001a60</color>
+    <color name="i_am_color_1a61">#00001a61</color>
+    <color name="i_am_color_1a62">#00001a62</color>
+    <color name="i_am_color_1a63">#00001a63</color>
+    <color name="i_am_color_1a64">#00001a64</color>
+    <color name="i_am_color_1a65">#00001a65</color>
+    <color name="i_am_color_1a66">#00001a66</color>
+    <color name="i_am_color_1a67">#00001a67</color>
+    <color name="i_am_color_1a68">#00001a68</color>
+    <color name="i_am_color_1a69">#00001a69</color>
+    <color name="i_am_color_1a6a">#00001a6a</color>
+    <color name="i_am_color_1a6b">#00001a6b</color>
+    <color name="i_am_color_1a6c">#00001a6c</color>
+    <color name="i_am_color_1a6d">#00001a6d</color>
+    <color name="i_am_color_1a6e">#00001a6e</color>
+    <color name="i_am_color_1a6f">#00001a6f</color>
+    <color name="i_am_color_1a70">#00001a70</color>
+    <color name="i_am_color_1a71">#00001a71</color>
+    <color name="i_am_color_1a72">#00001a72</color>
+    <color name="i_am_color_1a73">#00001a73</color>
+    <color name="i_am_color_1a74">#00001a74</color>
+    <color name="i_am_color_1a75">#00001a75</color>
+    <color name="i_am_color_1a76">#00001a76</color>
+    <color name="i_am_color_1a77">#00001a77</color>
+    <color name="i_am_color_1a78">#00001a78</color>
+    <color name="i_am_color_1a79">#00001a79</color>
+    <color name="i_am_color_1a7a">#00001a7a</color>
+    <color name="i_am_color_1a7b">#00001a7b</color>
+    <color name="i_am_color_1a7c">#00001a7c</color>
+    <color name="i_am_color_1a7d">#00001a7d</color>
+    <color name="i_am_color_1a7e">#00001a7e</color>
+    <color name="i_am_color_1a7f">#00001a7f</color>
+    <color name="i_am_color_1a80">#00001a80</color>
+    <color name="i_am_color_1a81">#00001a81</color>
+    <color name="i_am_color_1a82">#00001a82</color>
+    <color name="i_am_color_1a83">#00001a83</color>
+    <color name="i_am_color_1a84">#00001a84</color>
+    <color name="i_am_color_1a85">#00001a85</color>
+    <color name="i_am_color_1a86">#00001a86</color>
+    <color name="i_am_color_1a87">#00001a87</color>
+    <color name="i_am_color_1a88">#00001a88</color>
+    <color name="i_am_color_1a89">#00001a89</color>
+    <color name="i_am_color_1a8a">#00001a8a</color>
+    <color name="i_am_color_1a8b">#00001a8b</color>
+    <color name="i_am_color_1a8c">#00001a8c</color>
+    <color name="i_am_color_1a8d">#00001a8d</color>
+    <color name="i_am_color_1a8e">#00001a8e</color>
+    <color name="i_am_color_1a8f">#00001a8f</color>
+    <color name="i_am_color_1a90">#00001a90</color>
+    <color name="i_am_color_1a91">#00001a91</color>
+    <color name="i_am_color_1a92">#00001a92</color>
+    <color name="i_am_color_1a93">#00001a93</color>
+    <color name="i_am_color_1a94">#00001a94</color>
+    <color name="i_am_color_1a95">#00001a95</color>
+    <color name="i_am_color_1a96">#00001a96</color>
+    <color name="i_am_color_1a97">#00001a97</color>
+    <color name="i_am_color_1a98">#00001a98</color>
+    <color name="i_am_color_1a99">#00001a99</color>
+    <color name="i_am_color_1a9a">#00001a9a</color>
+    <color name="i_am_color_1a9b">#00001a9b</color>
+    <color name="i_am_color_1a9c">#00001a9c</color>
+    <color name="i_am_color_1a9d">#00001a9d</color>
+    <color name="i_am_color_1a9e">#00001a9e</color>
+    <color name="i_am_color_1a9f">#00001a9f</color>
+    <color name="i_am_color_1aa0">#00001aa0</color>
+    <color name="i_am_color_1aa1">#00001aa1</color>
+    <color name="i_am_color_1aa2">#00001aa2</color>
+    <color name="i_am_color_1aa3">#00001aa3</color>
+    <color name="i_am_color_1aa4">#00001aa4</color>
+    <color name="i_am_color_1aa5">#00001aa5</color>
+    <color name="i_am_color_1aa6">#00001aa6</color>
+    <color name="i_am_color_1aa7">#00001aa7</color>
+    <color name="i_am_color_1aa8">#00001aa8</color>
+    <color name="i_am_color_1aa9">#00001aa9</color>
+    <color name="i_am_color_1aaa">#00001aaa</color>
+    <color name="i_am_color_1aab">#00001aab</color>
+    <color name="i_am_color_1aac">#00001aac</color>
+    <color name="i_am_color_1aad">#00001aad</color>
+    <color name="i_am_color_1aae">#00001aae</color>
+    <color name="i_am_color_1aaf">#00001aaf</color>
+    <color name="i_am_color_1ab0">#00001ab0</color>
+    <color name="i_am_color_1ab1">#00001ab1</color>
+    <color name="i_am_color_1ab2">#00001ab2</color>
+    <color name="i_am_color_1ab3">#00001ab3</color>
+    <color name="i_am_color_1ab4">#00001ab4</color>
+    <color name="i_am_color_1ab5">#00001ab5</color>
+    <color name="i_am_color_1ab6">#00001ab6</color>
+    <color name="i_am_color_1ab7">#00001ab7</color>
+    <color name="i_am_color_1ab8">#00001ab8</color>
+    <color name="i_am_color_1ab9">#00001ab9</color>
+    <color name="i_am_color_1aba">#00001aba</color>
+    <color name="i_am_color_1abb">#00001abb</color>
+    <color name="i_am_color_1abc">#00001abc</color>
+    <color name="i_am_color_1abd">#00001abd</color>
+    <color name="i_am_color_1abe">#00001abe</color>
+    <color name="i_am_color_1abf">#00001abf</color>
+    <color name="i_am_color_1ac0">#00001ac0</color>
+    <color name="i_am_color_1ac1">#00001ac1</color>
+    <color name="i_am_color_1ac2">#00001ac2</color>
+    <color name="i_am_color_1ac3">#00001ac3</color>
+    <color name="i_am_color_1ac4">#00001ac4</color>
+    <color name="i_am_color_1ac5">#00001ac5</color>
+    <color name="i_am_color_1ac6">#00001ac6</color>
+    <color name="i_am_color_1ac7">#00001ac7</color>
+    <color name="i_am_color_1ac8">#00001ac8</color>
+    <color name="i_am_color_1ac9">#00001ac9</color>
+    <color name="i_am_color_1aca">#00001aca</color>
+    <color name="i_am_color_1acb">#00001acb</color>
+    <color name="i_am_color_1acc">#00001acc</color>
+    <color name="i_am_color_1acd">#00001acd</color>
+    <color name="i_am_color_1ace">#00001ace</color>
+    <color name="i_am_color_1acf">#00001acf</color>
+    <color name="i_am_color_1ad0">#00001ad0</color>
+    <color name="i_am_color_1ad1">#00001ad1</color>
+    <color name="i_am_color_1ad2">#00001ad2</color>
+    <color name="i_am_color_1ad3">#00001ad3</color>
+    <color name="i_am_color_1ad4">#00001ad4</color>
+    <color name="i_am_color_1ad5">#00001ad5</color>
+    <color name="i_am_color_1ad6">#00001ad6</color>
+    <color name="i_am_color_1ad7">#00001ad7</color>
+    <color name="i_am_color_1ad8">#00001ad8</color>
+    <color name="i_am_color_1ad9">#00001ad9</color>
+    <color name="i_am_color_1ada">#00001ada</color>
+    <color name="i_am_color_1adb">#00001adb</color>
+    <color name="i_am_color_1adc">#00001adc</color>
+    <color name="i_am_color_1add">#00001add</color>
+    <color name="i_am_color_1ade">#00001ade</color>
+    <color name="i_am_color_1adf">#00001adf</color>
+    <color name="i_am_color_1ae0">#00001ae0</color>
+    <color name="i_am_color_1ae1">#00001ae1</color>
+    <color name="i_am_color_1ae2">#00001ae2</color>
+    <color name="i_am_color_1ae3">#00001ae3</color>
+    <color name="i_am_color_1ae4">#00001ae4</color>
+    <color name="i_am_color_1ae5">#00001ae5</color>
+    <color name="i_am_color_1ae6">#00001ae6</color>
+    <color name="i_am_color_1ae7">#00001ae7</color>
+    <color name="i_am_color_1ae8">#00001ae8</color>
+    <color name="i_am_color_1ae9">#00001ae9</color>
+    <color name="i_am_color_1aea">#00001aea</color>
+    <color name="i_am_color_1aeb">#00001aeb</color>
+    <color name="i_am_color_1aec">#00001aec</color>
+    <color name="i_am_color_1aed">#00001aed</color>
+    <color name="i_am_color_1aee">#00001aee</color>
+    <color name="i_am_color_1aef">#00001aef</color>
+    <color name="i_am_color_1af0">#00001af0</color>
+    <color name="i_am_color_1af1">#00001af1</color>
+    <color name="i_am_color_1af2">#00001af2</color>
+    <color name="i_am_color_1af3">#00001af3</color>
+    <color name="i_am_color_1af4">#00001af4</color>
+    <color name="i_am_color_1af5">#00001af5</color>
+    <color name="i_am_color_1af6">#00001af6</color>
+    <color name="i_am_color_1af7">#00001af7</color>
+    <color name="i_am_color_1af8">#00001af8</color>
+    <color name="i_am_color_1af9">#00001af9</color>
+    <color name="i_am_color_1afa">#00001afa</color>
+    <color name="i_am_color_1afb">#00001afb</color>
+    <color name="i_am_color_1afc">#00001afc</color>
+    <color name="i_am_color_1afd">#00001afd</color>
+    <color name="i_am_color_1afe">#00001afe</color>
+    <color name="i_am_color_1aff">#00001aff</color>
+    <color name="i_am_color_1b00">#00001b00</color>
+    <color name="i_am_color_1b01">#00001b01</color>
+    <color name="i_am_color_1b02">#00001b02</color>
+    <color name="i_am_color_1b03">#00001b03</color>
+    <color name="i_am_color_1b04">#00001b04</color>
+    <color name="i_am_color_1b05">#00001b05</color>
+    <color name="i_am_color_1b06">#00001b06</color>
+    <color name="i_am_color_1b07">#00001b07</color>
+    <color name="i_am_color_1b08">#00001b08</color>
+    <color name="i_am_color_1b09">#00001b09</color>
+    <color name="i_am_color_1b0a">#00001b0a</color>
+    <color name="i_am_color_1b0b">#00001b0b</color>
+    <color name="i_am_color_1b0c">#00001b0c</color>
+    <color name="i_am_color_1b0d">#00001b0d</color>
+    <color name="i_am_color_1b0e">#00001b0e</color>
+    <color name="i_am_color_1b0f">#00001b0f</color>
+    <color name="i_am_color_1b10">#00001b10</color>
+    <color name="i_am_color_1b11">#00001b11</color>
+    <color name="i_am_color_1b12">#00001b12</color>
+    <color name="i_am_color_1b13">#00001b13</color>
+    <color name="i_am_color_1b14">#00001b14</color>
+    <color name="i_am_color_1b15">#00001b15</color>
+    <color name="i_am_color_1b16">#00001b16</color>
+    <color name="i_am_color_1b17">#00001b17</color>
+    <color name="i_am_color_1b18">#00001b18</color>
+    <color name="i_am_color_1b19">#00001b19</color>
+    <color name="i_am_color_1b1a">#00001b1a</color>
+    <color name="i_am_color_1b1b">#00001b1b</color>
+    <color name="i_am_color_1b1c">#00001b1c</color>
+    <color name="i_am_color_1b1d">#00001b1d</color>
+    <color name="i_am_color_1b1e">#00001b1e</color>
+    <color name="i_am_color_1b1f">#00001b1f</color>
+    <color name="i_am_color_1b20">#00001b20</color>
+    <color name="i_am_color_1b21">#00001b21</color>
+    <color name="i_am_color_1b22">#00001b22</color>
+    <color name="i_am_color_1b23">#00001b23</color>
+    <color name="i_am_color_1b24">#00001b24</color>
+    <color name="i_am_color_1b25">#00001b25</color>
+    <color name="i_am_color_1b26">#00001b26</color>
+    <color name="i_am_color_1b27">#00001b27</color>
+    <color name="i_am_color_1b28">#00001b28</color>
+    <color name="i_am_color_1b29">#00001b29</color>
+    <color name="i_am_color_1b2a">#00001b2a</color>
+    <color name="i_am_color_1b2b">#00001b2b</color>
+    <color name="i_am_color_1b2c">#00001b2c</color>
+    <color name="i_am_color_1b2d">#00001b2d</color>
+    <color name="i_am_color_1b2e">#00001b2e</color>
+    <color name="i_am_color_1b2f">#00001b2f</color>
+    <color name="i_am_color_1b30">#00001b30</color>
+    <color name="i_am_color_1b31">#00001b31</color>
+    <color name="i_am_color_1b32">#00001b32</color>
+    <color name="i_am_color_1b33">#00001b33</color>
+    <color name="i_am_color_1b34">#00001b34</color>
+    <color name="i_am_color_1b35">#00001b35</color>
+    <color name="i_am_color_1b36">#00001b36</color>
+    <color name="i_am_color_1b37">#00001b37</color>
+    <color name="i_am_color_1b38">#00001b38</color>
+    <color name="i_am_color_1b39">#00001b39</color>
+    <color name="i_am_color_1b3a">#00001b3a</color>
+    <color name="i_am_color_1b3b">#00001b3b</color>
+    <color name="i_am_color_1b3c">#00001b3c</color>
+    <color name="i_am_color_1b3d">#00001b3d</color>
+    <color name="i_am_color_1b3e">#00001b3e</color>
+    <color name="i_am_color_1b3f">#00001b3f</color>
+    <color name="i_am_color_1b40">#00001b40</color>
+    <color name="i_am_color_1b41">#00001b41</color>
+    <color name="i_am_color_1b42">#00001b42</color>
+    <color name="i_am_color_1b43">#00001b43</color>
+    <color name="i_am_color_1b44">#00001b44</color>
+    <color name="i_am_color_1b45">#00001b45</color>
+    <color name="i_am_color_1b46">#00001b46</color>
+    <color name="i_am_color_1b47">#00001b47</color>
+    <color name="i_am_color_1b48">#00001b48</color>
+    <color name="i_am_color_1b49">#00001b49</color>
+    <color name="i_am_color_1b4a">#00001b4a</color>
+    <color name="i_am_color_1b4b">#00001b4b</color>
+    <color name="i_am_color_1b4c">#00001b4c</color>
+    <color name="i_am_color_1b4d">#00001b4d</color>
+    <color name="i_am_color_1b4e">#00001b4e</color>
+    <color name="i_am_color_1b4f">#00001b4f</color>
+    <color name="i_am_color_1b50">#00001b50</color>
+    <color name="i_am_color_1b51">#00001b51</color>
+    <color name="i_am_color_1b52">#00001b52</color>
+    <color name="i_am_color_1b53">#00001b53</color>
+    <color name="i_am_color_1b54">#00001b54</color>
+    <color name="i_am_color_1b55">#00001b55</color>
+    <color name="i_am_color_1b56">#00001b56</color>
+    <color name="i_am_color_1b57">#00001b57</color>
+    <color name="i_am_color_1b58">#00001b58</color>
+    <color name="i_am_color_1b59">#00001b59</color>
+    <color name="i_am_color_1b5a">#00001b5a</color>
+    <color name="i_am_color_1b5b">#00001b5b</color>
+    <color name="i_am_color_1b5c">#00001b5c</color>
+    <color name="i_am_color_1b5d">#00001b5d</color>
+    <color name="i_am_color_1b5e">#00001b5e</color>
+    <color name="i_am_color_1b5f">#00001b5f</color>
+    <color name="i_am_color_1b60">#00001b60</color>
+    <color name="i_am_color_1b61">#00001b61</color>
+    <color name="i_am_color_1b62">#00001b62</color>
+    <color name="i_am_color_1b63">#00001b63</color>
+    <color name="i_am_color_1b64">#00001b64</color>
+    <color name="i_am_color_1b65">#00001b65</color>
+    <color name="i_am_color_1b66">#00001b66</color>
+    <color name="i_am_color_1b67">#00001b67</color>
+    <color name="i_am_color_1b68">#00001b68</color>
+    <color name="i_am_color_1b69">#00001b69</color>
+    <color name="i_am_color_1b6a">#00001b6a</color>
+    <color name="i_am_color_1b6b">#00001b6b</color>
+    <color name="i_am_color_1b6c">#00001b6c</color>
+    <color name="i_am_color_1b6d">#00001b6d</color>
+    <color name="i_am_color_1b6e">#00001b6e</color>
+    <color name="i_am_color_1b6f">#00001b6f</color>
+    <color name="i_am_color_1b70">#00001b70</color>
+    <color name="i_am_color_1b71">#00001b71</color>
+    <color name="i_am_color_1b72">#00001b72</color>
+    <color name="i_am_color_1b73">#00001b73</color>
+    <color name="i_am_color_1b74">#00001b74</color>
+    <color name="i_am_color_1b75">#00001b75</color>
+    <color name="i_am_color_1b76">#00001b76</color>
+    <color name="i_am_color_1b77">#00001b77</color>
+    <color name="i_am_color_1b78">#00001b78</color>
+    <color name="i_am_color_1b79">#00001b79</color>
+    <color name="i_am_color_1b7a">#00001b7a</color>
+    <color name="i_am_color_1b7b">#00001b7b</color>
+    <color name="i_am_color_1b7c">#00001b7c</color>
+    <color name="i_am_color_1b7d">#00001b7d</color>
+    <color name="i_am_color_1b7e">#00001b7e</color>
+    <color name="i_am_color_1b7f">#00001b7f</color>
+    <color name="i_am_color_1b80">#00001b80</color>
+    <color name="i_am_color_1b81">#00001b81</color>
+    <color name="i_am_color_1b82">#00001b82</color>
+    <color name="i_am_color_1b83">#00001b83</color>
+    <color name="i_am_color_1b84">#00001b84</color>
+    <color name="i_am_color_1b85">#00001b85</color>
+    <color name="i_am_color_1b86">#00001b86</color>
+    <color name="i_am_color_1b87">#00001b87</color>
+    <color name="i_am_color_1b88">#00001b88</color>
+    <color name="i_am_color_1b89">#00001b89</color>
+    <color name="i_am_color_1b8a">#00001b8a</color>
+    <color name="i_am_color_1b8b">#00001b8b</color>
+    <color name="i_am_color_1b8c">#00001b8c</color>
+    <color name="i_am_color_1b8d">#00001b8d</color>
+    <color name="i_am_color_1b8e">#00001b8e</color>
+    <color name="i_am_color_1b8f">#00001b8f</color>
+    <color name="i_am_color_1b90">#00001b90</color>
+    <color name="i_am_color_1b91">#00001b91</color>
+    <color name="i_am_color_1b92">#00001b92</color>
+    <color name="i_am_color_1b93">#00001b93</color>
+    <color name="i_am_color_1b94">#00001b94</color>
+    <color name="i_am_color_1b95">#00001b95</color>
+    <color name="i_am_color_1b96">#00001b96</color>
+    <color name="i_am_color_1b97">#00001b97</color>
+    <color name="i_am_color_1b98">#00001b98</color>
+    <color name="i_am_color_1b99">#00001b99</color>
+    <color name="i_am_color_1b9a">#00001b9a</color>
+    <color name="i_am_color_1b9b">#00001b9b</color>
+    <color name="i_am_color_1b9c">#00001b9c</color>
+    <color name="i_am_color_1b9d">#00001b9d</color>
+    <color name="i_am_color_1b9e">#00001b9e</color>
+    <color name="i_am_color_1b9f">#00001b9f</color>
+    <color name="i_am_color_1ba0">#00001ba0</color>
+    <color name="i_am_color_1ba1">#00001ba1</color>
+    <color name="i_am_color_1ba2">#00001ba2</color>
+    <color name="i_am_color_1ba3">#00001ba3</color>
+    <color name="i_am_color_1ba4">#00001ba4</color>
+    <color name="i_am_color_1ba5">#00001ba5</color>
+    <color name="i_am_color_1ba6">#00001ba6</color>
+    <color name="i_am_color_1ba7">#00001ba7</color>
+    <color name="i_am_color_1ba8">#00001ba8</color>
+    <color name="i_am_color_1ba9">#00001ba9</color>
+    <color name="i_am_color_1baa">#00001baa</color>
+    <color name="i_am_color_1bab">#00001bab</color>
+    <color name="i_am_color_1bac">#00001bac</color>
+    <color name="i_am_color_1bad">#00001bad</color>
+    <color name="i_am_color_1bae">#00001bae</color>
+    <color name="i_am_color_1baf">#00001baf</color>
+    <color name="i_am_color_1bb0">#00001bb0</color>
+    <color name="i_am_color_1bb1">#00001bb1</color>
+    <color name="i_am_color_1bb2">#00001bb2</color>
+    <color name="i_am_color_1bb3">#00001bb3</color>
+    <color name="i_am_color_1bb4">#00001bb4</color>
+    <color name="i_am_color_1bb5">#00001bb5</color>
+    <color name="i_am_color_1bb6">#00001bb6</color>
+    <color name="i_am_color_1bb7">#00001bb7</color>
+    <color name="i_am_color_1bb8">#00001bb8</color>
+    <color name="i_am_color_1bb9">#00001bb9</color>
+    <color name="i_am_color_1bba">#00001bba</color>
+    <color name="i_am_color_1bbb">#00001bbb</color>
+    <color name="i_am_color_1bbc">#00001bbc</color>
+    <color name="i_am_color_1bbd">#00001bbd</color>
+    <color name="i_am_color_1bbe">#00001bbe</color>
+    <color name="i_am_color_1bbf">#00001bbf</color>
+    <color name="i_am_color_1bc0">#00001bc0</color>
+    <color name="i_am_color_1bc1">#00001bc1</color>
+    <color name="i_am_color_1bc2">#00001bc2</color>
+    <color name="i_am_color_1bc3">#00001bc3</color>
+    <color name="i_am_color_1bc4">#00001bc4</color>
+    <color name="i_am_color_1bc5">#00001bc5</color>
+    <color name="i_am_color_1bc6">#00001bc6</color>
+    <color name="i_am_color_1bc7">#00001bc7</color>
+    <color name="i_am_color_1bc8">#00001bc8</color>
+    <color name="i_am_color_1bc9">#00001bc9</color>
+    <color name="i_am_color_1bca">#00001bca</color>
+    <color name="i_am_color_1bcb">#00001bcb</color>
+    <color name="i_am_color_1bcc">#00001bcc</color>
+    <color name="i_am_color_1bcd">#00001bcd</color>
+    <color name="i_am_color_1bce">#00001bce</color>
+    <color name="i_am_color_1bcf">#00001bcf</color>
+    <color name="i_am_color_1bd0">#00001bd0</color>
+    <color name="i_am_color_1bd1">#00001bd1</color>
+    <color name="i_am_color_1bd2">#00001bd2</color>
+    <color name="i_am_color_1bd3">#00001bd3</color>
+    <color name="i_am_color_1bd4">#00001bd4</color>
+    <color name="i_am_color_1bd5">#00001bd5</color>
+    <color name="i_am_color_1bd6">#00001bd6</color>
+    <color name="i_am_color_1bd7">#00001bd7</color>
+    <color name="i_am_color_1bd8">#00001bd8</color>
+    <color name="i_am_color_1bd9">#00001bd9</color>
+    <color name="i_am_color_1bda">#00001bda</color>
+    <color name="i_am_color_1bdb">#00001bdb</color>
+    <color name="i_am_color_1bdc">#00001bdc</color>
+    <color name="i_am_color_1bdd">#00001bdd</color>
+    <color name="i_am_color_1bde">#00001bde</color>
+    <color name="i_am_color_1bdf">#00001bdf</color>
+    <color name="i_am_color_1be0">#00001be0</color>
+    <color name="i_am_color_1be1">#00001be1</color>
+    <color name="i_am_color_1be2">#00001be2</color>
+    <color name="i_am_color_1be3">#00001be3</color>
+    <color name="i_am_color_1be4">#00001be4</color>
+    <color name="i_am_color_1be5">#00001be5</color>
+    <color name="i_am_color_1be6">#00001be6</color>
+    <color name="i_am_color_1be7">#00001be7</color>
+    <color name="i_am_color_1be8">#00001be8</color>
+    <color name="i_am_color_1be9">#00001be9</color>
+    <color name="i_am_color_1bea">#00001bea</color>
+    <color name="i_am_color_1beb">#00001beb</color>
+    <color name="i_am_color_1bec">#00001bec</color>
+    <color name="i_am_color_1bed">#00001bed</color>
+    <color name="i_am_color_1bee">#00001bee</color>
+    <color name="i_am_color_1bef">#00001bef</color>
+    <color name="i_am_color_1bf0">#00001bf0</color>
+    <color name="i_am_color_1bf1">#00001bf1</color>
+    <color name="i_am_color_1bf2">#00001bf2</color>
+    <color name="i_am_color_1bf3">#00001bf3</color>
+    <color name="i_am_color_1bf4">#00001bf4</color>
+    <color name="i_am_color_1bf5">#00001bf5</color>
+    <color name="i_am_color_1bf6">#00001bf6</color>
+    <color name="i_am_color_1bf7">#00001bf7</color>
+    <color name="i_am_color_1bf8">#00001bf8</color>
+    <color name="i_am_color_1bf9">#00001bf9</color>
+    <color name="i_am_color_1bfa">#00001bfa</color>
+    <color name="i_am_color_1bfb">#00001bfb</color>
+    <color name="i_am_color_1bfc">#00001bfc</color>
+    <color name="i_am_color_1bfd">#00001bfd</color>
+    <color name="i_am_color_1bfe">#00001bfe</color>
+    <color name="i_am_color_1bff">#00001bff</color>
+    <color name="i_am_color_1c00">#00001c00</color>
+    <color name="i_am_color_1c01">#00001c01</color>
+    <color name="i_am_color_1c02">#00001c02</color>
+    <color name="i_am_color_1c03">#00001c03</color>
+    <color name="i_am_color_1c04">#00001c04</color>
+    <color name="i_am_color_1c05">#00001c05</color>
+    <color name="i_am_color_1c06">#00001c06</color>
+    <color name="i_am_color_1c07">#00001c07</color>
+    <color name="i_am_color_1c08">#00001c08</color>
+    <color name="i_am_color_1c09">#00001c09</color>
+    <color name="i_am_color_1c0a">#00001c0a</color>
+    <color name="i_am_color_1c0b">#00001c0b</color>
+    <color name="i_am_color_1c0c">#00001c0c</color>
+    <color name="i_am_color_1c0d">#00001c0d</color>
+    <color name="i_am_color_1c0e">#00001c0e</color>
+    <color name="i_am_color_1c0f">#00001c0f</color>
+    <color name="i_am_color_1c10">#00001c10</color>
+    <color name="i_am_color_1c11">#00001c11</color>
+    <color name="i_am_color_1c12">#00001c12</color>
+    <color name="i_am_color_1c13">#00001c13</color>
+    <color name="i_am_color_1c14">#00001c14</color>
+    <color name="i_am_color_1c15">#00001c15</color>
+    <color name="i_am_color_1c16">#00001c16</color>
+    <color name="i_am_color_1c17">#00001c17</color>
+    <color name="i_am_color_1c18">#00001c18</color>
+    <color name="i_am_color_1c19">#00001c19</color>
+    <color name="i_am_color_1c1a">#00001c1a</color>
+    <color name="i_am_color_1c1b">#00001c1b</color>
+    <color name="i_am_color_1c1c">#00001c1c</color>
+    <color name="i_am_color_1c1d">#00001c1d</color>
+    <color name="i_am_color_1c1e">#00001c1e</color>
+    <color name="i_am_color_1c1f">#00001c1f</color>
+    <color name="i_am_color_1c20">#00001c20</color>
+    <color name="i_am_color_1c21">#00001c21</color>
+    <color name="i_am_color_1c22">#00001c22</color>
+    <color name="i_am_color_1c23">#00001c23</color>
+    <color name="i_am_color_1c24">#00001c24</color>
+    <color name="i_am_color_1c25">#00001c25</color>
+    <color name="i_am_color_1c26">#00001c26</color>
+    <color name="i_am_color_1c27">#00001c27</color>
+    <color name="i_am_color_1c28">#00001c28</color>
+    <color name="i_am_color_1c29">#00001c29</color>
+    <color name="i_am_color_1c2a">#00001c2a</color>
+    <color name="i_am_color_1c2b">#00001c2b</color>
+    <color name="i_am_color_1c2c">#00001c2c</color>
+    <color name="i_am_color_1c2d">#00001c2d</color>
+    <color name="i_am_color_1c2e">#00001c2e</color>
+    <color name="i_am_color_1c2f">#00001c2f</color>
+    <color name="i_am_color_1c30">#00001c30</color>
+    <color name="i_am_color_1c31">#00001c31</color>
+    <color name="i_am_color_1c32">#00001c32</color>
+    <color name="i_am_color_1c33">#00001c33</color>
+    <color name="i_am_color_1c34">#00001c34</color>
+    <color name="i_am_color_1c35">#00001c35</color>
+    <color name="i_am_color_1c36">#00001c36</color>
+    <color name="i_am_color_1c37">#00001c37</color>
+    <color name="i_am_color_1c38">#00001c38</color>
+    <color name="i_am_color_1c39">#00001c39</color>
+    <color name="i_am_color_1c3a">#00001c3a</color>
+    <color name="i_am_color_1c3b">#00001c3b</color>
+    <color name="i_am_color_1c3c">#00001c3c</color>
+    <color name="i_am_color_1c3d">#00001c3d</color>
+    <color name="i_am_color_1c3e">#00001c3e</color>
+    <color name="i_am_color_1c3f">#00001c3f</color>
+    <color name="i_am_color_1c40">#00001c40</color>
+    <color name="i_am_color_1c41">#00001c41</color>
+    <color name="i_am_color_1c42">#00001c42</color>
+    <color name="i_am_color_1c43">#00001c43</color>
+    <color name="i_am_color_1c44">#00001c44</color>
+    <color name="i_am_color_1c45">#00001c45</color>
+    <color name="i_am_color_1c46">#00001c46</color>
+    <color name="i_am_color_1c47">#00001c47</color>
+    <color name="i_am_color_1c48">#00001c48</color>
+    <color name="i_am_color_1c49">#00001c49</color>
+    <color name="i_am_color_1c4a">#00001c4a</color>
+    <color name="i_am_color_1c4b">#00001c4b</color>
+    <color name="i_am_color_1c4c">#00001c4c</color>
+    <color name="i_am_color_1c4d">#00001c4d</color>
+    <color name="i_am_color_1c4e">#00001c4e</color>
+    <color name="i_am_color_1c4f">#00001c4f</color>
+    <color name="i_am_color_1c50">#00001c50</color>
+    <color name="i_am_color_1c51">#00001c51</color>
+    <color name="i_am_color_1c52">#00001c52</color>
+    <color name="i_am_color_1c53">#00001c53</color>
+    <color name="i_am_color_1c54">#00001c54</color>
+    <color name="i_am_color_1c55">#00001c55</color>
+    <color name="i_am_color_1c56">#00001c56</color>
+    <color name="i_am_color_1c57">#00001c57</color>
+    <color name="i_am_color_1c58">#00001c58</color>
+    <color name="i_am_color_1c59">#00001c59</color>
+    <color name="i_am_color_1c5a">#00001c5a</color>
+    <color name="i_am_color_1c5b">#00001c5b</color>
+    <color name="i_am_color_1c5c">#00001c5c</color>
+    <color name="i_am_color_1c5d">#00001c5d</color>
+    <color name="i_am_color_1c5e">#00001c5e</color>
+    <color name="i_am_color_1c5f">#00001c5f</color>
+    <color name="i_am_color_1c60">#00001c60</color>
+    <color name="i_am_color_1c61">#00001c61</color>
+    <color name="i_am_color_1c62">#00001c62</color>
+    <color name="i_am_color_1c63">#00001c63</color>
+    <color name="i_am_color_1c64">#00001c64</color>
+    <color name="i_am_color_1c65">#00001c65</color>
+    <color name="i_am_color_1c66">#00001c66</color>
+    <color name="i_am_color_1c67">#00001c67</color>
+    <color name="i_am_color_1c68">#00001c68</color>
+    <color name="i_am_color_1c69">#00001c69</color>
+    <color name="i_am_color_1c6a">#00001c6a</color>
+    <color name="i_am_color_1c6b">#00001c6b</color>
+    <color name="i_am_color_1c6c">#00001c6c</color>
+    <color name="i_am_color_1c6d">#00001c6d</color>
+    <color name="i_am_color_1c6e">#00001c6e</color>
+    <color name="i_am_color_1c6f">#00001c6f</color>
+    <color name="i_am_color_1c70">#00001c70</color>
+    <color name="i_am_color_1c71">#00001c71</color>
+    <color name="i_am_color_1c72">#00001c72</color>
+    <color name="i_am_color_1c73">#00001c73</color>
+    <color name="i_am_color_1c74">#00001c74</color>
+    <color name="i_am_color_1c75">#00001c75</color>
+    <color name="i_am_color_1c76">#00001c76</color>
+    <color name="i_am_color_1c77">#00001c77</color>
+    <color name="i_am_color_1c78">#00001c78</color>
+    <color name="i_am_color_1c79">#00001c79</color>
+    <color name="i_am_color_1c7a">#00001c7a</color>
+    <color name="i_am_color_1c7b">#00001c7b</color>
+    <color name="i_am_color_1c7c">#00001c7c</color>
+    <color name="i_am_color_1c7d">#00001c7d</color>
+    <color name="i_am_color_1c7e">#00001c7e</color>
+    <color name="i_am_color_1c7f">#00001c7f</color>
+    <color name="i_am_color_1c80">#00001c80</color>
+    <color name="i_am_color_1c81">#00001c81</color>
+    <color name="i_am_color_1c82">#00001c82</color>
+    <color name="i_am_color_1c83">#00001c83</color>
+    <color name="i_am_color_1c84">#00001c84</color>
+    <color name="i_am_color_1c85">#00001c85</color>
+    <color name="i_am_color_1c86">#00001c86</color>
+    <color name="i_am_color_1c87">#00001c87</color>
+    <color name="i_am_color_1c88">#00001c88</color>
+    <color name="i_am_color_1c89">#00001c89</color>
+    <color name="i_am_color_1c8a">#00001c8a</color>
+    <color name="i_am_color_1c8b">#00001c8b</color>
+    <color name="i_am_color_1c8c">#00001c8c</color>
+    <color name="i_am_color_1c8d">#00001c8d</color>
+    <color name="i_am_color_1c8e">#00001c8e</color>
+    <color name="i_am_color_1c8f">#00001c8f</color>
+    <color name="i_am_color_1c90">#00001c90</color>
+    <color name="i_am_color_1c91">#00001c91</color>
+    <color name="i_am_color_1c92">#00001c92</color>
+    <color name="i_am_color_1c93">#00001c93</color>
+    <color name="i_am_color_1c94">#00001c94</color>
+    <color name="i_am_color_1c95">#00001c95</color>
+    <color name="i_am_color_1c96">#00001c96</color>
+    <color name="i_am_color_1c97">#00001c97</color>
+    <color name="i_am_color_1c98">#00001c98</color>
+    <color name="i_am_color_1c99">#00001c99</color>
+    <color name="i_am_color_1c9a">#00001c9a</color>
+    <color name="i_am_color_1c9b">#00001c9b</color>
+    <color name="i_am_color_1c9c">#00001c9c</color>
+    <color name="i_am_color_1c9d">#00001c9d</color>
+    <color name="i_am_color_1c9e">#00001c9e</color>
+    <color name="i_am_color_1c9f">#00001c9f</color>
+    <color name="i_am_color_1ca0">#00001ca0</color>
+    <color name="i_am_color_1ca1">#00001ca1</color>
+    <color name="i_am_color_1ca2">#00001ca2</color>
+    <color name="i_am_color_1ca3">#00001ca3</color>
+    <color name="i_am_color_1ca4">#00001ca4</color>
+    <color name="i_am_color_1ca5">#00001ca5</color>
+    <color name="i_am_color_1ca6">#00001ca6</color>
+    <color name="i_am_color_1ca7">#00001ca7</color>
+    <color name="i_am_color_1ca8">#00001ca8</color>
+    <color name="i_am_color_1ca9">#00001ca9</color>
+    <color name="i_am_color_1caa">#00001caa</color>
+    <color name="i_am_color_1cab">#00001cab</color>
+    <color name="i_am_color_1cac">#00001cac</color>
+    <color name="i_am_color_1cad">#00001cad</color>
+    <color name="i_am_color_1cae">#00001cae</color>
+    <color name="i_am_color_1caf">#00001caf</color>
+    <color name="i_am_color_1cb0">#00001cb0</color>
+    <color name="i_am_color_1cb1">#00001cb1</color>
+    <color name="i_am_color_1cb2">#00001cb2</color>
+    <color name="i_am_color_1cb3">#00001cb3</color>
+    <color name="i_am_color_1cb4">#00001cb4</color>
+    <color name="i_am_color_1cb5">#00001cb5</color>
+    <color name="i_am_color_1cb6">#00001cb6</color>
+    <color name="i_am_color_1cb7">#00001cb7</color>
+    <color name="i_am_color_1cb8">#00001cb8</color>
+    <color name="i_am_color_1cb9">#00001cb9</color>
+    <color name="i_am_color_1cba">#00001cba</color>
+    <color name="i_am_color_1cbb">#00001cbb</color>
+    <color name="i_am_color_1cbc">#00001cbc</color>
+    <color name="i_am_color_1cbd">#00001cbd</color>
+    <color name="i_am_color_1cbe">#00001cbe</color>
+    <color name="i_am_color_1cbf">#00001cbf</color>
+    <color name="i_am_color_1cc0">#00001cc0</color>
+    <color name="i_am_color_1cc1">#00001cc1</color>
+    <color name="i_am_color_1cc2">#00001cc2</color>
+    <color name="i_am_color_1cc3">#00001cc3</color>
+    <color name="i_am_color_1cc4">#00001cc4</color>
+    <color name="i_am_color_1cc5">#00001cc5</color>
+    <color name="i_am_color_1cc6">#00001cc6</color>
+    <color name="i_am_color_1cc7">#00001cc7</color>
+    <color name="i_am_color_1cc8">#00001cc8</color>
+    <color name="i_am_color_1cc9">#00001cc9</color>
+    <color name="i_am_color_1cca">#00001cca</color>
+    <color name="i_am_color_1ccb">#00001ccb</color>
+    <color name="i_am_color_1ccc">#00001ccc</color>
+    <color name="i_am_color_1ccd">#00001ccd</color>
+    <color name="i_am_color_1cce">#00001cce</color>
+    <color name="i_am_color_1ccf">#00001ccf</color>
+    <color name="i_am_color_1cd0">#00001cd0</color>
+    <color name="i_am_color_1cd1">#00001cd1</color>
+    <color name="i_am_color_1cd2">#00001cd2</color>
+    <color name="i_am_color_1cd3">#00001cd3</color>
+    <color name="i_am_color_1cd4">#00001cd4</color>
+    <color name="i_am_color_1cd5">#00001cd5</color>
+    <color name="i_am_color_1cd6">#00001cd6</color>
+    <color name="i_am_color_1cd7">#00001cd7</color>
+    <color name="i_am_color_1cd8">#00001cd8</color>
+    <color name="i_am_color_1cd9">#00001cd9</color>
+    <color name="i_am_color_1cda">#00001cda</color>
+    <color name="i_am_color_1cdb">#00001cdb</color>
+    <color name="i_am_color_1cdc">#00001cdc</color>
+    <color name="i_am_color_1cdd">#00001cdd</color>
+    <color name="i_am_color_1cde">#00001cde</color>
+    <color name="i_am_color_1cdf">#00001cdf</color>
+    <color name="i_am_color_1ce0">#00001ce0</color>
+    <color name="i_am_color_1ce1">#00001ce1</color>
+    <color name="i_am_color_1ce2">#00001ce2</color>
+    <color name="i_am_color_1ce3">#00001ce3</color>
+    <color name="i_am_color_1ce4">#00001ce4</color>
+    <color name="i_am_color_1ce5">#00001ce5</color>
+    <color name="i_am_color_1ce6">#00001ce6</color>
+    <color name="i_am_color_1ce7">#00001ce7</color>
+    <color name="i_am_color_1ce8">#00001ce8</color>
+    <color name="i_am_color_1ce9">#00001ce9</color>
+    <color name="i_am_color_1cea">#00001cea</color>
+    <color name="i_am_color_1ceb">#00001ceb</color>
+    <color name="i_am_color_1cec">#00001cec</color>
+    <color name="i_am_color_1ced">#00001ced</color>
+    <color name="i_am_color_1cee">#00001cee</color>
+    <color name="i_am_color_1cef">#00001cef</color>
+    <color name="i_am_color_1cf0">#00001cf0</color>
+    <color name="i_am_color_1cf1">#00001cf1</color>
+    <color name="i_am_color_1cf2">#00001cf2</color>
+    <color name="i_am_color_1cf3">#00001cf3</color>
+    <color name="i_am_color_1cf4">#00001cf4</color>
+    <color name="i_am_color_1cf5">#00001cf5</color>
+    <color name="i_am_color_1cf6">#00001cf6</color>
+    <color name="i_am_color_1cf7">#00001cf7</color>
+    <color name="i_am_color_1cf8">#00001cf8</color>
+    <color name="i_am_color_1cf9">#00001cf9</color>
+    <color name="i_am_color_1cfa">#00001cfa</color>
+    <color name="i_am_color_1cfb">#00001cfb</color>
+    <color name="i_am_color_1cfc">#00001cfc</color>
+    <color name="i_am_color_1cfd">#00001cfd</color>
+    <color name="i_am_color_1cfe">#00001cfe</color>
+    <color name="i_am_color_1cff">#00001cff</color>
+    <color name="i_am_color_1d00">#00001d00</color>
+    <color name="i_am_color_1d01">#00001d01</color>
+    <color name="i_am_color_1d02">#00001d02</color>
+    <color name="i_am_color_1d03">#00001d03</color>
+    <color name="i_am_color_1d04">#00001d04</color>
+    <color name="i_am_color_1d05">#00001d05</color>
+    <color name="i_am_color_1d06">#00001d06</color>
+    <color name="i_am_color_1d07">#00001d07</color>
+    <color name="i_am_color_1d08">#00001d08</color>
+    <color name="i_am_color_1d09">#00001d09</color>
+    <color name="i_am_color_1d0a">#00001d0a</color>
+    <color name="i_am_color_1d0b">#00001d0b</color>
+    <color name="i_am_color_1d0c">#00001d0c</color>
+    <color name="i_am_color_1d0d">#00001d0d</color>
+    <color name="i_am_color_1d0e">#00001d0e</color>
+    <color name="i_am_color_1d0f">#00001d0f</color>
+    <color name="i_am_color_1d10">#00001d10</color>
+    <color name="i_am_color_1d11">#00001d11</color>
+    <color name="i_am_color_1d12">#00001d12</color>
+    <color name="i_am_color_1d13">#00001d13</color>
+    <color name="i_am_color_1d14">#00001d14</color>
+    <color name="i_am_color_1d15">#00001d15</color>
+    <color name="i_am_color_1d16">#00001d16</color>
+    <color name="i_am_color_1d17">#00001d17</color>
+    <color name="i_am_color_1d18">#00001d18</color>
+    <color name="i_am_color_1d19">#00001d19</color>
+    <color name="i_am_color_1d1a">#00001d1a</color>
+    <color name="i_am_color_1d1b">#00001d1b</color>
+    <color name="i_am_color_1d1c">#00001d1c</color>
+    <color name="i_am_color_1d1d">#00001d1d</color>
+    <color name="i_am_color_1d1e">#00001d1e</color>
+    <color name="i_am_color_1d1f">#00001d1f</color>
+    <color name="i_am_color_1d20">#00001d20</color>
+    <color name="i_am_color_1d21">#00001d21</color>
+    <color name="i_am_color_1d22">#00001d22</color>
+    <color name="i_am_color_1d23">#00001d23</color>
+    <color name="i_am_color_1d24">#00001d24</color>
+    <color name="i_am_color_1d25">#00001d25</color>
+    <color name="i_am_color_1d26">#00001d26</color>
+    <color name="i_am_color_1d27">#00001d27</color>
+    <color name="i_am_color_1d28">#00001d28</color>
+    <color name="i_am_color_1d29">#00001d29</color>
+    <color name="i_am_color_1d2a">#00001d2a</color>
+    <color name="i_am_color_1d2b">#00001d2b</color>
+    <color name="i_am_color_1d2c">#00001d2c</color>
+    <color name="i_am_color_1d2d">#00001d2d</color>
+    <color name="i_am_color_1d2e">#00001d2e</color>
+    <color name="i_am_color_1d2f">#00001d2f</color>
+    <color name="i_am_color_1d30">#00001d30</color>
+    <color name="i_am_color_1d31">#00001d31</color>
+    <color name="i_am_color_1d32">#00001d32</color>
+    <color name="i_am_color_1d33">#00001d33</color>
+    <color name="i_am_color_1d34">#00001d34</color>
+    <color name="i_am_color_1d35">#00001d35</color>
+    <color name="i_am_color_1d36">#00001d36</color>
+    <color name="i_am_color_1d37">#00001d37</color>
+    <color name="i_am_color_1d38">#00001d38</color>
+    <color name="i_am_color_1d39">#00001d39</color>
+    <color name="i_am_color_1d3a">#00001d3a</color>
+    <color name="i_am_color_1d3b">#00001d3b</color>
+    <color name="i_am_color_1d3c">#00001d3c</color>
+    <color name="i_am_color_1d3d">#00001d3d</color>
+    <color name="i_am_color_1d3e">#00001d3e</color>
+    <color name="i_am_color_1d3f">#00001d3f</color>
+    <color name="i_am_color_1d40">#00001d40</color>
+    <color name="i_am_color_1d41">#00001d41</color>
+    <color name="i_am_color_1d42">#00001d42</color>
+    <color name="i_am_color_1d43">#00001d43</color>
+    <color name="i_am_color_1d44">#00001d44</color>
+    <color name="i_am_color_1d45">#00001d45</color>
+    <color name="i_am_color_1d46">#00001d46</color>
+    <color name="i_am_color_1d47">#00001d47</color>
+    <color name="i_am_color_1d48">#00001d48</color>
+    <color name="i_am_color_1d49">#00001d49</color>
+    <color name="i_am_color_1d4a">#00001d4a</color>
+    <color name="i_am_color_1d4b">#00001d4b</color>
+    <color name="i_am_color_1d4c">#00001d4c</color>
+    <color name="i_am_color_1d4d">#00001d4d</color>
+    <color name="i_am_color_1d4e">#00001d4e</color>
+    <color name="i_am_color_1d4f">#00001d4f</color>
+    <color name="i_am_color_1d50">#00001d50</color>
+    <color name="i_am_color_1d51">#00001d51</color>
+    <color name="i_am_color_1d52">#00001d52</color>
+    <color name="i_am_color_1d53">#00001d53</color>
+    <color name="i_am_color_1d54">#00001d54</color>
+    <color name="i_am_color_1d55">#00001d55</color>
+    <color name="i_am_color_1d56">#00001d56</color>
+    <color name="i_am_color_1d57">#00001d57</color>
+    <color name="i_am_color_1d58">#00001d58</color>
+    <color name="i_am_color_1d59">#00001d59</color>
+    <color name="i_am_color_1d5a">#00001d5a</color>
+    <color name="i_am_color_1d5b">#00001d5b</color>
+    <color name="i_am_color_1d5c">#00001d5c</color>
+    <color name="i_am_color_1d5d">#00001d5d</color>
+    <color name="i_am_color_1d5e">#00001d5e</color>
+    <color name="i_am_color_1d5f">#00001d5f</color>
+    <color name="i_am_color_1d60">#00001d60</color>
+    <color name="i_am_color_1d61">#00001d61</color>
+    <color name="i_am_color_1d62">#00001d62</color>
+    <color name="i_am_color_1d63">#00001d63</color>
+    <color name="i_am_color_1d64">#00001d64</color>
+    <color name="i_am_color_1d65">#00001d65</color>
+    <color name="i_am_color_1d66">#00001d66</color>
+    <color name="i_am_color_1d67">#00001d67</color>
+    <color name="i_am_color_1d68">#00001d68</color>
+    <color name="i_am_color_1d69">#00001d69</color>
+    <color name="i_am_color_1d6a">#00001d6a</color>
+    <color name="i_am_color_1d6b">#00001d6b</color>
+    <color name="i_am_color_1d6c">#00001d6c</color>
+    <color name="i_am_color_1d6d">#00001d6d</color>
+    <color name="i_am_color_1d6e">#00001d6e</color>
+    <color name="i_am_color_1d6f">#00001d6f</color>
+    <color name="i_am_color_1d70">#00001d70</color>
+    <color name="i_am_color_1d71">#00001d71</color>
+    <color name="i_am_color_1d72">#00001d72</color>
+    <color name="i_am_color_1d73">#00001d73</color>
+    <color name="i_am_color_1d74">#00001d74</color>
+    <color name="i_am_color_1d75">#00001d75</color>
+    <color name="i_am_color_1d76">#00001d76</color>
+    <color name="i_am_color_1d77">#00001d77</color>
+    <color name="i_am_color_1d78">#00001d78</color>
+    <color name="i_am_color_1d79">#00001d79</color>
+    <color name="i_am_color_1d7a">#00001d7a</color>
+    <color name="i_am_color_1d7b">#00001d7b</color>
+    <color name="i_am_color_1d7c">#00001d7c</color>
+    <color name="i_am_color_1d7d">#00001d7d</color>
+    <color name="i_am_color_1d7e">#00001d7e</color>
+    <color name="i_am_color_1d7f">#00001d7f</color>
+    <color name="i_am_color_1d80">#00001d80</color>
+    <color name="i_am_color_1d81">#00001d81</color>
+    <color name="i_am_color_1d82">#00001d82</color>
+    <color name="i_am_color_1d83">#00001d83</color>
+    <color name="i_am_color_1d84">#00001d84</color>
+    <color name="i_am_color_1d85">#00001d85</color>
+    <color name="i_am_color_1d86">#00001d86</color>
+    <color name="i_am_color_1d87">#00001d87</color>
+    <color name="i_am_color_1d88">#00001d88</color>
+    <color name="i_am_color_1d89">#00001d89</color>
+    <color name="i_am_color_1d8a">#00001d8a</color>
+    <color name="i_am_color_1d8b">#00001d8b</color>
+    <color name="i_am_color_1d8c">#00001d8c</color>
+    <color name="i_am_color_1d8d">#00001d8d</color>
+    <color name="i_am_color_1d8e">#00001d8e</color>
+    <color name="i_am_color_1d8f">#00001d8f</color>
+    <color name="i_am_color_1d90">#00001d90</color>
+    <color name="i_am_color_1d91">#00001d91</color>
+    <color name="i_am_color_1d92">#00001d92</color>
+    <color name="i_am_color_1d93">#00001d93</color>
+    <color name="i_am_color_1d94">#00001d94</color>
+    <color name="i_am_color_1d95">#00001d95</color>
+    <color name="i_am_color_1d96">#00001d96</color>
+    <color name="i_am_color_1d97">#00001d97</color>
+    <color name="i_am_color_1d98">#00001d98</color>
+    <color name="i_am_color_1d99">#00001d99</color>
+    <color name="i_am_color_1d9a">#00001d9a</color>
+    <color name="i_am_color_1d9b">#00001d9b</color>
+    <color name="i_am_color_1d9c">#00001d9c</color>
+    <color name="i_am_color_1d9d">#00001d9d</color>
+    <color name="i_am_color_1d9e">#00001d9e</color>
+    <color name="i_am_color_1d9f">#00001d9f</color>
+    <color name="i_am_color_1da0">#00001da0</color>
+    <color name="i_am_color_1da1">#00001da1</color>
+    <color name="i_am_color_1da2">#00001da2</color>
+    <color name="i_am_color_1da3">#00001da3</color>
+    <color name="i_am_color_1da4">#00001da4</color>
+    <color name="i_am_color_1da5">#00001da5</color>
+    <color name="i_am_color_1da6">#00001da6</color>
+    <color name="i_am_color_1da7">#00001da7</color>
+    <color name="i_am_color_1da8">#00001da8</color>
+    <color name="i_am_color_1da9">#00001da9</color>
+    <color name="i_am_color_1daa">#00001daa</color>
+    <color name="i_am_color_1dab">#00001dab</color>
+    <color name="i_am_color_1dac">#00001dac</color>
+    <color name="i_am_color_1dad">#00001dad</color>
+    <color name="i_am_color_1dae">#00001dae</color>
+    <color name="i_am_color_1daf">#00001daf</color>
+    <color name="i_am_color_1db0">#00001db0</color>
+    <color name="i_am_color_1db1">#00001db1</color>
+    <color name="i_am_color_1db2">#00001db2</color>
+    <color name="i_am_color_1db3">#00001db3</color>
+    <color name="i_am_color_1db4">#00001db4</color>
+    <color name="i_am_color_1db5">#00001db5</color>
+    <color name="i_am_color_1db6">#00001db6</color>
+    <color name="i_am_color_1db7">#00001db7</color>
+    <color name="i_am_color_1db8">#00001db8</color>
+    <color name="i_am_color_1db9">#00001db9</color>
+    <color name="i_am_color_1dba">#00001dba</color>
+    <color name="i_am_color_1dbb">#00001dbb</color>
+    <color name="i_am_color_1dbc">#00001dbc</color>
+    <color name="i_am_color_1dbd">#00001dbd</color>
+    <color name="i_am_color_1dbe">#00001dbe</color>
+    <color name="i_am_color_1dbf">#00001dbf</color>
+    <color name="i_am_color_1dc0">#00001dc0</color>
+    <color name="i_am_color_1dc1">#00001dc1</color>
+    <color name="i_am_color_1dc2">#00001dc2</color>
+    <color name="i_am_color_1dc3">#00001dc3</color>
+    <color name="i_am_color_1dc4">#00001dc4</color>
+    <color name="i_am_color_1dc5">#00001dc5</color>
+    <color name="i_am_color_1dc6">#00001dc6</color>
+    <color name="i_am_color_1dc7">#00001dc7</color>
+    <color name="i_am_color_1dc8">#00001dc8</color>
+    <color name="i_am_color_1dc9">#00001dc9</color>
+    <color name="i_am_color_1dca">#00001dca</color>
+    <color name="i_am_color_1dcb">#00001dcb</color>
+    <color name="i_am_color_1dcc">#00001dcc</color>
+    <color name="i_am_color_1dcd">#00001dcd</color>
+    <color name="i_am_color_1dce">#00001dce</color>
+    <color name="i_am_color_1dcf">#00001dcf</color>
+    <color name="i_am_color_1dd0">#00001dd0</color>
+    <color name="i_am_color_1dd1">#00001dd1</color>
+    <color name="i_am_color_1dd2">#00001dd2</color>
+    <color name="i_am_color_1dd3">#00001dd3</color>
+    <color name="i_am_color_1dd4">#00001dd4</color>
+    <color name="i_am_color_1dd5">#00001dd5</color>
+    <color name="i_am_color_1dd6">#00001dd6</color>
+    <color name="i_am_color_1dd7">#00001dd7</color>
+    <color name="i_am_color_1dd8">#00001dd8</color>
+    <color name="i_am_color_1dd9">#00001dd9</color>
+    <color name="i_am_color_1dda">#00001dda</color>
+    <color name="i_am_color_1ddb">#00001ddb</color>
+    <color name="i_am_color_1ddc">#00001ddc</color>
+    <color name="i_am_color_1ddd">#00001ddd</color>
+    <color name="i_am_color_1dde">#00001dde</color>
+    <color name="i_am_color_1ddf">#00001ddf</color>
+    <color name="i_am_color_1de0">#00001de0</color>
+    <color name="i_am_color_1de1">#00001de1</color>
+    <color name="i_am_color_1de2">#00001de2</color>
+    <color name="i_am_color_1de3">#00001de3</color>
+    <color name="i_am_color_1de4">#00001de4</color>
+    <color name="i_am_color_1de5">#00001de5</color>
+    <color name="i_am_color_1de6">#00001de6</color>
+    <color name="i_am_color_1de7">#00001de7</color>
+    <color name="i_am_color_1de8">#00001de8</color>
+    <color name="i_am_color_1de9">#00001de9</color>
+    <color name="i_am_color_1dea">#00001dea</color>
+    <color name="i_am_color_1deb">#00001deb</color>
+    <color name="i_am_color_1dec">#00001dec</color>
+    <color name="i_am_color_1ded">#00001ded</color>
+    <color name="i_am_color_1dee">#00001dee</color>
+    <color name="i_am_color_1def">#00001def</color>
+    <color name="i_am_color_1df0">#00001df0</color>
+    <color name="i_am_color_1df1">#00001df1</color>
+    <color name="i_am_color_1df2">#00001df2</color>
+    <color name="i_am_color_1df3">#00001df3</color>
+    <color name="i_am_color_1df4">#00001df4</color>
+    <color name="i_am_color_1df5">#00001df5</color>
+    <color name="i_am_color_1df6">#00001df6</color>
+    <color name="i_am_color_1df7">#00001df7</color>
+    <color name="i_am_color_1df8">#00001df8</color>
+    <color name="i_am_color_1df9">#00001df9</color>
+    <color name="i_am_color_1dfa">#00001dfa</color>
+    <color name="i_am_color_1dfb">#00001dfb</color>
+    <color name="i_am_color_1dfc">#00001dfc</color>
+    <color name="i_am_color_1dfd">#00001dfd</color>
+    <color name="i_am_color_1dfe">#00001dfe</color>
+    <color name="i_am_color_1dff">#00001dff</color>
+    <color name="i_am_color_1e00">#00001e00</color>
+    <color name="i_am_color_1e01">#00001e01</color>
+    <color name="i_am_color_1e02">#00001e02</color>
+    <color name="i_am_color_1e03">#00001e03</color>
+    <color name="i_am_color_1e04">#00001e04</color>
+    <color name="i_am_color_1e05">#00001e05</color>
+    <color name="i_am_color_1e06">#00001e06</color>
+    <color name="i_am_color_1e07">#00001e07</color>
+    <color name="i_am_color_1e08">#00001e08</color>
+    <color name="i_am_color_1e09">#00001e09</color>
+    <color name="i_am_color_1e0a">#00001e0a</color>
+    <color name="i_am_color_1e0b">#00001e0b</color>
+    <color name="i_am_color_1e0c">#00001e0c</color>
+    <color name="i_am_color_1e0d">#00001e0d</color>
+    <color name="i_am_color_1e0e">#00001e0e</color>
+    <color name="i_am_color_1e0f">#00001e0f</color>
+    <color name="i_am_color_1e10">#00001e10</color>
+    <color name="i_am_color_1e11">#00001e11</color>
+    <color name="i_am_color_1e12">#00001e12</color>
+    <color name="i_am_color_1e13">#00001e13</color>
+    <color name="i_am_color_1e14">#00001e14</color>
+    <color name="i_am_color_1e15">#00001e15</color>
+    <color name="i_am_color_1e16">#00001e16</color>
+    <color name="i_am_color_1e17">#00001e17</color>
+    <color name="i_am_color_1e18">#00001e18</color>
+    <color name="i_am_color_1e19">#00001e19</color>
+    <color name="i_am_color_1e1a">#00001e1a</color>
+    <color name="i_am_color_1e1b">#00001e1b</color>
+    <color name="i_am_color_1e1c">#00001e1c</color>
+    <color name="i_am_color_1e1d">#00001e1d</color>
+    <color name="i_am_color_1e1e">#00001e1e</color>
+    <color name="i_am_color_1e1f">#00001e1f</color>
+    <color name="i_am_color_1e20">#00001e20</color>
+    <color name="i_am_color_1e21">#00001e21</color>
+    <color name="i_am_color_1e22">#00001e22</color>
+    <color name="i_am_color_1e23">#00001e23</color>
+    <color name="i_am_color_1e24">#00001e24</color>
+    <color name="i_am_color_1e25">#00001e25</color>
+    <color name="i_am_color_1e26">#00001e26</color>
+    <color name="i_am_color_1e27">#00001e27</color>
+    <color name="i_am_color_1e28">#00001e28</color>
+    <color name="i_am_color_1e29">#00001e29</color>
+    <color name="i_am_color_1e2a">#00001e2a</color>
+    <color name="i_am_color_1e2b">#00001e2b</color>
+    <color name="i_am_color_1e2c">#00001e2c</color>
+    <color name="i_am_color_1e2d">#00001e2d</color>
+    <color name="i_am_color_1e2e">#00001e2e</color>
+    <color name="i_am_color_1e2f">#00001e2f</color>
+    <color name="i_am_color_1e30">#00001e30</color>
+    <color name="i_am_color_1e31">#00001e31</color>
+    <color name="i_am_color_1e32">#00001e32</color>
+    <color name="i_am_color_1e33">#00001e33</color>
+    <color name="i_am_color_1e34">#00001e34</color>
+    <color name="i_am_color_1e35">#00001e35</color>
+    <color name="i_am_color_1e36">#00001e36</color>
+    <color name="i_am_color_1e37">#00001e37</color>
+    <color name="i_am_color_1e38">#00001e38</color>
+    <color name="i_am_color_1e39">#00001e39</color>
+    <color name="i_am_color_1e3a">#00001e3a</color>
+    <color name="i_am_color_1e3b">#00001e3b</color>
+    <color name="i_am_color_1e3c">#00001e3c</color>
+    <color name="i_am_color_1e3d">#00001e3d</color>
+    <color name="i_am_color_1e3e">#00001e3e</color>
+    <color name="i_am_color_1e3f">#00001e3f</color>
+    <color name="i_am_color_1e40">#00001e40</color>
+    <color name="i_am_color_1e41">#00001e41</color>
+    <color name="i_am_color_1e42">#00001e42</color>
+    <color name="i_am_color_1e43">#00001e43</color>
+    <color name="i_am_color_1e44">#00001e44</color>
+    <color name="i_am_color_1e45">#00001e45</color>
+    <color name="i_am_color_1e46">#00001e46</color>
+    <color name="i_am_color_1e47">#00001e47</color>
+    <color name="i_am_color_1e48">#00001e48</color>
+    <color name="i_am_color_1e49">#00001e49</color>
+    <color name="i_am_color_1e4a">#00001e4a</color>
+    <color name="i_am_color_1e4b">#00001e4b</color>
+    <color name="i_am_color_1e4c">#00001e4c</color>
+    <color name="i_am_color_1e4d">#00001e4d</color>
+    <color name="i_am_color_1e4e">#00001e4e</color>
+    <color name="i_am_color_1e4f">#00001e4f</color>
+    <color name="i_am_color_1e50">#00001e50</color>
+    <color name="i_am_color_1e51">#00001e51</color>
+    <color name="i_am_color_1e52">#00001e52</color>
+    <color name="i_am_color_1e53">#00001e53</color>
+    <color name="i_am_color_1e54">#00001e54</color>
+    <color name="i_am_color_1e55">#00001e55</color>
+    <color name="i_am_color_1e56">#00001e56</color>
+    <color name="i_am_color_1e57">#00001e57</color>
+    <color name="i_am_color_1e58">#00001e58</color>
+    <color name="i_am_color_1e59">#00001e59</color>
+    <color name="i_am_color_1e5a">#00001e5a</color>
+    <color name="i_am_color_1e5b">#00001e5b</color>
+    <color name="i_am_color_1e5c">#00001e5c</color>
+    <color name="i_am_color_1e5d">#00001e5d</color>
+    <color name="i_am_color_1e5e">#00001e5e</color>
+    <color name="i_am_color_1e5f">#00001e5f</color>
+    <color name="i_am_color_1e60">#00001e60</color>
+    <color name="i_am_color_1e61">#00001e61</color>
+    <color name="i_am_color_1e62">#00001e62</color>
+    <color name="i_am_color_1e63">#00001e63</color>
+    <color name="i_am_color_1e64">#00001e64</color>
+    <color name="i_am_color_1e65">#00001e65</color>
+    <color name="i_am_color_1e66">#00001e66</color>
+    <color name="i_am_color_1e67">#00001e67</color>
+    <color name="i_am_color_1e68">#00001e68</color>
+    <color name="i_am_color_1e69">#00001e69</color>
+    <color name="i_am_color_1e6a">#00001e6a</color>
+    <color name="i_am_color_1e6b">#00001e6b</color>
+    <color name="i_am_color_1e6c">#00001e6c</color>
+    <color name="i_am_color_1e6d">#00001e6d</color>
+    <color name="i_am_color_1e6e">#00001e6e</color>
+    <color name="i_am_color_1e6f">#00001e6f</color>
+    <color name="i_am_color_1e70">#00001e70</color>
+    <color name="i_am_color_1e71">#00001e71</color>
+    <color name="i_am_color_1e72">#00001e72</color>
+    <color name="i_am_color_1e73">#00001e73</color>
+    <color name="i_am_color_1e74">#00001e74</color>
+    <color name="i_am_color_1e75">#00001e75</color>
+    <color name="i_am_color_1e76">#00001e76</color>
+    <color name="i_am_color_1e77">#00001e77</color>
+    <color name="i_am_color_1e78">#00001e78</color>
+    <color name="i_am_color_1e79">#00001e79</color>
+    <color name="i_am_color_1e7a">#00001e7a</color>
+    <color name="i_am_color_1e7b">#00001e7b</color>
+    <color name="i_am_color_1e7c">#00001e7c</color>
+    <color name="i_am_color_1e7d">#00001e7d</color>
+    <color name="i_am_color_1e7e">#00001e7e</color>
+    <color name="i_am_color_1e7f">#00001e7f</color>
+    <color name="i_am_color_1e80">#00001e80</color>
+    <color name="i_am_color_1e81">#00001e81</color>
+    <color name="i_am_color_1e82">#00001e82</color>
+    <color name="i_am_color_1e83">#00001e83</color>
+    <color name="i_am_color_1e84">#00001e84</color>
+    <color name="i_am_color_1e85">#00001e85</color>
+    <color name="i_am_color_1e86">#00001e86</color>
+    <color name="i_am_color_1e87">#00001e87</color>
+    <color name="i_am_color_1e88">#00001e88</color>
+    <color name="i_am_color_1e89">#00001e89</color>
+    <color name="i_am_color_1e8a">#00001e8a</color>
+    <color name="i_am_color_1e8b">#00001e8b</color>
+    <color name="i_am_color_1e8c">#00001e8c</color>
+    <color name="i_am_color_1e8d">#00001e8d</color>
+    <color name="i_am_color_1e8e">#00001e8e</color>
+    <color name="i_am_color_1e8f">#00001e8f</color>
+    <color name="i_am_color_1e90">#00001e90</color>
+    <color name="i_am_color_1e91">#00001e91</color>
+    <color name="i_am_color_1e92">#00001e92</color>
+    <color name="i_am_color_1e93">#00001e93</color>
+    <color name="i_am_color_1e94">#00001e94</color>
+    <color name="i_am_color_1e95">#00001e95</color>
+    <color name="i_am_color_1e96">#00001e96</color>
+    <color name="i_am_color_1e97">#00001e97</color>
+    <color name="i_am_color_1e98">#00001e98</color>
+    <color name="i_am_color_1e99">#00001e99</color>
+    <color name="i_am_color_1e9a">#00001e9a</color>
+    <color name="i_am_color_1e9b">#00001e9b</color>
+    <color name="i_am_color_1e9c">#00001e9c</color>
+    <color name="i_am_color_1e9d">#00001e9d</color>
+    <color name="i_am_color_1e9e">#00001e9e</color>
+    <color name="i_am_color_1e9f">#00001e9f</color>
+    <color name="i_am_color_1ea0">#00001ea0</color>
+    <color name="i_am_color_1ea1">#00001ea1</color>
+    <color name="i_am_color_1ea2">#00001ea2</color>
+    <color name="i_am_color_1ea3">#00001ea3</color>
+    <color name="i_am_color_1ea4">#00001ea4</color>
+    <color name="i_am_color_1ea5">#00001ea5</color>
+    <color name="i_am_color_1ea6">#00001ea6</color>
+    <color name="i_am_color_1ea7">#00001ea7</color>
+    <color name="i_am_color_1ea8">#00001ea8</color>
+    <color name="i_am_color_1ea9">#00001ea9</color>
+    <color name="i_am_color_1eaa">#00001eaa</color>
+    <color name="i_am_color_1eab">#00001eab</color>
+    <color name="i_am_color_1eac">#00001eac</color>
+    <color name="i_am_color_1ead">#00001ead</color>
+    <color name="i_am_color_1eae">#00001eae</color>
+    <color name="i_am_color_1eaf">#00001eaf</color>
+    <color name="i_am_color_1eb0">#00001eb0</color>
+    <color name="i_am_color_1eb1">#00001eb1</color>
+    <color name="i_am_color_1eb2">#00001eb2</color>
+    <color name="i_am_color_1eb3">#00001eb3</color>
+    <color name="i_am_color_1eb4">#00001eb4</color>
+    <color name="i_am_color_1eb5">#00001eb5</color>
+    <color name="i_am_color_1eb6">#00001eb6</color>
+    <color name="i_am_color_1eb7">#00001eb7</color>
+    <color name="i_am_color_1eb8">#00001eb8</color>
+    <color name="i_am_color_1eb9">#00001eb9</color>
+    <color name="i_am_color_1eba">#00001eba</color>
+    <color name="i_am_color_1ebb">#00001ebb</color>
+    <color name="i_am_color_1ebc">#00001ebc</color>
+    <color name="i_am_color_1ebd">#00001ebd</color>
+    <color name="i_am_color_1ebe">#00001ebe</color>
+    <color name="i_am_color_1ebf">#00001ebf</color>
+    <color name="i_am_color_1ec0">#00001ec0</color>
+    <color name="i_am_color_1ec1">#00001ec1</color>
+    <color name="i_am_color_1ec2">#00001ec2</color>
+    <color name="i_am_color_1ec3">#00001ec3</color>
+    <color name="i_am_color_1ec4">#00001ec4</color>
+    <color name="i_am_color_1ec5">#00001ec5</color>
+    <color name="i_am_color_1ec6">#00001ec6</color>
+    <color name="i_am_color_1ec7">#00001ec7</color>
+    <color name="i_am_color_1ec8">#00001ec8</color>
+    <color name="i_am_color_1ec9">#00001ec9</color>
+    <color name="i_am_color_1eca">#00001eca</color>
+    <color name="i_am_color_1ecb">#00001ecb</color>
+    <color name="i_am_color_1ecc">#00001ecc</color>
+    <color name="i_am_color_1ecd">#00001ecd</color>
+    <color name="i_am_color_1ece">#00001ece</color>
+    <color name="i_am_color_1ecf">#00001ecf</color>
+    <color name="i_am_color_1ed0">#00001ed0</color>
+    <color name="i_am_color_1ed1">#00001ed1</color>
+    <color name="i_am_color_1ed2">#00001ed2</color>
+    <color name="i_am_color_1ed3">#00001ed3</color>
+    <color name="i_am_color_1ed4">#00001ed4</color>
+    <color name="i_am_color_1ed5">#00001ed5</color>
+    <color name="i_am_color_1ed6">#00001ed6</color>
+    <color name="i_am_color_1ed7">#00001ed7</color>
+    <color name="i_am_color_1ed8">#00001ed8</color>
+    <color name="i_am_color_1ed9">#00001ed9</color>
+    <color name="i_am_color_1eda">#00001eda</color>
+    <color name="i_am_color_1edb">#00001edb</color>
+    <color name="i_am_color_1edc">#00001edc</color>
+    <color name="i_am_color_1edd">#00001edd</color>
+    <color name="i_am_color_1ede">#00001ede</color>
+    <color name="i_am_color_1edf">#00001edf</color>
+    <color name="i_am_color_1ee0">#00001ee0</color>
+    <color name="i_am_color_1ee1">#00001ee1</color>
+    <color name="i_am_color_1ee2">#00001ee2</color>
+    <color name="i_am_color_1ee3">#00001ee3</color>
+    <color name="i_am_color_1ee4">#00001ee4</color>
+    <color name="i_am_color_1ee5">#00001ee5</color>
+    <color name="i_am_color_1ee6">#00001ee6</color>
+    <color name="i_am_color_1ee7">#00001ee7</color>
+    <color name="i_am_color_1ee8">#00001ee8</color>
+    <color name="i_am_color_1ee9">#00001ee9</color>
+    <color name="i_am_color_1eea">#00001eea</color>
+    <color name="i_am_color_1eeb">#00001eeb</color>
+    <color name="i_am_color_1eec">#00001eec</color>
+    <color name="i_am_color_1eed">#00001eed</color>
+    <color name="i_am_color_1eee">#00001eee</color>
+    <color name="i_am_color_1eef">#00001eef</color>
+    <color name="i_am_color_1ef0">#00001ef0</color>
+    <color name="i_am_color_1ef1">#00001ef1</color>
+    <color name="i_am_color_1ef2">#00001ef2</color>
+    <color name="i_am_color_1ef3">#00001ef3</color>
+    <color name="i_am_color_1ef4">#00001ef4</color>
+    <color name="i_am_color_1ef5">#00001ef5</color>
+    <color name="i_am_color_1ef6">#00001ef6</color>
+    <color name="i_am_color_1ef7">#00001ef7</color>
+    <color name="i_am_color_1ef8">#00001ef8</color>
+    <color name="i_am_color_1ef9">#00001ef9</color>
+    <color name="i_am_color_1efa">#00001efa</color>
+    <color name="i_am_color_1efb">#00001efb</color>
+    <color name="i_am_color_1efc">#00001efc</color>
+    <color name="i_am_color_1efd">#00001efd</color>
+    <color name="i_am_color_1efe">#00001efe</color>
+    <color name="i_am_color_1eff">#00001eff</color>
+    <color name="i_am_color_1f00">#00001f00</color>
+    <color name="i_am_color_1f01">#00001f01</color>
+    <color name="i_am_color_1f02">#00001f02</color>
+    <color name="i_am_color_1f03">#00001f03</color>
+    <color name="i_am_color_1f04">#00001f04</color>
+    <color name="i_am_color_1f05">#00001f05</color>
+    <color name="i_am_color_1f06">#00001f06</color>
+    <color name="i_am_color_1f07">#00001f07</color>
+    <color name="i_am_color_1f08">#00001f08</color>
+    <color name="i_am_color_1f09">#00001f09</color>
+    <color name="i_am_color_1f0a">#00001f0a</color>
+    <color name="i_am_color_1f0b">#00001f0b</color>
+    <color name="i_am_color_1f0c">#00001f0c</color>
+    <color name="i_am_color_1f0d">#00001f0d</color>
+    <color name="i_am_color_1f0e">#00001f0e</color>
+    <color name="i_am_color_1f0f">#00001f0f</color>
+    <color name="i_am_color_1f10">#00001f10</color>
+    <color name="i_am_color_1f11">#00001f11</color>
+    <color name="i_am_color_1f12">#00001f12</color>
+    <color name="i_am_color_1f13">#00001f13</color>
+    <color name="i_am_color_1f14">#00001f14</color>
+    <color name="i_am_color_1f15">#00001f15</color>
+    <color name="i_am_color_1f16">#00001f16</color>
+    <color name="i_am_color_1f17">#00001f17</color>
+    <color name="i_am_color_1f18">#00001f18</color>
+    <color name="i_am_color_1f19">#00001f19</color>
+    <color name="i_am_color_1f1a">#00001f1a</color>
+    <color name="i_am_color_1f1b">#00001f1b</color>
+    <color name="i_am_color_1f1c">#00001f1c</color>
+    <color name="i_am_color_1f1d">#00001f1d</color>
+    <color name="i_am_color_1f1e">#00001f1e</color>
+    <color name="i_am_color_1f1f">#00001f1f</color>
+    <color name="i_am_color_1f20">#00001f20</color>
+    <color name="i_am_color_1f21">#00001f21</color>
+    <color name="i_am_color_1f22">#00001f22</color>
+    <color name="i_am_color_1f23">#00001f23</color>
+    <color name="i_am_color_1f24">#00001f24</color>
+    <color name="i_am_color_1f25">#00001f25</color>
+    <color name="i_am_color_1f26">#00001f26</color>
+    <color name="i_am_color_1f27">#00001f27</color>
+    <color name="i_am_color_1f28">#00001f28</color>
+    <color name="i_am_color_1f29">#00001f29</color>
+    <color name="i_am_color_1f2a">#00001f2a</color>
+    <color name="i_am_color_1f2b">#00001f2b</color>
+    <color name="i_am_color_1f2c">#00001f2c</color>
+    <color name="i_am_color_1f2d">#00001f2d</color>
+    <color name="i_am_color_1f2e">#00001f2e</color>
+    <color name="i_am_color_1f2f">#00001f2f</color>
+    <color name="i_am_color_1f30">#00001f30</color>
+    <color name="i_am_color_1f31">#00001f31</color>
+    <color name="i_am_color_1f32">#00001f32</color>
+    <color name="i_am_color_1f33">#00001f33</color>
+    <color name="i_am_color_1f34">#00001f34</color>
+    <color name="i_am_color_1f35">#00001f35</color>
+    <color name="i_am_color_1f36">#00001f36</color>
+    <color name="i_am_color_1f37">#00001f37</color>
+    <color name="i_am_color_1f38">#00001f38</color>
+    <color name="i_am_color_1f39">#00001f39</color>
+    <color name="i_am_color_1f3a">#00001f3a</color>
+    <color name="i_am_color_1f3b">#00001f3b</color>
+    <color name="i_am_color_1f3c">#00001f3c</color>
+    <color name="i_am_color_1f3d">#00001f3d</color>
+    <color name="i_am_color_1f3e">#00001f3e</color>
+    <color name="i_am_color_1f3f">#00001f3f</color>
+    <color name="i_am_color_1f40">#00001f40</color>
+    <color name="i_am_color_1f41">#00001f41</color>
+    <color name="i_am_color_1f42">#00001f42</color>
+    <color name="i_am_color_1f43">#00001f43</color>
+    <color name="i_am_color_1f44">#00001f44</color>
+    <color name="i_am_color_1f45">#00001f45</color>
+    <color name="i_am_color_1f46">#00001f46</color>
+    <color name="i_am_color_1f47">#00001f47</color>
+    <color name="i_am_color_1f48">#00001f48</color>
+    <color name="i_am_color_1f49">#00001f49</color>
+    <color name="i_am_color_1f4a">#00001f4a</color>
+    <color name="i_am_color_1f4b">#00001f4b</color>
+    <color name="i_am_color_1f4c">#00001f4c</color>
+    <color name="i_am_color_1f4d">#00001f4d</color>
+    <color name="i_am_color_1f4e">#00001f4e</color>
+    <color name="i_am_color_1f4f">#00001f4f</color>
+    <color name="i_am_color_1f50">#00001f50</color>
+    <color name="i_am_color_1f51">#00001f51</color>
+    <color name="i_am_color_1f52">#00001f52</color>
+    <color name="i_am_color_1f53">#00001f53</color>
+    <color name="i_am_color_1f54">#00001f54</color>
+    <color name="i_am_color_1f55">#00001f55</color>
+    <color name="i_am_color_1f56">#00001f56</color>
+    <color name="i_am_color_1f57">#00001f57</color>
+    <color name="i_am_color_1f58">#00001f58</color>
+    <color name="i_am_color_1f59">#00001f59</color>
+    <color name="i_am_color_1f5a">#00001f5a</color>
+    <color name="i_am_color_1f5b">#00001f5b</color>
+    <color name="i_am_color_1f5c">#00001f5c</color>
+    <color name="i_am_color_1f5d">#00001f5d</color>
+    <color name="i_am_color_1f5e">#00001f5e</color>
+    <color name="i_am_color_1f5f">#00001f5f</color>
+    <color name="i_am_color_1f60">#00001f60</color>
+    <color name="i_am_color_1f61">#00001f61</color>
+    <color name="i_am_color_1f62">#00001f62</color>
+    <color name="i_am_color_1f63">#00001f63</color>
+    <color name="i_am_color_1f64">#00001f64</color>
+    <color name="i_am_color_1f65">#00001f65</color>
+    <color name="i_am_color_1f66">#00001f66</color>
+    <color name="i_am_color_1f67">#00001f67</color>
+    <color name="i_am_color_1f68">#00001f68</color>
+    <color name="i_am_color_1f69">#00001f69</color>
+    <color name="i_am_color_1f6a">#00001f6a</color>
+    <color name="i_am_color_1f6b">#00001f6b</color>
+    <color name="i_am_color_1f6c">#00001f6c</color>
+    <color name="i_am_color_1f6d">#00001f6d</color>
+    <color name="i_am_color_1f6e">#00001f6e</color>
+    <color name="i_am_color_1f6f">#00001f6f</color>
+    <color name="i_am_color_1f70">#00001f70</color>
+    <color name="i_am_color_1f71">#00001f71</color>
+    <color name="i_am_color_1f72">#00001f72</color>
+    <color name="i_am_color_1f73">#00001f73</color>
+    <color name="i_am_color_1f74">#00001f74</color>
+    <color name="i_am_color_1f75">#00001f75</color>
+    <color name="i_am_color_1f76">#00001f76</color>
+    <color name="i_am_color_1f77">#00001f77</color>
+    <color name="i_am_color_1f78">#00001f78</color>
+    <color name="i_am_color_1f79">#00001f79</color>
+    <color name="i_am_color_1f7a">#00001f7a</color>
+    <color name="i_am_color_1f7b">#00001f7b</color>
+    <color name="i_am_color_1f7c">#00001f7c</color>
+    <color name="i_am_color_1f7d">#00001f7d</color>
+    <color name="i_am_color_1f7e">#00001f7e</color>
+    <color name="i_am_color_1f7f">#00001f7f</color>
+    <color name="i_am_color_1f80">#00001f80</color>
+    <color name="i_am_color_1f81">#00001f81</color>
+    <color name="i_am_color_1f82">#00001f82</color>
+    <color name="i_am_color_1f83">#00001f83</color>
+    <color name="i_am_color_1f84">#00001f84</color>
+    <color name="i_am_color_1f85">#00001f85</color>
+    <color name="i_am_color_1f86">#00001f86</color>
+    <color name="i_am_color_1f87">#00001f87</color>
+    <color name="i_am_color_1f88">#00001f88</color>
+    <color name="i_am_color_1f89">#00001f89</color>
+    <color name="i_am_color_1f8a">#00001f8a</color>
+    <color name="i_am_color_1f8b">#00001f8b</color>
+    <color name="i_am_color_1f8c">#00001f8c</color>
+    <color name="i_am_color_1f8d">#00001f8d</color>
+    <color name="i_am_color_1f8e">#00001f8e</color>
+    <color name="i_am_color_1f8f">#00001f8f</color>
+    <color name="i_am_color_1f90">#00001f90</color>
+    <color name="i_am_color_1f91">#00001f91</color>
+    <color name="i_am_color_1f92">#00001f92</color>
+    <color name="i_am_color_1f93">#00001f93</color>
+    <color name="i_am_color_1f94">#00001f94</color>
+    <color name="i_am_color_1f95">#00001f95</color>
+    <color name="i_am_color_1f96">#00001f96</color>
+    <color name="i_am_color_1f97">#00001f97</color>
+    <color name="i_am_color_1f98">#00001f98</color>
+    <color name="i_am_color_1f99">#00001f99</color>
+    <color name="i_am_color_1f9a">#00001f9a</color>
+    <color name="i_am_color_1f9b">#00001f9b</color>
+    <color name="i_am_color_1f9c">#00001f9c</color>
+    <color name="i_am_color_1f9d">#00001f9d</color>
+    <color name="i_am_color_1f9e">#00001f9e</color>
+    <color name="i_am_color_1f9f">#00001f9f</color>
+    <color name="i_am_color_1fa0">#00001fa0</color>
+    <color name="i_am_color_1fa1">#00001fa1</color>
+    <color name="i_am_color_1fa2">#00001fa2</color>
+    <color name="i_am_color_1fa3">#00001fa3</color>
+    <color name="i_am_color_1fa4">#00001fa4</color>
+    <color name="i_am_color_1fa5">#00001fa5</color>
+    <color name="i_am_color_1fa6">#00001fa6</color>
+    <color name="i_am_color_1fa7">#00001fa7</color>
+    <color name="i_am_color_1fa8">#00001fa8</color>
+    <color name="i_am_color_1fa9">#00001fa9</color>
+    <color name="i_am_color_1faa">#00001faa</color>
+    <color name="i_am_color_1fab">#00001fab</color>
+    <color name="i_am_color_1fac">#00001fac</color>
+    <color name="i_am_color_1fad">#00001fad</color>
+    <color name="i_am_color_1fae">#00001fae</color>
+    <color name="i_am_color_1faf">#00001faf</color>
+    <color name="i_am_color_1fb0">#00001fb0</color>
+    <color name="i_am_color_1fb1">#00001fb1</color>
+    <color name="i_am_color_1fb2">#00001fb2</color>
+    <color name="i_am_color_1fb3">#00001fb3</color>
+    <color name="i_am_color_1fb4">#00001fb4</color>
+    <color name="i_am_color_1fb5">#00001fb5</color>
+    <color name="i_am_color_1fb6">#00001fb6</color>
+    <color name="i_am_color_1fb7">#00001fb7</color>
+    <color name="i_am_color_1fb8">#00001fb8</color>
+    <color name="i_am_color_1fb9">#00001fb9</color>
+    <color name="i_am_color_1fba">#00001fba</color>
+    <color name="i_am_color_1fbb">#00001fbb</color>
+    <color name="i_am_color_1fbc">#00001fbc</color>
+    <color name="i_am_color_1fbd">#00001fbd</color>
+    <color name="i_am_color_1fbe">#00001fbe</color>
+    <color name="i_am_color_1fbf">#00001fbf</color>
+    <color name="i_am_color_1fc0">#00001fc0</color>
+    <color name="i_am_color_1fc1">#00001fc1</color>
+    <color name="i_am_color_1fc2">#00001fc2</color>
+    <color name="i_am_color_1fc3">#00001fc3</color>
+    <color name="i_am_color_1fc4">#00001fc4</color>
+    <color name="i_am_color_1fc5">#00001fc5</color>
+    <color name="i_am_color_1fc6">#00001fc6</color>
+    <color name="i_am_color_1fc7">#00001fc7</color>
+    <color name="i_am_color_1fc8">#00001fc8</color>
+    <color name="i_am_color_1fc9">#00001fc9</color>
+    <color name="i_am_color_1fca">#00001fca</color>
+    <color name="i_am_color_1fcb">#00001fcb</color>
+    <color name="i_am_color_1fcc">#00001fcc</color>
+    <color name="i_am_color_1fcd">#00001fcd</color>
+    <color name="i_am_color_1fce">#00001fce</color>
+    <color name="i_am_color_1fcf">#00001fcf</color>
+    <color name="i_am_color_1fd0">#00001fd0</color>
+    <color name="i_am_color_1fd1">#00001fd1</color>
+    <color name="i_am_color_1fd2">#00001fd2</color>
+    <color name="i_am_color_1fd3">#00001fd3</color>
+    <color name="i_am_color_1fd4">#00001fd4</color>
+    <color name="i_am_color_1fd5">#00001fd5</color>
+    <color name="i_am_color_1fd6">#00001fd6</color>
+    <color name="i_am_color_1fd7">#00001fd7</color>
+    <color name="i_am_color_1fd8">#00001fd8</color>
+    <color name="i_am_color_1fd9">#00001fd9</color>
+    <color name="i_am_color_1fda">#00001fda</color>
+    <color name="i_am_color_1fdb">#00001fdb</color>
+    <color name="i_am_color_1fdc">#00001fdc</color>
+    <color name="i_am_color_1fdd">#00001fdd</color>
+    <color name="i_am_color_1fde">#00001fde</color>
+    <color name="i_am_color_1fdf">#00001fdf</color>
+    <color name="i_am_color_1fe0">#00001fe0</color>
+    <color name="i_am_color_1fe1">#00001fe1</color>
+    <color name="i_am_color_1fe2">#00001fe2</color>
+    <color name="i_am_color_1fe3">#00001fe3</color>
+    <color name="i_am_color_1fe4">#00001fe4</color>
+    <color name="i_am_color_1fe5">#00001fe5</color>
+    <color name="i_am_color_1fe6">#00001fe6</color>
+    <color name="i_am_color_1fe7">#00001fe7</color>
+    <color name="i_am_color_1fe8">#00001fe8</color>
+    <color name="i_am_color_1fe9">#00001fe9</color>
+    <color name="i_am_color_1fea">#00001fea</color>
+    <color name="i_am_color_1feb">#00001feb</color>
+    <color name="i_am_color_1fec">#00001fec</color>
+    <color name="i_am_color_1fed">#00001fed</color>
+    <color name="i_am_color_1fee">#00001fee</color>
+    <color name="i_am_color_1fef">#00001fef</color>
+    <color name="i_am_color_1ff0">#00001ff0</color>
+    <color name="i_am_color_1ff1">#00001ff1</color>
+    <color name="i_am_color_1ff2">#00001ff2</color>
+    <color name="i_am_color_1ff3">#00001ff3</color>
+    <color name="i_am_color_1ff4">#00001ff4</color>
+    <color name="i_am_color_1ff5">#00001ff5</color>
+    <color name="i_am_color_1ff6">#00001ff6</color>
+    <color name="i_am_color_1ff7">#00001ff7</color>
+    <color name="i_am_color_1ff8">#00001ff8</color>
+    <color name="i_am_color_1ff9">#00001ff9</color>
+    <color name="i_am_color_1ffa">#00001ffa</color>
+    <color name="i_am_color_1ffb">#00001ffb</color>
+    <color name="i_am_color_1ffc">#00001ffc</color>
+    <color name="i_am_color_1ffd">#00001ffd</color>
+    <color name="i_am_color_1ffe">#00001ffe</color>
+    <color name="i_am_color_1fff">#00001fff</color>
+    <color name="i_am_color_2000">#00002000</color>
+    <color name="i_am_color_2001">#00002001</color>
+    <color name="i_am_color_2002">#00002002</color>
+    <color name="i_am_color_2003">#00002003</color>
+    <color name="i_am_color_2004">#00002004</color>
+    <color name="i_am_color_2005">#00002005</color>
+    <color name="i_am_color_2006">#00002006</color>
+    <color name="i_am_color_2007">#00002007</color>
+    <color name="i_am_color_2008">#00002008</color>
+    <color name="i_am_color_2009">#00002009</color>
+    <color name="i_am_color_200a">#0000200a</color>
+    <color name="i_am_color_200b">#0000200b</color>
+    <color name="i_am_color_200c">#0000200c</color>
+    <color name="i_am_color_200d">#0000200d</color>
+    <color name="i_am_color_200e">#0000200e</color>
+    <color name="i_am_color_200f">#0000200f</color>
+    <color name="i_am_color_2010">#00002010</color>
+    <color name="i_am_color_2011">#00002011</color>
+    <color name="i_am_color_2012">#00002012</color>
+    <color name="i_am_color_2013">#00002013</color>
+    <color name="i_am_color_2014">#00002014</color>
+    <color name="i_am_color_2015">#00002015</color>
+    <color name="i_am_color_2016">#00002016</color>
+    <color name="i_am_color_2017">#00002017</color>
+    <color name="i_am_color_2018">#00002018</color>
+    <color name="i_am_color_2019">#00002019</color>
+    <color name="i_am_color_201a">#0000201a</color>
+    <color name="i_am_color_201b">#0000201b</color>
+    <color name="i_am_color_201c">#0000201c</color>
+    <color name="i_am_color_201d">#0000201d</color>
+    <color name="i_am_color_201e">#0000201e</color>
+    <color name="i_am_color_201f">#0000201f</color>
+    <color name="i_am_color_2020">#00002020</color>
+    <color name="i_am_color_2021">#00002021</color>
+    <color name="i_am_color_2022">#00002022</color>
+    <color name="i_am_color_2023">#00002023</color>
+    <color name="i_am_color_2024">#00002024</color>
+    <color name="i_am_color_2025">#00002025</color>
+    <color name="i_am_color_2026">#00002026</color>
+    <color name="i_am_color_2027">#00002027</color>
+    <color name="i_am_color_2028">#00002028</color>
+    <color name="i_am_color_2029">#00002029</color>
+    <color name="i_am_color_202a">#0000202a</color>
+    <color name="i_am_color_202b">#0000202b</color>
+    <color name="i_am_color_202c">#0000202c</color>
+    <color name="i_am_color_202d">#0000202d</color>
+    <color name="i_am_color_202e">#0000202e</color>
+    <color name="i_am_color_202f">#0000202f</color>
+    <color name="i_am_color_2030">#00002030</color>
+    <color name="i_am_color_2031">#00002031</color>
+    <color name="i_am_color_2032">#00002032</color>
+    <color name="i_am_color_2033">#00002033</color>
+    <color name="i_am_color_2034">#00002034</color>
+    <color name="i_am_color_2035">#00002035</color>
+    <color name="i_am_color_2036">#00002036</color>
+    <color name="i_am_color_2037">#00002037</color>
+    <color name="i_am_color_2038">#00002038</color>
+    <color name="i_am_color_2039">#00002039</color>
+    <color name="i_am_color_203a">#0000203a</color>
+    <color name="i_am_color_203b">#0000203b</color>
+    <color name="i_am_color_203c">#0000203c</color>
+    <color name="i_am_color_203d">#0000203d</color>
+    <color name="i_am_color_203e">#0000203e</color>
+    <color name="i_am_color_203f">#0000203f</color>
+    <color name="i_am_color_2040">#00002040</color>
+    <color name="i_am_color_2041">#00002041</color>
+    <color name="i_am_color_2042">#00002042</color>
+    <color name="i_am_color_2043">#00002043</color>
+    <color name="i_am_color_2044">#00002044</color>
+    <color name="i_am_color_2045">#00002045</color>
+    <color name="i_am_color_2046">#00002046</color>
+    <color name="i_am_color_2047">#00002047</color>
+    <color name="i_am_color_2048">#00002048</color>
+    <color name="i_am_color_2049">#00002049</color>
+    <color name="i_am_color_204a">#0000204a</color>
+    <color name="i_am_color_204b">#0000204b</color>
+    <color name="i_am_color_204c">#0000204c</color>
+    <color name="i_am_color_204d">#0000204d</color>
+    <color name="i_am_color_204e">#0000204e</color>
+    <color name="i_am_color_204f">#0000204f</color>
+    <color name="i_am_color_2050">#00002050</color>
+    <color name="i_am_color_2051">#00002051</color>
+    <color name="i_am_color_2052">#00002052</color>
+    <color name="i_am_color_2053">#00002053</color>
+    <color name="i_am_color_2054">#00002054</color>
+    <color name="i_am_color_2055">#00002055</color>
+    <color name="i_am_color_2056">#00002056</color>
+    <color name="i_am_color_2057">#00002057</color>
+    <color name="i_am_color_2058">#00002058</color>
+    <color name="i_am_color_2059">#00002059</color>
+    <color name="i_am_color_205a">#0000205a</color>
+    <color name="i_am_color_205b">#0000205b</color>
+    <color name="i_am_color_205c">#0000205c</color>
+    <color name="i_am_color_205d">#0000205d</color>
+    <color name="i_am_color_205e">#0000205e</color>
+    <color name="i_am_color_205f">#0000205f</color>
+    <color name="i_am_color_2060">#00002060</color>
+    <color name="i_am_color_2061">#00002061</color>
+    <color name="i_am_color_2062">#00002062</color>
+    <color name="i_am_color_2063">#00002063</color>
+    <color name="i_am_color_2064">#00002064</color>
+    <color name="i_am_color_2065">#00002065</color>
+    <color name="i_am_color_2066">#00002066</color>
+    <color name="i_am_color_2067">#00002067</color>
+    <color name="i_am_color_2068">#00002068</color>
+    <color name="i_am_color_2069">#00002069</color>
+    <color name="i_am_color_206a">#0000206a</color>
+    <color name="i_am_color_206b">#0000206b</color>
+    <color name="i_am_color_206c">#0000206c</color>
+    <color name="i_am_color_206d">#0000206d</color>
+    <color name="i_am_color_206e">#0000206e</color>
+    <color name="i_am_color_206f">#0000206f</color>
+    <color name="i_am_color_2070">#00002070</color>
+    <color name="i_am_color_2071">#00002071</color>
+    <color name="i_am_color_2072">#00002072</color>
+    <color name="i_am_color_2073">#00002073</color>
+    <color name="i_am_color_2074">#00002074</color>
+    <color name="i_am_color_2075">#00002075</color>
+    <color name="i_am_color_2076">#00002076</color>
+    <color name="i_am_color_2077">#00002077</color>
+    <color name="i_am_color_2078">#00002078</color>
+    <color name="i_am_color_2079">#00002079</color>
+    <color name="i_am_color_207a">#0000207a</color>
+    <color name="i_am_color_207b">#0000207b</color>
+    <color name="i_am_color_207c">#0000207c</color>
+    <color name="i_am_color_207d">#0000207d</color>
+    <color name="i_am_color_207e">#0000207e</color>
+    <color name="i_am_color_207f">#0000207f</color>
+    <color name="i_am_color_2080">#00002080</color>
+    <color name="i_am_color_2081">#00002081</color>
+    <color name="i_am_color_2082">#00002082</color>
+    <color name="i_am_color_2083">#00002083</color>
+    <color name="i_am_color_2084">#00002084</color>
+    <color name="i_am_color_2085">#00002085</color>
+    <color name="i_am_color_2086">#00002086</color>
+    <color name="i_am_color_2087">#00002087</color>
+    <color name="i_am_color_2088">#00002088</color>
+    <color name="i_am_color_2089">#00002089</color>
+    <color name="i_am_color_208a">#0000208a</color>
+    <color name="i_am_color_208b">#0000208b</color>
+    <color name="i_am_color_208c">#0000208c</color>
+    <color name="i_am_color_208d">#0000208d</color>
+    <color name="i_am_color_208e">#0000208e</color>
+    <color name="i_am_color_208f">#0000208f</color>
+    <color name="i_am_color_2090">#00002090</color>
+    <color name="i_am_color_2091">#00002091</color>
+    <color name="i_am_color_2092">#00002092</color>
+    <color name="i_am_color_2093">#00002093</color>
+    <color name="i_am_color_2094">#00002094</color>
+    <color name="i_am_color_2095">#00002095</color>
+    <color name="i_am_color_2096">#00002096</color>
+    <color name="i_am_color_2097">#00002097</color>
+    <color name="i_am_color_2098">#00002098</color>
+    <color name="i_am_color_2099">#00002099</color>
+    <color name="i_am_color_209a">#0000209a</color>
+    <color name="i_am_color_209b">#0000209b</color>
+    <color name="i_am_color_209c">#0000209c</color>
+    <color name="i_am_color_209d">#0000209d</color>
+    <color name="i_am_color_209e">#0000209e</color>
+    <color name="i_am_color_209f">#0000209f</color>
+    <color name="i_am_color_20a0">#000020a0</color>
+    <color name="i_am_color_20a1">#000020a1</color>
+    <color name="i_am_color_20a2">#000020a2</color>
+    <color name="i_am_color_20a3">#000020a3</color>
+    <color name="i_am_color_20a4">#000020a4</color>
+    <color name="i_am_color_20a5">#000020a5</color>
+    <color name="i_am_color_20a6">#000020a6</color>
+    <color name="i_am_color_20a7">#000020a7</color>
+    <color name="i_am_color_20a8">#000020a8</color>
+    <color name="i_am_color_20a9">#000020a9</color>
+    <color name="i_am_color_20aa">#000020aa</color>
+    <color name="i_am_color_20ab">#000020ab</color>
+    <color name="i_am_color_20ac">#000020ac</color>
+    <color name="i_am_color_20ad">#000020ad</color>
+    <color name="i_am_color_20ae">#000020ae</color>
+    <color name="i_am_color_20af">#000020af</color>
+    <color name="i_am_color_20b0">#000020b0</color>
+    <color name="i_am_color_20b1">#000020b1</color>
+    <color name="i_am_color_20b2">#000020b2</color>
+    <color name="i_am_color_20b3">#000020b3</color>
+    <color name="i_am_color_20b4">#000020b4</color>
+    <color name="i_am_color_20b5">#000020b5</color>
+    <color name="i_am_color_20b6">#000020b6</color>
+    <color name="i_am_color_20b7">#000020b7</color>
+    <color name="i_am_color_20b8">#000020b8</color>
+    <color name="i_am_color_20b9">#000020b9</color>
+    <color name="i_am_color_20ba">#000020ba</color>
+    <color name="i_am_color_20bb">#000020bb</color>
+    <color name="i_am_color_20bc">#000020bc</color>
+    <color name="i_am_color_20bd">#000020bd</color>
+    <color name="i_am_color_20be">#000020be</color>
+    <color name="i_am_color_20bf">#000020bf</color>
+    <color name="i_am_color_20c0">#000020c0</color>
+    <color name="i_am_color_20c1">#000020c1</color>
+    <color name="i_am_color_20c2">#000020c2</color>
+    <color name="i_am_color_20c3">#000020c3</color>
+    <color name="i_am_color_20c4">#000020c4</color>
+    <color name="i_am_color_20c5">#000020c5</color>
+    <color name="i_am_color_20c6">#000020c6</color>
+    <color name="i_am_color_20c7">#000020c7</color>
+    <color name="i_am_color_20c8">#000020c8</color>
+    <color name="i_am_color_20c9">#000020c9</color>
+    <color name="i_am_color_20ca">#000020ca</color>
+    <color name="i_am_color_20cb">#000020cb</color>
+    <color name="i_am_color_20cc">#000020cc</color>
+    <color name="i_am_color_20cd">#000020cd</color>
+    <color name="i_am_color_20ce">#000020ce</color>
+    <color name="i_am_color_20cf">#000020cf</color>
+    <color name="i_am_color_20d0">#000020d0</color>
+    <color name="i_am_color_20d1">#000020d1</color>
+    <color name="i_am_color_20d2">#000020d2</color>
+    <color name="i_am_color_20d3">#000020d3</color>
+    <color name="i_am_color_20d4">#000020d4</color>
+    <color name="i_am_color_20d5">#000020d5</color>
+    <color name="i_am_color_20d6">#000020d6</color>
+    <color name="i_am_color_20d7">#000020d7</color>
+    <color name="i_am_color_20d8">#000020d8</color>
+    <color name="i_am_color_20d9">#000020d9</color>
+    <color name="i_am_color_20da">#000020da</color>
+    <color name="i_am_color_20db">#000020db</color>
+    <color name="i_am_color_20dc">#000020dc</color>
+    <color name="i_am_color_20dd">#000020dd</color>
+    <color name="i_am_color_20de">#000020de</color>
+    <color name="i_am_color_20df">#000020df</color>
+    <color name="i_am_color_20e0">#000020e0</color>
+    <color name="i_am_color_20e1">#000020e1</color>
+    <color name="i_am_color_20e2">#000020e2</color>
+    <color name="i_am_color_20e3">#000020e3</color>
+    <color name="i_am_color_20e4">#000020e4</color>
+    <color name="i_am_color_20e5">#000020e5</color>
+    <color name="i_am_color_20e6">#000020e6</color>
+    <color name="i_am_color_20e7">#000020e7</color>
+    <color name="i_am_color_20e8">#000020e8</color>
+    <color name="i_am_color_20e9">#000020e9</color>
+    <color name="i_am_color_20ea">#000020ea</color>
+    <color name="i_am_color_20eb">#000020eb</color>
+    <color name="i_am_color_20ec">#000020ec</color>
+    <color name="i_am_color_20ed">#000020ed</color>
+    <color name="i_am_color_20ee">#000020ee</color>
+    <color name="i_am_color_20ef">#000020ef</color>
+    <color name="i_am_color_20f0">#000020f0</color>
+    <color name="i_am_color_20f1">#000020f1</color>
+    <color name="i_am_color_20f2">#000020f2</color>
+    <color name="i_am_color_20f3">#000020f3</color>
+    <color name="i_am_color_20f4">#000020f4</color>
+    <color name="i_am_color_20f5">#000020f5</color>
+    <color name="i_am_color_20f6">#000020f6</color>
+    <color name="i_am_color_20f7">#000020f7</color>
+    <color name="i_am_color_20f8">#000020f8</color>
+    <color name="i_am_color_20f9">#000020f9</color>
+    <color name="i_am_color_20fa">#000020fa</color>
+    <color name="i_am_color_20fb">#000020fb</color>
+    <color name="i_am_color_20fc">#000020fc</color>
+    <color name="i_am_color_20fd">#000020fd</color>
+    <color name="i_am_color_20fe">#000020fe</color>
+    <color name="i_am_color_20ff">#000020ff</color>
+    <color name="i_am_color_2100">#00002100</color>
+    <color name="i_am_color_2101">#00002101</color>
+    <color name="i_am_color_2102">#00002102</color>
+    <color name="i_am_color_2103">#00002103</color>
+    <color name="i_am_color_2104">#00002104</color>
+    <color name="i_am_color_2105">#00002105</color>
+    <color name="i_am_color_2106">#00002106</color>
+    <color name="i_am_color_2107">#00002107</color>
+    <color name="i_am_color_2108">#00002108</color>
+    <color name="i_am_color_2109">#00002109</color>
+    <color name="i_am_color_210a">#0000210a</color>
+    <color name="i_am_color_210b">#0000210b</color>
+    <color name="i_am_color_210c">#0000210c</color>
+    <color name="i_am_color_210d">#0000210d</color>
+    <color name="i_am_color_210e">#0000210e</color>
+    <color name="i_am_color_210f">#0000210f</color>
+    <color name="i_am_color_2110">#00002110</color>
+    <color name="i_am_color_2111">#00002111</color>
+    <color name="i_am_color_2112">#00002112</color>
+    <color name="i_am_color_2113">#00002113</color>
+    <color name="i_am_color_2114">#00002114</color>
+    <color name="i_am_color_2115">#00002115</color>
+    <color name="i_am_color_2116">#00002116</color>
+    <color name="i_am_color_2117">#00002117</color>
+    <color name="i_am_color_2118">#00002118</color>
+    <color name="i_am_color_2119">#00002119</color>
+    <color name="i_am_color_211a">#0000211a</color>
+    <color name="i_am_color_211b">#0000211b</color>
+    <color name="i_am_color_211c">#0000211c</color>
+    <color name="i_am_color_211d">#0000211d</color>
+    <color name="i_am_color_211e">#0000211e</color>
+    <color name="i_am_color_211f">#0000211f</color>
+    <color name="i_am_color_2120">#00002120</color>
+    <color name="i_am_color_2121">#00002121</color>
+    <color name="i_am_color_2122">#00002122</color>
+    <color name="i_am_color_2123">#00002123</color>
+    <color name="i_am_color_2124">#00002124</color>
+    <color name="i_am_color_2125">#00002125</color>
+    <color name="i_am_color_2126">#00002126</color>
+    <color name="i_am_color_2127">#00002127</color>
+    <color name="i_am_color_2128">#00002128</color>
+    <color name="i_am_color_2129">#00002129</color>
+    <color name="i_am_color_212a">#0000212a</color>
+    <color name="i_am_color_212b">#0000212b</color>
+    <color name="i_am_color_212c">#0000212c</color>
+    <color name="i_am_color_212d">#0000212d</color>
+    <color name="i_am_color_212e">#0000212e</color>
+    <color name="i_am_color_212f">#0000212f</color>
+    <color name="i_am_color_2130">#00002130</color>
+    <color name="i_am_color_2131">#00002131</color>
+    <color name="i_am_color_2132">#00002132</color>
+    <color name="i_am_color_2133">#00002133</color>
+    <color name="i_am_color_2134">#00002134</color>
+    <color name="i_am_color_2135">#00002135</color>
+    <color name="i_am_color_2136">#00002136</color>
+    <color name="i_am_color_2137">#00002137</color>
+    <color name="i_am_color_2138">#00002138</color>
+    <color name="i_am_color_2139">#00002139</color>
+    <color name="i_am_color_213a">#0000213a</color>
+    <color name="i_am_color_213b">#0000213b</color>
+    <color name="i_am_color_213c">#0000213c</color>
+    <color name="i_am_color_213d">#0000213d</color>
+    <color name="i_am_color_213e">#0000213e</color>
+    <color name="i_am_color_213f">#0000213f</color>
+    <color name="i_am_color_2140">#00002140</color>
+    <color name="i_am_color_2141">#00002141</color>
+    <color name="i_am_color_2142">#00002142</color>
+    <color name="i_am_color_2143">#00002143</color>
+    <color name="i_am_color_2144">#00002144</color>
+    <color name="i_am_color_2145">#00002145</color>
+    <color name="i_am_color_2146">#00002146</color>
+    <color name="i_am_color_2147">#00002147</color>
+    <color name="i_am_color_2148">#00002148</color>
+    <color name="i_am_color_2149">#00002149</color>
+    <color name="i_am_color_214a">#0000214a</color>
+    <color name="i_am_color_214b">#0000214b</color>
+    <color name="i_am_color_214c">#0000214c</color>
+    <color name="i_am_color_214d">#0000214d</color>
+    <color name="i_am_color_214e">#0000214e</color>
+    <color name="i_am_color_214f">#0000214f</color>
+    <color name="i_am_color_2150">#00002150</color>
+    <color name="i_am_color_2151">#00002151</color>
+    <color name="i_am_color_2152">#00002152</color>
+    <color name="i_am_color_2153">#00002153</color>
+    <color name="i_am_color_2154">#00002154</color>
+    <color name="i_am_color_2155">#00002155</color>
+    <color name="i_am_color_2156">#00002156</color>
+    <color name="i_am_color_2157">#00002157</color>
+    <color name="i_am_color_2158">#00002158</color>
+    <color name="i_am_color_2159">#00002159</color>
+    <color name="i_am_color_215a">#0000215a</color>
+    <color name="i_am_color_215b">#0000215b</color>
+    <color name="i_am_color_215c">#0000215c</color>
+    <color name="i_am_color_215d">#0000215d</color>
+    <color name="i_am_color_215e">#0000215e</color>
+    <color name="i_am_color_215f">#0000215f</color>
+    <color name="i_am_color_2160">#00002160</color>
+    <color name="i_am_color_2161">#00002161</color>
+    <color name="i_am_color_2162">#00002162</color>
+    <color name="i_am_color_2163">#00002163</color>
+    <color name="i_am_color_2164">#00002164</color>
+    <color name="i_am_color_2165">#00002165</color>
+    <color name="i_am_color_2166">#00002166</color>
+    <color name="i_am_color_2167">#00002167</color>
+    <color name="i_am_color_2168">#00002168</color>
+    <color name="i_am_color_2169">#00002169</color>
+    <color name="i_am_color_216a">#0000216a</color>
+    <color name="i_am_color_216b">#0000216b</color>
+    <color name="i_am_color_216c">#0000216c</color>
+    <color name="i_am_color_216d">#0000216d</color>
+    <color name="i_am_color_216e">#0000216e</color>
+    <color name="i_am_color_216f">#0000216f</color>
+    <color name="i_am_color_2170">#00002170</color>
+    <color name="i_am_color_2171">#00002171</color>
+    <color name="i_am_color_2172">#00002172</color>
+    <color name="i_am_color_2173">#00002173</color>
+    <color name="i_am_color_2174">#00002174</color>
+    <color name="i_am_color_2175">#00002175</color>
+    <color name="i_am_color_2176">#00002176</color>
+    <color name="i_am_color_2177">#00002177</color>
+    <color name="i_am_color_2178">#00002178</color>
+    <color name="i_am_color_2179">#00002179</color>
+    <color name="i_am_color_217a">#0000217a</color>
+    <color name="i_am_color_217b">#0000217b</color>
+    <color name="i_am_color_217c">#0000217c</color>
+    <color name="i_am_color_217d">#0000217d</color>
+    <color name="i_am_color_217e">#0000217e</color>
+    <color name="i_am_color_217f">#0000217f</color>
+    <color name="i_am_color_2180">#00002180</color>
+    <color name="i_am_color_2181">#00002181</color>
+    <color name="i_am_color_2182">#00002182</color>
+    <color name="i_am_color_2183">#00002183</color>
+    <color name="i_am_color_2184">#00002184</color>
+    <color name="i_am_color_2185">#00002185</color>
+    <color name="i_am_color_2186">#00002186</color>
+    <color name="i_am_color_2187">#00002187</color>
+    <color name="i_am_color_2188">#00002188</color>
+    <color name="i_am_color_2189">#00002189</color>
+    <color name="i_am_color_218a">#0000218a</color>
+    <color name="i_am_color_218b">#0000218b</color>
+    <color name="i_am_color_218c">#0000218c</color>
+    <color name="i_am_color_218d">#0000218d</color>
+    <color name="i_am_color_218e">#0000218e</color>
+    <color name="i_am_color_218f">#0000218f</color>
+    <color name="i_am_color_2190">#00002190</color>
+    <color name="i_am_color_2191">#00002191</color>
+    <color name="i_am_color_2192">#00002192</color>
+    <color name="i_am_color_2193">#00002193</color>
+    <color name="i_am_color_2194">#00002194</color>
+    <color name="i_am_color_2195">#00002195</color>
+    <color name="i_am_color_2196">#00002196</color>
+    <color name="i_am_color_2197">#00002197</color>
+    <color name="i_am_color_2198">#00002198</color>
+    <color name="i_am_color_2199">#00002199</color>
+    <color name="i_am_color_219a">#0000219a</color>
+    <color name="i_am_color_219b">#0000219b</color>
+    <color name="i_am_color_219c">#0000219c</color>
+    <color name="i_am_color_219d">#0000219d</color>
+    <color name="i_am_color_219e">#0000219e</color>
+    <color name="i_am_color_219f">#0000219f</color>
+    <color name="i_am_color_21a0">#000021a0</color>
+    <color name="i_am_color_21a1">#000021a1</color>
+    <color name="i_am_color_21a2">#000021a2</color>
+    <color name="i_am_color_21a3">#000021a3</color>
+    <color name="i_am_color_21a4">#000021a4</color>
+    <color name="i_am_color_21a5">#000021a5</color>
+    <color name="i_am_color_21a6">#000021a6</color>
+    <color name="i_am_color_21a7">#000021a7</color>
+    <color name="i_am_color_21a8">#000021a8</color>
+    <color name="i_am_color_21a9">#000021a9</color>
+    <color name="i_am_color_21aa">#000021aa</color>
+    <color name="i_am_color_21ab">#000021ab</color>
+    <color name="i_am_color_21ac">#000021ac</color>
+    <color name="i_am_color_21ad">#000021ad</color>
+    <color name="i_am_color_21ae">#000021ae</color>
+    <color name="i_am_color_21af">#000021af</color>
+    <color name="i_am_color_21b0">#000021b0</color>
+    <color name="i_am_color_21b1">#000021b1</color>
+    <color name="i_am_color_21b2">#000021b2</color>
+    <color name="i_am_color_21b3">#000021b3</color>
+    <color name="i_am_color_21b4">#000021b4</color>
+    <color name="i_am_color_21b5">#000021b5</color>
+    <color name="i_am_color_21b6">#000021b6</color>
+    <color name="i_am_color_21b7">#000021b7</color>
+    <color name="i_am_color_21b8">#000021b8</color>
+    <color name="i_am_color_21b9">#000021b9</color>
+    <color name="i_am_color_21ba">#000021ba</color>
+    <color name="i_am_color_21bb">#000021bb</color>
+    <color name="i_am_color_21bc">#000021bc</color>
+    <color name="i_am_color_21bd">#000021bd</color>
+    <color name="i_am_color_21be">#000021be</color>
+    <color name="i_am_color_21bf">#000021bf</color>
+    <color name="i_am_color_21c0">#000021c0</color>
+    <color name="i_am_color_21c1">#000021c1</color>
+    <color name="i_am_color_21c2">#000021c2</color>
+    <color name="i_am_color_21c3">#000021c3</color>
+    <color name="i_am_color_21c4">#000021c4</color>
+    <color name="i_am_color_21c5">#000021c5</color>
+    <color name="i_am_color_21c6">#000021c6</color>
+    <color name="i_am_color_21c7">#000021c7</color>
+    <color name="i_am_color_21c8">#000021c8</color>
+    <color name="i_am_color_21c9">#000021c9</color>
+    <color name="i_am_color_21ca">#000021ca</color>
+    <color name="i_am_color_21cb">#000021cb</color>
+    <color name="i_am_color_21cc">#000021cc</color>
+    <color name="i_am_color_21cd">#000021cd</color>
+    <color name="i_am_color_21ce">#000021ce</color>
+    <color name="i_am_color_21cf">#000021cf</color>
+    <color name="i_am_color_21d0">#000021d0</color>
+    <color name="i_am_color_21d1">#000021d1</color>
+    <color name="i_am_color_21d2">#000021d2</color>
+    <color name="i_am_color_21d3">#000021d3</color>
+    <color name="i_am_color_21d4">#000021d4</color>
+    <color name="i_am_color_21d5">#000021d5</color>
+    <color name="i_am_color_21d6">#000021d6</color>
+    <color name="i_am_color_21d7">#000021d7</color>
+    <color name="i_am_color_21d8">#000021d8</color>
+    <color name="i_am_color_21d9">#000021d9</color>
+    <color name="i_am_color_21da">#000021da</color>
+    <color name="i_am_color_21db">#000021db</color>
+    <color name="i_am_color_21dc">#000021dc</color>
+    <color name="i_am_color_21dd">#000021dd</color>
+    <color name="i_am_color_21de">#000021de</color>
+    <color name="i_am_color_21df">#000021df</color>
+    <color name="i_am_color_21e0">#000021e0</color>
+    <color name="i_am_color_21e1">#000021e1</color>
+    <color name="i_am_color_21e2">#000021e2</color>
+    <color name="i_am_color_21e3">#000021e3</color>
+    <color name="i_am_color_21e4">#000021e4</color>
+    <color name="i_am_color_21e5">#000021e5</color>
+    <color name="i_am_color_21e6">#000021e6</color>
+    <color name="i_am_color_21e7">#000021e7</color>
+    <color name="i_am_color_21e8">#000021e8</color>
+    <color name="i_am_color_21e9">#000021e9</color>
+    <color name="i_am_color_21ea">#000021ea</color>
+    <color name="i_am_color_21eb">#000021eb</color>
+    <color name="i_am_color_21ec">#000021ec</color>
+    <color name="i_am_color_21ed">#000021ed</color>
+    <color name="i_am_color_21ee">#000021ee</color>
+    <color name="i_am_color_21ef">#000021ef</color>
+    <color name="i_am_color_21f0">#000021f0</color>
+    <color name="i_am_color_21f1">#000021f1</color>
+    <color name="i_am_color_21f2">#000021f2</color>
+    <color name="i_am_color_21f3">#000021f3</color>
+    <color name="i_am_color_21f4">#000021f4</color>
+    <color name="i_am_color_21f5">#000021f5</color>
+    <color name="i_am_color_21f6">#000021f6</color>
+    <color name="i_am_color_21f7">#000021f7</color>
+    <color name="i_am_color_21f8">#000021f8</color>
+    <color name="i_am_color_21f9">#000021f9</color>
+    <color name="i_am_color_21fa">#000021fa</color>
+    <color name="i_am_color_21fb">#000021fb</color>
+    <color name="i_am_color_21fc">#000021fc</color>
+    <color name="i_am_color_21fd">#000021fd</color>
+    <color name="i_am_color_21fe">#000021fe</color>
+    <color name="i_am_color_21ff">#000021ff</color>
+    <color name="i_am_color_2200">#00002200</color>
+    <color name="i_am_color_2201">#00002201</color>
+    <color name="i_am_color_2202">#00002202</color>
+    <color name="i_am_color_2203">#00002203</color>
+    <color name="i_am_color_2204">#00002204</color>
+    <color name="i_am_color_2205">#00002205</color>
+    <color name="i_am_color_2206">#00002206</color>
+    <color name="i_am_color_2207">#00002207</color>
+    <color name="i_am_color_2208">#00002208</color>
+    <color name="i_am_color_2209">#00002209</color>
+    <color name="i_am_color_220a">#0000220a</color>
+    <color name="i_am_color_220b">#0000220b</color>
+    <color name="i_am_color_220c">#0000220c</color>
+    <color name="i_am_color_220d">#0000220d</color>
+    <color name="i_am_color_220e">#0000220e</color>
+    <color name="i_am_color_220f">#0000220f</color>
+    <color name="i_am_color_2210">#00002210</color>
+    <color name="i_am_color_2211">#00002211</color>
+    <color name="i_am_color_2212">#00002212</color>
+    <color name="i_am_color_2213">#00002213</color>
+    <color name="i_am_color_2214">#00002214</color>
+    <color name="i_am_color_2215">#00002215</color>
+    <color name="i_am_color_2216">#00002216</color>
+    <color name="i_am_color_2217">#00002217</color>
+    <color name="i_am_color_2218">#00002218</color>
+    <color name="i_am_color_2219">#00002219</color>
+    <color name="i_am_color_221a">#0000221a</color>
+    <color name="i_am_color_221b">#0000221b</color>
+    <color name="i_am_color_221c">#0000221c</color>
+    <color name="i_am_color_221d">#0000221d</color>
+    <color name="i_am_color_221e">#0000221e</color>
+    <color name="i_am_color_221f">#0000221f</color>
+    <color name="i_am_color_2220">#00002220</color>
+    <color name="i_am_color_2221">#00002221</color>
+    <color name="i_am_color_2222">#00002222</color>
+    <color name="i_am_color_2223">#00002223</color>
+    <color name="i_am_color_2224">#00002224</color>
+    <color name="i_am_color_2225">#00002225</color>
+    <color name="i_am_color_2226">#00002226</color>
+    <color name="i_am_color_2227">#00002227</color>
+    <color name="i_am_color_2228">#00002228</color>
+    <color name="i_am_color_2229">#00002229</color>
+    <color name="i_am_color_222a">#0000222a</color>
+    <color name="i_am_color_222b">#0000222b</color>
+    <color name="i_am_color_222c">#0000222c</color>
+    <color name="i_am_color_222d">#0000222d</color>
+    <color name="i_am_color_222e">#0000222e</color>
+    <color name="i_am_color_222f">#0000222f</color>
+    <color name="i_am_color_2230">#00002230</color>
+    <color name="i_am_color_2231">#00002231</color>
+    <color name="i_am_color_2232">#00002232</color>
+    <color name="i_am_color_2233">#00002233</color>
+    <color name="i_am_color_2234">#00002234</color>
+    <color name="i_am_color_2235">#00002235</color>
+    <color name="i_am_color_2236">#00002236</color>
+    <color name="i_am_color_2237">#00002237</color>
+    <color name="i_am_color_2238">#00002238</color>
+    <color name="i_am_color_2239">#00002239</color>
+    <color name="i_am_color_223a">#0000223a</color>
+    <color name="i_am_color_223b">#0000223b</color>
+    <color name="i_am_color_223c">#0000223c</color>
+    <color name="i_am_color_223d">#0000223d</color>
+    <color name="i_am_color_223e">#0000223e</color>
+    <color name="i_am_color_223f">#0000223f</color>
+    <color name="i_am_color_2240">#00002240</color>
+    <color name="i_am_color_2241">#00002241</color>
+    <color name="i_am_color_2242">#00002242</color>
+    <color name="i_am_color_2243">#00002243</color>
+    <color name="i_am_color_2244">#00002244</color>
+    <color name="i_am_color_2245">#00002245</color>
+    <color name="i_am_color_2246">#00002246</color>
+    <color name="i_am_color_2247">#00002247</color>
+    <color name="i_am_color_2248">#00002248</color>
+    <color name="i_am_color_2249">#00002249</color>
+    <color name="i_am_color_224a">#0000224a</color>
+    <color name="i_am_color_224b">#0000224b</color>
+    <color name="i_am_color_224c">#0000224c</color>
+    <color name="i_am_color_224d">#0000224d</color>
+    <color name="i_am_color_224e">#0000224e</color>
+    <color name="i_am_color_224f">#0000224f</color>
+    <color name="i_am_color_2250">#00002250</color>
+    <color name="i_am_color_2251">#00002251</color>
+    <color name="i_am_color_2252">#00002252</color>
+    <color name="i_am_color_2253">#00002253</color>
+    <color name="i_am_color_2254">#00002254</color>
+    <color name="i_am_color_2255">#00002255</color>
+    <color name="i_am_color_2256">#00002256</color>
+    <color name="i_am_color_2257">#00002257</color>
+    <color name="i_am_color_2258">#00002258</color>
+    <color name="i_am_color_2259">#00002259</color>
+    <color name="i_am_color_225a">#0000225a</color>
+    <color name="i_am_color_225b">#0000225b</color>
+    <color name="i_am_color_225c">#0000225c</color>
+    <color name="i_am_color_225d">#0000225d</color>
+    <color name="i_am_color_225e">#0000225e</color>
+    <color name="i_am_color_225f">#0000225f</color>
+    <color name="i_am_color_2260">#00002260</color>
+    <color name="i_am_color_2261">#00002261</color>
+    <color name="i_am_color_2262">#00002262</color>
+    <color name="i_am_color_2263">#00002263</color>
+    <color name="i_am_color_2264">#00002264</color>
+    <color name="i_am_color_2265">#00002265</color>
+    <color name="i_am_color_2266">#00002266</color>
+    <color name="i_am_color_2267">#00002267</color>
+    <color name="i_am_color_2268">#00002268</color>
+    <color name="i_am_color_2269">#00002269</color>
+    <color name="i_am_color_226a">#0000226a</color>
+    <color name="i_am_color_226b">#0000226b</color>
+    <color name="i_am_color_226c">#0000226c</color>
+    <color name="i_am_color_226d">#0000226d</color>
+    <color name="i_am_color_226e">#0000226e</color>
+    <color name="i_am_color_226f">#0000226f</color>
+    <color name="i_am_color_2270">#00002270</color>
+    <color name="i_am_color_2271">#00002271</color>
+    <color name="i_am_color_2272">#00002272</color>
+    <color name="i_am_color_2273">#00002273</color>
+    <color name="i_am_color_2274">#00002274</color>
+    <color name="i_am_color_2275">#00002275</color>
+    <color name="i_am_color_2276">#00002276</color>
+    <color name="i_am_color_2277">#00002277</color>
+    <color name="i_am_color_2278">#00002278</color>
+    <color name="i_am_color_2279">#00002279</color>
+    <color name="i_am_color_227a">#0000227a</color>
+    <color name="i_am_color_227b">#0000227b</color>
+    <color name="i_am_color_227c">#0000227c</color>
+    <color name="i_am_color_227d">#0000227d</color>
+    <color name="i_am_color_227e">#0000227e</color>
+    <color name="i_am_color_227f">#0000227f</color>
+    <color name="i_am_color_2280">#00002280</color>
+    <color name="i_am_color_2281">#00002281</color>
+    <color name="i_am_color_2282">#00002282</color>
+    <color name="i_am_color_2283">#00002283</color>
+    <color name="i_am_color_2284">#00002284</color>
+    <color name="i_am_color_2285">#00002285</color>
+    <color name="i_am_color_2286">#00002286</color>
+    <color name="i_am_color_2287">#00002287</color>
+    <color name="i_am_color_2288">#00002288</color>
+    <color name="i_am_color_2289">#00002289</color>
+    <color name="i_am_color_228a">#0000228a</color>
+    <color name="i_am_color_228b">#0000228b</color>
+    <color name="i_am_color_228c">#0000228c</color>
+    <color name="i_am_color_228d">#0000228d</color>
+    <color name="i_am_color_228e">#0000228e</color>
+    <color name="i_am_color_228f">#0000228f</color>
+    <color name="i_am_color_2290">#00002290</color>
+    <color name="i_am_color_2291">#00002291</color>
+    <color name="i_am_color_2292">#00002292</color>
+    <color name="i_am_color_2293">#00002293</color>
+    <color name="i_am_color_2294">#00002294</color>
+    <color name="i_am_color_2295">#00002295</color>
+    <color name="i_am_color_2296">#00002296</color>
+    <color name="i_am_color_2297">#00002297</color>
+    <color name="i_am_color_2298">#00002298</color>
+    <color name="i_am_color_2299">#00002299</color>
+    <color name="i_am_color_229a">#0000229a</color>
+    <color name="i_am_color_229b">#0000229b</color>
+    <color name="i_am_color_229c">#0000229c</color>
+    <color name="i_am_color_229d">#0000229d</color>
+    <color name="i_am_color_229e">#0000229e</color>
+    <color name="i_am_color_229f">#0000229f</color>
+    <color name="i_am_color_22a0">#000022a0</color>
+    <color name="i_am_color_22a1">#000022a1</color>
+    <color name="i_am_color_22a2">#000022a2</color>
+    <color name="i_am_color_22a3">#000022a3</color>
+    <color name="i_am_color_22a4">#000022a4</color>
+    <color name="i_am_color_22a5">#000022a5</color>
+    <color name="i_am_color_22a6">#000022a6</color>
+    <color name="i_am_color_22a7">#000022a7</color>
+    <color name="i_am_color_22a8">#000022a8</color>
+    <color name="i_am_color_22a9">#000022a9</color>
+    <color name="i_am_color_22aa">#000022aa</color>
+    <color name="i_am_color_22ab">#000022ab</color>
+    <color name="i_am_color_22ac">#000022ac</color>
+    <color name="i_am_color_22ad">#000022ad</color>
+    <color name="i_am_color_22ae">#000022ae</color>
+    <color name="i_am_color_22af">#000022af</color>
+    <color name="i_am_color_22b0">#000022b0</color>
+    <color name="i_am_color_22b1">#000022b1</color>
+    <color name="i_am_color_22b2">#000022b2</color>
+    <color name="i_am_color_22b3">#000022b3</color>
+    <color name="i_am_color_22b4">#000022b4</color>
+    <color name="i_am_color_22b5">#000022b5</color>
+    <color name="i_am_color_22b6">#000022b6</color>
+    <color name="i_am_color_22b7">#000022b7</color>
+    <color name="i_am_color_22b8">#000022b8</color>
+    <color name="i_am_color_22b9">#000022b9</color>
+    <color name="i_am_color_22ba">#000022ba</color>
+    <color name="i_am_color_22bb">#000022bb</color>
+    <color name="i_am_color_22bc">#000022bc</color>
+    <color name="i_am_color_22bd">#000022bd</color>
+    <color name="i_am_color_22be">#000022be</color>
+    <color name="i_am_color_22bf">#000022bf</color>
+    <color name="i_am_color_22c0">#000022c0</color>
+    <color name="i_am_color_22c1">#000022c1</color>
+    <color name="i_am_color_22c2">#000022c2</color>
+    <color name="i_am_color_22c3">#000022c3</color>
+    <color name="i_am_color_22c4">#000022c4</color>
+    <color name="i_am_color_22c5">#000022c5</color>
+    <color name="i_am_color_22c6">#000022c6</color>
+    <color name="i_am_color_22c7">#000022c7</color>
+    <color name="i_am_color_22c8">#000022c8</color>
+    <color name="i_am_color_22c9">#000022c9</color>
+    <color name="i_am_color_22ca">#000022ca</color>
+    <color name="i_am_color_22cb">#000022cb</color>
+    <color name="i_am_color_22cc">#000022cc</color>
+    <color name="i_am_color_22cd">#000022cd</color>
+    <color name="i_am_color_22ce">#000022ce</color>
+    <color name="i_am_color_22cf">#000022cf</color>
+    <color name="i_am_color_22d0">#000022d0</color>
+    <color name="i_am_color_22d1">#000022d1</color>
+    <color name="i_am_color_22d2">#000022d2</color>
+    <color name="i_am_color_22d3">#000022d3</color>
+    <color name="i_am_color_22d4">#000022d4</color>
+    <color name="i_am_color_22d5">#000022d5</color>
+    <color name="i_am_color_22d6">#000022d6</color>
+    <color name="i_am_color_22d7">#000022d7</color>
+    <color name="i_am_color_22d8">#000022d8</color>
+    <color name="i_am_color_22d9">#000022d9</color>
+    <color name="i_am_color_22da">#000022da</color>
+    <color name="i_am_color_22db">#000022db</color>
+    <color name="i_am_color_22dc">#000022dc</color>
+    <color name="i_am_color_22dd">#000022dd</color>
+    <color name="i_am_color_22de">#000022de</color>
+    <color name="i_am_color_22df">#000022df</color>
+    <color name="i_am_color_22e0">#000022e0</color>
+    <color name="i_am_color_22e1">#000022e1</color>
+    <color name="i_am_color_22e2">#000022e2</color>
+    <color name="i_am_color_22e3">#000022e3</color>
+    <color name="i_am_color_22e4">#000022e4</color>
+    <color name="i_am_color_22e5">#000022e5</color>
+    <color name="i_am_color_22e6">#000022e6</color>
+    <color name="i_am_color_22e7">#000022e7</color>
+    <color name="i_am_color_22e8">#000022e8</color>
+    <color name="i_am_color_22e9">#000022e9</color>
+    <color name="i_am_color_22ea">#000022ea</color>
+    <color name="i_am_color_22eb">#000022eb</color>
+    <color name="i_am_color_22ec">#000022ec</color>
+    <color name="i_am_color_22ed">#000022ed</color>
+    <color name="i_am_color_22ee">#000022ee</color>
+    <color name="i_am_color_22ef">#000022ef</color>
+    <color name="i_am_color_22f0">#000022f0</color>
+    <color name="i_am_color_22f1">#000022f1</color>
+    <color name="i_am_color_22f2">#000022f2</color>
+    <color name="i_am_color_22f3">#000022f3</color>
+    <color name="i_am_color_22f4">#000022f4</color>
+    <color name="i_am_color_22f5">#000022f5</color>
+    <color name="i_am_color_22f6">#000022f6</color>
+    <color name="i_am_color_22f7">#000022f7</color>
+    <color name="i_am_color_22f8">#000022f8</color>
+    <color name="i_am_color_22f9">#000022f9</color>
+    <color name="i_am_color_22fa">#000022fa</color>
+    <color name="i_am_color_22fb">#000022fb</color>
+    <color name="i_am_color_22fc">#000022fc</color>
+    <color name="i_am_color_22fd">#000022fd</color>
+    <color name="i_am_color_22fe">#000022fe</color>
+    <color name="i_am_color_22ff">#000022ff</color>
+    <color name="i_am_color_2300">#00002300</color>
+    <color name="i_am_color_2301">#00002301</color>
+    <color name="i_am_color_2302">#00002302</color>
+    <color name="i_am_color_2303">#00002303</color>
+    <color name="i_am_color_2304">#00002304</color>
+    <color name="i_am_color_2305">#00002305</color>
+    <color name="i_am_color_2306">#00002306</color>
+    <color name="i_am_color_2307">#00002307</color>
+    <color name="i_am_color_2308">#00002308</color>
+    <color name="i_am_color_2309">#00002309</color>
+    <color name="i_am_color_230a">#0000230a</color>
+    <color name="i_am_color_230b">#0000230b</color>
+    <color name="i_am_color_230c">#0000230c</color>
+    <color name="i_am_color_230d">#0000230d</color>
+    <color name="i_am_color_230e">#0000230e</color>
+    <color name="i_am_color_230f">#0000230f</color>
+    <color name="i_am_color_2310">#00002310</color>
+    <color name="i_am_color_2311">#00002311</color>
+    <color name="i_am_color_2312">#00002312</color>
+    <color name="i_am_color_2313">#00002313</color>
+    <color name="i_am_color_2314">#00002314</color>
+    <color name="i_am_color_2315">#00002315</color>
+    <color name="i_am_color_2316">#00002316</color>
+    <color name="i_am_color_2317">#00002317</color>
+    <color name="i_am_color_2318">#00002318</color>
+    <color name="i_am_color_2319">#00002319</color>
+    <color name="i_am_color_231a">#0000231a</color>
+    <color name="i_am_color_231b">#0000231b</color>
+    <color name="i_am_color_231c">#0000231c</color>
+    <color name="i_am_color_231d">#0000231d</color>
+    <color name="i_am_color_231e">#0000231e</color>
+    <color name="i_am_color_231f">#0000231f</color>
+    <color name="i_am_color_2320">#00002320</color>
+    <color name="i_am_color_2321">#00002321</color>
+    <color name="i_am_color_2322">#00002322</color>
+    <color name="i_am_color_2323">#00002323</color>
+    <color name="i_am_color_2324">#00002324</color>
+    <color name="i_am_color_2325">#00002325</color>
+    <color name="i_am_color_2326">#00002326</color>
+    <color name="i_am_color_2327">#00002327</color>
+    <color name="i_am_color_2328">#00002328</color>
+    <color name="i_am_color_2329">#00002329</color>
+    <color name="i_am_color_232a">#0000232a</color>
+    <color name="i_am_color_232b">#0000232b</color>
+    <color name="i_am_color_232c">#0000232c</color>
+    <color name="i_am_color_232d">#0000232d</color>
+    <color name="i_am_color_232e">#0000232e</color>
+    <color name="i_am_color_232f">#0000232f</color>
+    <color name="i_am_color_2330">#00002330</color>
+    <color name="i_am_color_2331">#00002331</color>
+    <color name="i_am_color_2332">#00002332</color>
+    <color name="i_am_color_2333">#00002333</color>
+    <color name="i_am_color_2334">#00002334</color>
+    <color name="i_am_color_2335">#00002335</color>
+    <color name="i_am_color_2336">#00002336</color>
+    <color name="i_am_color_2337">#00002337</color>
+    <color name="i_am_color_2338">#00002338</color>
+    <color name="i_am_color_2339">#00002339</color>
+    <color name="i_am_color_233a">#0000233a</color>
+    <color name="i_am_color_233b">#0000233b</color>
+    <color name="i_am_color_233c">#0000233c</color>
+    <color name="i_am_color_233d">#0000233d</color>
+    <color name="i_am_color_233e">#0000233e</color>
+    <color name="i_am_color_233f">#0000233f</color>
+    <color name="i_am_color_2340">#00002340</color>
+    <color name="i_am_color_2341">#00002341</color>
+    <color name="i_am_color_2342">#00002342</color>
+    <color name="i_am_color_2343">#00002343</color>
+    <color name="i_am_color_2344">#00002344</color>
+    <color name="i_am_color_2345">#00002345</color>
+    <color name="i_am_color_2346">#00002346</color>
+    <color name="i_am_color_2347">#00002347</color>
+    <color name="i_am_color_2348">#00002348</color>
+    <color name="i_am_color_2349">#00002349</color>
+    <color name="i_am_color_234a">#0000234a</color>
+    <color name="i_am_color_234b">#0000234b</color>
+    <color name="i_am_color_234c">#0000234c</color>
+    <color name="i_am_color_234d">#0000234d</color>
+    <color name="i_am_color_234e">#0000234e</color>
+    <color name="i_am_color_234f">#0000234f</color>
+    <color name="i_am_color_2350">#00002350</color>
+    <color name="i_am_color_2351">#00002351</color>
+    <color name="i_am_color_2352">#00002352</color>
+    <color name="i_am_color_2353">#00002353</color>
+    <color name="i_am_color_2354">#00002354</color>
+    <color name="i_am_color_2355">#00002355</color>
+    <color name="i_am_color_2356">#00002356</color>
+    <color name="i_am_color_2357">#00002357</color>
+    <color name="i_am_color_2358">#00002358</color>
+    <color name="i_am_color_2359">#00002359</color>
+    <color name="i_am_color_235a">#0000235a</color>
+    <color name="i_am_color_235b">#0000235b</color>
+    <color name="i_am_color_235c">#0000235c</color>
+    <color name="i_am_color_235d">#0000235d</color>
+    <color name="i_am_color_235e">#0000235e</color>
+    <color name="i_am_color_235f">#0000235f</color>
+    <color name="i_am_color_2360">#00002360</color>
+    <color name="i_am_color_2361">#00002361</color>
+    <color name="i_am_color_2362">#00002362</color>
+    <color name="i_am_color_2363">#00002363</color>
+    <color name="i_am_color_2364">#00002364</color>
+    <color name="i_am_color_2365">#00002365</color>
+    <color name="i_am_color_2366">#00002366</color>
+    <color name="i_am_color_2367">#00002367</color>
+    <color name="i_am_color_2368">#00002368</color>
+    <color name="i_am_color_2369">#00002369</color>
+    <color name="i_am_color_236a">#0000236a</color>
+    <color name="i_am_color_236b">#0000236b</color>
+    <color name="i_am_color_236c">#0000236c</color>
+    <color name="i_am_color_236d">#0000236d</color>
+    <color name="i_am_color_236e">#0000236e</color>
+    <color name="i_am_color_236f">#0000236f</color>
+    <color name="i_am_color_2370">#00002370</color>
+    <color name="i_am_color_2371">#00002371</color>
+    <color name="i_am_color_2372">#00002372</color>
+    <color name="i_am_color_2373">#00002373</color>
+    <color name="i_am_color_2374">#00002374</color>
+    <color name="i_am_color_2375">#00002375</color>
+    <color name="i_am_color_2376">#00002376</color>
+    <color name="i_am_color_2377">#00002377</color>
+    <color name="i_am_color_2378">#00002378</color>
+    <color name="i_am_color_2379">#00002379</color>
+    <color name="i_am_color_237a">#0000237a</color>
+    <color name="i_am_color_237b">#0000237b</color>
+    <color name="i_am_color_237c">#0000237c</color>
+    <color name="i_am_color_237d">#0000237d</color>
+    <color name="i_am_color_237e">#0000237e</color>
+    <color name="i_am_color_237f">#0000237f</color>
+    <color name="i_am_color_2380">#00002380</color>
+    <color name="i_am_color_2381">#00002381</color>
+    <color name="i_am_color_2382">#00002382</color>
+    <color name="i_am_color_2383">#00002383</color>
+    <color name="i_am_color_2384">#00002384</color>
+    <color name="i_am_color_2385">#00002385</color>
+    <color name="i_am_color_2386">#00002386</color>
+    <color name="i_am_color_2387">#00002387</color>
+    <color name="i_am_color_2388">#00002388</color>
+    <color name="i_am_color_2389">#00002389</color>
+    <color name="i_am_color_238a">#0000238a</color>
+    <color name="i_am_color_238b">#0000238b</color>
+    <color name="i_am_color_238c">#0000238c</color>
+    <color name="i_am_color_238d">#0000238d</color>
+    <color name="i_am_color_238e">#0000238e</color>
+    <color name="i_am_color_238f">#0000238f</color>
+    <color name="i_am_color_2390">#00002390</color>
+    <color name="i_am_color_2391">#00002391</color>
+    <color name="i_am_color_2392">#00002392</color>
+    <color name="i_am_color_2393">#00002393</color>
+    <color name="i_am_color_2394">#00002394</color>
+    <color name="i_am_color_2395">#00002395</color>
+    <color name="i_am_color_2396">#00002396</color>
+    <color name="i_am_color_2397">#00002397</color>
+    <color name="i_am_color_2398">#00002398</color>
+    <color name="i_am_color_2399">#00002399</color>
+    <color name="i_am_color_239a">#0000239a</color>
+    <color name="i_am_color_239b">#0000239b</color>
+    <color name="i_am_color_239c">#0000239c</color>
+    <color name="i_am_color_239d">#0000239d</color>
+    <color name="i_am_color_239e">#0000239e</color>
+    <color name="i_am_color_239f">#0000239f</color>
+    <color name="i_am_color_23a0">#000023a0</color>
+    <color name="i_am_color_23a1">#000023a1</color>
+    <color name="i_am_color_23a2">#000023a2</color>
+    <color name="i_am_color_23a3">#000023a3</color>
+    <color name="i_am_color_23a4">#000023a4</color>
+    <color name="i_am_color_23a5">#000023a5</color>
+    <color name="i_am_color_23a6">#000023a6</color>
+    <color name="i_am_color_23a7">#000023a7</color>
+    <color name="i_am_color_23a8">#000023a8</color>
+    <color name="i_am_color_23a9">#000023a9</color>
+    <color name="i_am_color_23aa">#000023aa</color>
+    <color name="i_am_color_23ab">#000023ab</color>
+    <color name="i_am_color_23ac">#000023ac</color>
+    <color name="i_am_color_23ad">#000023ad</color>
+    <color name="i_am_color_23ae">#000023ae</color>
+    <color name="i_am_color_23af">#000023af</color>
+    <color name="i_am_color_23b0">#000023b0</color>
+    <color name="i_am_color_23b1">#000023b1</color>
+    <color name="i_am_color_23b2">#000023b2</color>
+    <color name="i_am_color_23b3">#000023b3</color>
+    <color name="i_am_color_23b4">#000023b4</color>
+    <color name="i_am_color_23b5">#000023b5</color>
+    <color name="i_am_color_23b6">#000023b6</color>
+    <color name="i_am_color_23b7">#000023b7</color>
+    <color name="i_am_color_23b8">#000023b8</color>
+    <color name="i_am_color_23b9">#000023b9</color>
+    <color name="i_am_color_23ba">#000023ba</color>
+    <color name="i_am_color_23bb">#000023bb</color>
+    <color name="i_am_color_23bc">#000023bc</color>
+    <color name="i_am_color_23bd">#000023bd</color>
+    <color name="i_am_color_23be">#000023be</color>
+    <color name="i_am_color_23bf">#000023bf</color>
+    <color name="i_am_color_23c0">#000023c0</color>
+    <color name="i_am_color_23c1">#000023c1</color>
+    <color name="i_am_color_23c2">#000023c2</color>
+    <color name="i_am_color_23c3">#000023c3</color>
+    <color name="i_am_color_23c4">#000023c4</color>
+    <color name="i_am_color_23c5">#000023c5</color>
+    <color name="i_am_color_23c6">#000023c6</color>
+    <color name="i_am_color_23c7">#000023c7</color>
+    <color name="i_am_color_23c8">#000023c8</color>
+    <color name="i_am_color_23c9">#000023c9</color>
+    <color name="i_am_color_23ca">#000023ca</color>
+    <color name="i_am_color_23cb">#000023cb</color>
+    <color name="i_am_color_23cc">#000023cc</color>
+    <color name="i_am_color_23cd">#000023cd</color>
+    <color name="i_am_color_23ce">#000023ce</color>
+    <color name="i_am_color_23cf">#000023cf</color>
+    <color name="i_am_color_23d0">#000023d0</color>
+    <color name="i_am_color_23d1">#000023d1</color>
+    <color name="i_am_color_23d2">#000023d2</color>
+    <color name="i_am_color_23d3">#000023d3</color>
+    <color name="i_am_color_23d4">#000023d4</color>
+    <color name="i_am_color_23d5">#000023d5</color>
+    <color name="i_am_color_23d6">#000023d6</color>
+    <color name="i_am_color_23d7">#000023d7</color>
+    <color name="i_am_color_23d8">#000023d8</color>
+    <color name="i_am_color_23d9">#000023d9</color>
+    <color name="i_am_color_23da">#000023da</color>
+    <color name="i_am_color_23db">#000023db</color>
+    <color name="i_am_color_23dc">#000023dc</color>
+    <color name="i_am_color_23dd">#000023dd</color>
+    <color name="i_am_color_23de">#000023de</color>
+    <color name="i_am_color_23df">#000023df</color>
+    <color name="i_am_color_23e0">#000023e0</color>
+    <color name="i_am_color_23e1">#000023e1</color>
+    <color name="i_am_color_23e2">#000023e2</color>
+    <color name="i_am_color_23e3">#000023e3</color>
+    <color name="i_am_color_23e4">#000023e4</color>
+    <color name="i_am_color_23e5">#000023e5</color>
+    <color name="i_am_color_23e6">#000023e6</color>
+    <color name="i_am_color_23e7">#000023e7</color>
+    <color name="i_am_color_23e8">#000023e8</color>
+    <color name="i_am_color_23e9">#000023e9</color>
+    <color name="i_am_color_23ea">#000023ea</color>
+    <color name="i_am_color_23eb">#000023eb</color>
+    <color name="i_am_color_23ec">#000023ec</color>
+    <color name="i_am_color_23ed">#000023ed</color>
+    <color name="i_am_color_23ee">#000023ee</color>
+    <color name="i_am_color_23ef">#000023ef</color>
+    <color name="i_am_color_23f0">#000023f0</color>
+    <color name="i_am_color_23f1">#000023f1</color>
+    <color name="i_am_color_23f2">#000023f2</color>
+    <color name="i_am_color_23f3">#000023f3</color>
+    <color name="i_am_color_23f4">#000023f4</color>
+    <color name="i_am_color_23f5">#000023f5</color>
+    <color name="i_am_color_23f6">#000023f6</color>
+    <color name="i_am_color_23f7">#000023f7</color>
+    <color name="i_am_color_23f8">#000023f8</color>
+    <color name="i_am_color_23f9">#000023f9</color>
+    <color name="i_am_color_23fa">#000023fa</color>
+    <color name="i_am_color_23fb">#000023fb</color>
+    <color name="i_am_color_23fc">#000023fc</color>
+    <color name="i_am_color_23fd">#000023fd</color>
+    <color name="i_am_color_23fe">#000023fe</color>
+    <color name="i_am_color_23ff">#000023ff</color>
+    <color name="i_am_color_2400">#00002400</color>
+    <color name="i_am_color_2401">#00002401</color>
+    <color name="i_am_color_2402">#00002402</color>
+    <color name="i_am_color_2403">#00002403</color>
+    <color name="i_am_color_2404">#00002404</color>
+    <color name="i_am_color_2405">#00002405</color>
+    <color name="i_am_color_2406">#00002406</color>
+    <color name="i_am_color_2407">#00002407</color>
+    <color name="i_am_color_2408">#00002408</color>
+    <color name="i_am_color_2409">#00002409</color>
+    <color name="i_am_color_240a">#0000240a</color>
+    <color name="i_am_color_240b">#0000240b</color>
+    <color name="i_am_color_240c">#0000240c</color>
+    <color name="i_am_color_240d">#0000240d</color>
+    <color name="i_am_color_240e">#0000240e</color>
+    <color name="i_am_color_240f">#0000240f</color>
+    <color name="i_am_color_2410">#00002410</color>
+    <color name="i_am_color_2411">#00002411</color>
+    <color name="i_am_color_2412">#00002412</color>
+    <color name="i_am_color_2413">#00002413</color>
+    <color name="i_am_color_2414">#00002414</color>
+    <color name="i_am_color_2415">#00002415</color>
+    <color name="i_am_color_2416">#00002416</color>
+    <color name="i_am_color_2417">#00002417</color>
+    <color name="i_am_color_2418">#00002418</color>
+    <color name="i_am_color_2419">#00002419</color>
+    <color name="i_am_color_241a">#0000241a</color>
+    <color name="i_am_color_241b">#0000241b</color>
+    <color name="i_am_color_241c">#0000241c</color>
+    <color name="i_am_color_241d">#0000241d</color>
+    <color name="i_am_color_241e">#0000241e</color>
+    <color name="i_am_color_241f">#0000241f</color>
+    <color name="i_am_color_2420">#00002420</color>
+    <color name="i_am_color_2421">#00002421</color>
+    <color name="i_am_color_2422">#00002422</color>
+    <color name="i_am_color_2423">#00002423</color>
+    <color name="i_am_color_2424">#00002424</color>
+    <color name="i_am_color_2425">#00002425</color>
+    <color name="i_am_color_2426">#00002426</color>
+    <color name="i_am_color_2427">#00002427</color>
+    <color name="i_am_color_2428">#00002428</color>
+    <color name="i_am_color_2429">#00002429</color>
+    <color name="i_am_color_242a">#0000242a</color>
+    <color name="i_am_color_242b">#0000242b</color>
+    <color name="i_am_color_242c">#0000242c</color>
+    <color name="i_am_color_242d">#0000242d</color>
+    <color name="i_am_color_242e">#0000242e</color>
+    <color name="i_am_color_242f">#0000242f</color>
+    <color name="i_am_color_2430">#00002430</color>
+    <color name="i_am_color_2431">#00002431</color>
+    <color name="i_am_color_2432">#00002432</color>
+    <color name="i_am_color_2433">#00002433</color>
+    <color name="i_am_color_2434">#00002434</color>
+    <color name="i_am_color_2435">#00002435</color>
+    <color name="i_am_color_2436">#00002436</color>
+    <color name="i_am_color_2437">#00002437</color>
+    <color name="i_am_color_2438">#00002438</color>
+    <color name="i_am_color_2439">#00002439</color>
+    <color name="i_am_color_243a">#0000243a</color>
+    <color name="i_am_color_243b">#0000243b</color>
+    <color name="i_am_color_243c">#0000243c</color>
+    <color name="i_am_color_243d">#0000243d</color>
+    <color name="i_am_color_243e">#0000243e</color>
+    <color name="i_am_color_243f">#0000243f</color>
+    <color name="i_am_color_2440">#00002440</color>
+    <color name="i_am_color_2441">#00002441</color>
+    <color name="i_am_color_2442">#00002442</color>
+    <color name="i_am_color_2443">#00002443</color>
+    <color name="i_am_color_2444">#00002444</color>
+    <color name="i_am_color_2445">#00002445</color>
+    <color name="i_am_color_2446">#00002446</color>
+    <color name="i_am_color_2447">#00002447</color>
+    <color name="i_am_color_2448">#00002448</color>
+    <color name="i_am_color_2449">#00002449</color>
+    <color name="i_am_color_244a">#0000244a</color>
+    <color name="i_am_color_244b">#0000244b</color>
+    <color name="i_am_color_244c">#0000244c</color>
+    <color name="i_am_color_244d">#0000244d</color>
+    <color name="i_am_color_244e">#0000244e</color>
+    <color name="i_am_color_244f">#0000244f</color>
+    <color name="i_am_color_2450">#00002450</color>
+    <color name="i_am_color_2451">#00002451</color>
+    <color name="i_am_color_2452">#00002452</color>
+    <color name="i_am_color_2453">#00002453</color>
+    <color name="i_am_color_2454">#00002454</color>
+    <color name="i_am_color_2455">#00002455</color>
+    <color name="i_am_color_2456">#00002456</color>
+    <color name="i_am_color_2457">#00002457</color>
+    <color name="i_am_color_2458">#00002458</color>
+    <color name="i_am_color_2459">#00002459</color>
+    <color name="i_am_color_245a">#0000245a</color>
+    <color name="i_am_color_245b">#0000245b</color>
+    <color name="i_am_color_245c">#0000245c</color>
+    <color name="i_am_color_245d">#0000245d</color>
+    <color name="i_am_color_245e">#0000245e</color>
+    <color name="i_am_color_245f">#0000245f</color>
+    <color name="i_am_color_2460">#00002460</color>
+    <color name="i_am_color_2461">#00002461</color>
+    <color name="i_am_color_2462">#00002462</color>
+    <color name="i_am_color_2463">#00002463</color>
+    <color name="i_am_color_2464">#00002464</color>
+    <color name="i_am_color_2465">#00002465</color>
+    <color name="i_am_color_2466">#00002466</color>
+    <color name="i_am_color_2467">#00002467</color>
+    <color name="i_am_color_2468">#00002468</color>
+    <color name="i_am_color_2469">#00002469</color>
+    <color name="i_am_color_246a">#0000246a</color>
+    <color name="i_am_color_246b">#0000246b</color>
+    <color name="i_am_color_246c">#0000246c</color>
+    <color name="i_am_color_246d">#0000246d</color>
+    <color name="i_am_color_246e">#0000246e</color>
+    <color name="i_am_color_246f">#0000246f</color>
+    <color name="i_am_color_2470">#00002470</color>
+    <color name="i_am_color_2471">#00002471</color>
+    <color name="i_am_color_2472">#00002472</color>
+    <color name="i_am_color_2473">#00002473</color>
+    <color name="i_am_color_2474">#00002474</color>
+    <color name="i_am_color_2475">#00002475</color>
+    <color name="i_am_color_2476">#00002476</color>
+    <color name="i_am_color_2477">#00002477</color>
+    <color name="i_am_color_2478">#00002478</color>
+    <color name="i_am_color_2479">#00002479</color>
+    <color name="i_am_color_247a">#0000247a</color>
+    <color name="i_am_color_247b">#0000247b</color>
+    <color name="i_am_color_247c">#0000247c</color>
+    <color name="i_am_color_247d">#0000247d</color>
+    <color name="i_am_color_247e">#0000247e</color>
+    <color name="i_am_color_247f">#0000247f</color>
+    <color name="i_am_color_2480">#00002480</color>
+    <color name="i_am_color_2481">#00002481</color>
+    <color name="i_am_color_2482">#00002482</color>
+    <color name="i_am_color_2483">#00002483</color>
+    <color name="i_am_color_2484">#00002484</color>
+    <color name="i_am_color_2485">#00002485</color>
+    <color name="i_am_color_2486">#00002486</color>
+    <color name="i_am_color_2487">#00002487</color>
+    <color name="i_am_color_2488">#00002488</color>
+    <color name="i_am_color_2489">#00002489</color>
+    <color name="i_am_color_248a">#0000248a</color>
+    <color name="i_am_color_248b">#0000248b</color>
+    <color name="i_am_color_248c">#0000248c</color>
+    <color name="i_am_color_248d">#0000248d</color>
+    <color name="i_am_color_248e">#0000248e</color>
+    <color name="i_am_color_248f">#0000248f</color>
+    <color name="i_am_color_2490">#00002490</color>
+    <color name="i_am_color_2491">#00002491</color>
+    <color name="i_am_color_2492">#00002492</color>
+    <color name="i_am_color_2493">#00002493</color>
+    <color name="i_am_color_2494">#00002494</color>
+    <color name="i_am_color_2495">#00002495</color>
+    <color name="i_am_color_2496">#00002496</color>
+    <color name="i_am_color_2497">#00002497</color>
+    <color name="i_am_color_2498">#00002498</color>
+    <color name="i_am_color_2499">#00002499</color>
+    <color name="i_am_color_249a">#0000249a</color>
+    <color name="i_am_color_249b">#0000249b</color>
+    <color name="i_am_color_249c">#0000249c</color>
+    <color name="i_am_color_249d">#0000249d</color>
+    <color name="i_am_color_249e">#0000249e</color>
+    <color name="i_am_color_249f">#0000249f</color>
+    <color name="i_am_color_24a0">#000024a0</color>
+    <color name="i_am_color_24a1">#000024a1</color>
+    <color name="i_am_color_24a2">#000024a2</color>
+    <color name="i_am_color_24a3">#000024a3</color>
+    <color name="i_am_color_24a4">#000024a4</color>
+    <color name="i_am_color_24a5">#000024a5</color>
+    <color name="i_am_color_24a6">#000024a6</color>
+    <color name="i_am_color_24a7">#000024a7</color>
+    <color name="i_am_color_24a8">#000024a8</color>
+    <color name="i_am_color_24a9">#000024a9</color>
+    <color name="i_am_color_24aa">#000024aa</color>
+    <color name="i_am_color_24ab">#000024ab</color>
+    <color name="i_am_color_24ac">#000024ac</color>
+    <color name="i_am_color_24ad">#000024ad</color>
+    <color name="i_am_color_24ae">#000024ae</color>
+    <color name="i_am_color_24af">#000024af</color>
+    <color name="i_am_color_24b0">#000024b0</color>
+    <color name="i_am_color_24b1">#000024b1</color>
+    <color name="i_am_color_24b2">#000024b2</color>
+    <color name="i_am_color_24b3">#000024b3</color>
+    <color name="i_am_color_24b4">#000024b4</color>
+    <color name="i_am_color_24b5">#000024b5</color>
+    <color name="i_am_color_24b6">#000024b6</color>
+    <color name="i_am_color_24b7">#000024b7</color>
+    <color name="i_am_color_24b8">#000024b8</color>
+    <color name="i_am_color_24b9">#000024b9</color>
+    <color name="i_am_color_24ba">#000024ba</color>
+    <color name="i_am_color_24bb">#000024bb</color>
+    <color name="i_am_color_24bc">#000024bc</color>
+    <color name="i_am_color_24bd">#000024bd</color>
+    <color name="i_am_color_24be">#000024be</color>
+    <color name="i_am_color_24bf">#000024bf</color>
+    <color name="i_am_color_24c0">#000024c0</color>
+    <color name="i_am_color_24c1">#000024c1</color>
+    <color name="i_am_color_24c2">#000024c2</color>
+    <color name="i_am_color_24c3">#000024c3</color>
+    <color name="i_am_color_24c4">#000024c4</color>
+    <color name="i_am_color_24c5">#000024c5</color>
+    <color name="i_am_color_24c6">#000024c6</color>
+    <color name="i_am_color_24c7">#000024c7</color>
+    <color name="i_am_color_24c8">#000024c8</color>
+    <color name="i_am_color_24c9">#000024c9</color>
+    <color name="i_am_color_24ca">#000024ca</color>
+    <color name="i_am_color_24cb">#000024cb</color>
+    <color name="i_am_color_24cc">#000024cc</color>
+    <color name="i_am_color_24cd">#000024cd</color>
+    <color name="i_am_color_24ce">#000024ce</color>
+    <color name="i_am_color_24cf">#000024cf</color>
+    <color name="i_am_color_24d0">#000024d0</color>
+    <color name="i_am_color_24d1">#000024d1</color>
+    <color name="i_am_color_24d2">#000024d2</color>
+    <color name="i_am_color_24d3">#000024d3</color>
+    <color name="i_am_color_24d4">#000024d4</color>
+    <color name="i_am_color_24d5">#000024d5</color>
+    <color name="i_am_color_24d6">#000024d6</color>
+    <color name="i_am_color_24d7">#000024d7</color>
+    <color name="i_am_color_24d8">#000024d8</color>
+    <color name="i_am_color_24d9">#000024d9</color>
+    <color name="i_am_color_24da">#000024da</color>
+    <color name="i_am_color_24db">#000024db</color>
+    <color name="i_am_color_24dc">#000024dc</color>
+    <color name="i_am_color_24dd">#000024dd</color>
+    <color name="i_am_color_24de">#000024de</color>
+    <color name="i_am_color_24df">#000024df</color>
+    <color name="i_am_color_24e0">#000024e0</color>
+    <color name="i_am_color_24e1">#000024e1</color>
+    <color name="i_am_color_24e2">#000024e2</color>
+    <color name="i_am_color_24e3">#000024e3</color>
+    <color name="i_am_color_24e4">#000024e4</color>
+    <color name="i_am_color_24e5">#000024e5</color>
+    <color name="i_am_color_24e6">#000024e6</color>
+    <color name="i_am_color_24e7">#000024e7</color>
+    <color name="i_am_color_24e8">#000024e8</color>
+    <color name="i_am_color_24e9">#000024e9</color>
+    <color name="i_am_color_24ea">#000024ea</color>
+    <color name="i_am_color_24eb">#000024eb</color>
+    <color name="i_am_color_24ec">#000024ec</color>
+    <color name="i_am_color_24ed">#000024ed</color>
+    <color name="i_am_color_24ee">#000024ee</color>
+    <color name="i_am_color_24ef">#000024ef</color>
+    <color name="i_am_color_24f0">#000024f0</color>
+    <color name="i_am_color_24f1">#000024f1</color>
+    <color name="i_am_color_24f2">#000024f2</color>
+    <color name="i_am_color_24f3">#000024f3</color>
+    <color name="i_am_color_24f4">#000024f4</color>
+    <color name="i_am_color_24f5">#000024f5</color>
+    <color name="i_am_color_24f6">#000024f6</color>
+    <color name="i_am_color_24f7">#000024f7</color>
+    <color name="i_am_color_24f8">#000024f8</color>
+    <color name="i_am_color_24f9">#000024f9</color>
+    <color name="i_am_color_24fa">#000024fa</color>
+    <color name="i_am_color_24fb">#000024fb</color>
+    <color name="i_am_color_24fc">#000024fc</color>
+    <color name="i_am_color_24fd">#000024fd</color>
+    <color name="i_am_color_24fe">#000024fe</color>
+    <color name="i_am_color_24ff">#000024ff</color>
+    <color name="i_am_color_2500">#00002500</color>
+    <color name="i_am_color_2501">#00002501</color>
+    <color name="i_am_color_2502">#00002502</color>
+    <color name="i_am_color_2503">#00002503</color>
+    <color name="i_am_color_2504">#00002504</color>
+    <color name="i_am_color_2505">#00002505</color>
+    <color name="i_am_color_2506">#00002506</color>
+    <color name="i_am_color_2507">#00002507</color>
+    <color name="i_am_color_2508">#00002508</color>
+    <color name="i_am_color_2509">#00002509</color>
+    <color name="i_am_color_250a">#0000250a</color>
+    <color name="i_am_color_250b">#0000250b</color>
+    <color name="i_am_color_250c">#0000250c</color>
+    <color name="i_am_color_250d">#0000250d</color>
+    <color name="i_am_color_250e">#0000250e</color>
+    <color name="i_am_color_250f">#0000250f</color>
+    <color name="i_am_color_2510">#00002510</color>
+    <color name="i_am_color_2511">#00002511</color>
+    <color name="i_am_color_2512">#00002512</color>
+    <color name="i_am_color_2513">#00002513</color>
+    <color name="i_am_color_2514">#00002514</color>
+    <color name="i_am_color_2515">#00002515</color>
+    <color name="i_am_color_2516">#00002516</color>
+    <color name="i_am_color_2517">#00002517</color>
+    <color name="i_am_color_2518">#00002518</color>
+    <color name="i_am_color_2519">#00002519</color>
+    <color name="i_am_color_251a">#0000251a</color>
+    <color name="i_am_color_251b">#0000251b</color>
+    <color name="i_am_color_251c">#0000251c</color>
+    <color name="i_am_color_251d">#0000251d</color>
+    <color name="i_am_color_251e">#0000251e</color>
+    <color name="i_am_color_251f">#0000251f</color>
+    <color name="i_am_color_2520">#00002520</color>
+    <color name="i_am_color_2521">#00002521</color>
+    <color name="i_am_color_2522">#00002522</color>
+    <color name="i_am_color_2523">#00002523</color>
+    <color name="i_am_color_2524">#00002524</color>
+    <color name="i_am_color_2525">#00002525</color>
+    <color name="i_am_color_2526">#00002526</color>
+    <color name="i_am_color_2527">#00002527</color>
+    <color name="i_am_color_2528">#00002528</color>
+    <color name="i_am_color_2529">#00002529</color>
+    <color name="i_am_color_252a">#0000252a</color>
+    <color name="i_am_color_252b">#0000252b</color>
+    <color name="i_am_color_252c">#0000252c</color>
+    <color name="i_am_color_252d">#0000252d</color>
+    <color name="i_am_color_252e">#0000252e</color>
+    <color name="i_am_color_252f">#0000252f</color>
+    <color name="i_am_color_2530">#00002530</color>
+    <color name="i_am_color_2531">#00002531</color>
+    <color name="i_am_color_2532">#00002532</color>
+    <color name="i_am_color_2533">#00002533</color>
+    <color name="i_am_color_2534">#00002534</color>
+    <color name="i_am_color_2535">#00002535</color>
+    <color name="i_am_color_2536">#00002536</color>
+    <color name="i_am_color_2537">#00002537</color>
+    <color name="i_am_color_2538">#00002538</color>
+    <color name="i_am_color_2539">#00002539</color>
+    <color name="i_am_color_253a">#0000253a</color>
+    <color name="i_am_color_253b">#0000253b</color>
+    <color name="i_am_color_253c">#0000253c</color>
+    <color name="i_am_color_253d">#0000253d</color>
+    <color name="i_am_color_253e">#0000253e</color>
+    <color name="i_am_color_253f">#0000253f</color>
+    <color name="i_am_color_2540">#00002540</color>
+    <color name="i_am_color_2541">#00002541</color>
+    <color name="i_am_color_2542">#00002542</color>
+    <color name="i_am_color_2543">#00002543</color>
+    <color name="i_am_color_2544">#00002544</color>
+    <color name="i_am_color_2545">#00002545</color>
+    <color name="i_am_color_2546">#00002546</color>
+    <color name="i_am_color_2547">#00002547</color>
+    <color name="i_am_color_2548">#00002548</color>
+    <color name="i_am_color_2549">#00002549</color>
+    <color name="i_am_color_254a">#0000254a</color>
+    <color name="i_am_color_254b">#0000254b</color>
+    <color name="i_am_color_254c">#0000254c</color>
+    <color name="i_am_color_254d">#0000254d</color>
+    <color name="i_am_color_254e">#0000254e</color>
+    <color name="i_am_color_254f">#0000254f</color>
+    <color name="i_am_color_2550">#00002550</color>
+    <color name="i_am_color_2551">#00002551</color>
+    <color name="i_am_color_2552">#00002552</color>
+    <color name="i_am_color_2553">#00002553</color>
+    <color name="i_am_color_2554">#00002554</color>
+    <color name="i_am_color_2555">#00002555</color>
+    <color name="i_am_color_2556">#00002556</color>
+    <color name="i_am_color_2557">#00002557</color>
+    <color name="i_am_color_2558">#00002558</color>
+    <color name="i_am_color_2559">#00002559</color>
+    <color name="i_am_color_255a">#0000255a</color>
+    <color name="i_am_color_255b">#0000255b</color>
+    <color name="i_am_color_255c">#0000255c</color>
+    <color name="i_am_color_255d">#0000255d</color>
+    <color name="i_am_color_255e">#0000255e</color>
+    <color name="i_am_color_255f">#0000255f</color>
+    <color name="i_am_color_2560">#00002560</color>
+    <color name="i_am_color_2561">#00002561</color>
+    <color name="i_am_color_2562">#00002562</color>
+    <color name="i_am_color_2563">#00002563</color>
+    <color name="i_am_color_2564">#00002564</color>
+    <color name="i_am_color_2565">#00002565</color>
+    <color name="i_am_color_2566">#00002566</color>
+    <color name="i_am_color_2567">#00002567</color>
+    <color name="i_am_color_2568">#00002568</color>
+    <color name="i_am_color_2569">#00002569</color>
+    <color name="i_am_color_256a">#0000256a</color>
+    <color name="i_am_color_256b">#0000256b</color>
+    <color name="i_am_color_256c">#0000256c</color>
+    <color name="i_am_color_256d">#0000256d</color>
+    <color name="i_am_color_256e">#0000256e</color>
+    <color name="i_am_color_256f">#0000256f</color>
+    <color name="i_am_color_2570">#00002570</color>
+    <color name="i_am_color_2571">#00002571</color>
+    <color name="i_am_color_2572">#00002572</color>
+    <color name="i_am_color_2573">#00002573</color>
+    <color name="i_am_color_2574">#00002574</color>
+    <color name="i_am_color_2575">#00002575</color>
+    <color name="i_am_color_2576">#00002576</color>
+    <color name="i_am_color_2577">#00002577</color>
+    <color name="i_am_color_2578">#00002578</color>
+    <color name="i_am_color_2579">#00002579</color>
+    <color name="i_am_color_257a">#0000257a</color>
+    <color name="i_am_color_257b">#0000257b</color>
+    <color name="i_am_color_257c">#0000257c</color>
+    <color name="i_am_color_257d">#0000257d</color>
+    <color name="i_am_color_257e">#0000257e</color>
+    <color name="i_am_color_257f">#0000257f</color>
+    <color name="i_am_color_2580">#00002580</color>
+    <color name="i_am_color_2581">#00002581</color>
+    <color name="i_am_color_2582">#00002582</color>
+    <color name="i_am_color_2583">#00002583</color>
+    <color name="i_am_color_2584">#00002584</color>
+    <color name="i_am_color_2585">#00002585</color>
+    <color name="i_am_color_2586">#00002586</color>
+    <color name="i_am_color_2587">#00002587</color>
+    <color name="i_am_color_2588">#00002588</color>
+    <color name="i_am_color_2589">#00002589</color>
+    <color name="i_am_color_258a">#0000258a</color>
+    <color name="i_am_color_258b">#0000258b</color>
+    <color name="i_am_color_258c">#0000258c</color>
+    <color name="i_am_color_258d">#0000258d</color>
+    <color name="i_am_color_258e">#0000258e</color>
+    <color name="i_am_color_258f">#0000258f</color>
+    <color name="i_am_color_2590">#00002590</color>
+    <color name="i_am_color_2591">#00002591</color>
+    <color name="i_am_color_2592">#00002592</color>
+    <color name="i_am_color_2593">#00002593</color>
+    <color name="i_am_color_2594">#00002594</color>
+    <color name="i_am_color_2595">#00002595</color>
+    <color name="i_am_color_2596">#00002596</color>
+    <color name="i_am_color_2597">#00002597</color>
+    <color name="i_am_color_2598">#00002598</color>
+    <color name="i_am_color_2599">#00002599</color>
+    <color name="i_am_color_259a">#0000259a</color>
+    <color name="i_am_color_259b">#0000259b</color>
+    <color name="i_am_color_259c">#0000259c</color>
+    <color name="i_am_color_259d">#0000259d</color>
+    <color name="i_am_color_259e">#0000259e</color>
+    <color name="i_am_color_259f">#0000259f</color>
+    <color name="i_am_color_25a0">#000025a0</color>
+    <color name="i_am_color_25a1">#000025a1</color>
+    <color name="i_am_color_25a2">#000025a2</color>
+    <color name="i_am_color_25a3">#000025a3</color>
+    <color name="i_am_color_25a4">#000025a4</color>
+    <color name="i_am_color_25a5">#000025a5</color>
+    <color name="i_am_color_25a6">#000025a6</color>
+    <color name="i_am_color_25a7">#000025a7</color>
+    <color name="i_am_color_25a8">#000025a8</color>
+    <color name="i_am_color_25a9">#000025a9</color>
+    <color name="i_am_color_25aa">#000025aa</color>
+    <color name="i_am_color_25ab">#000025ab</color>
+    <color name="i_am_color_25ac">#000025ac</color>
+    <color name="i_am_color_25ad">#000025ad</color>
+    <color name="i_am_color_25ae">#000025ae</color>
+    <color name="i_am_color_25af">#000025af</color>
+    <color name="i_am_color_25b0">#000025b0</color>
+    <color name="i_am_color_25b1">#000025b1</color>
+    <color name="i_am_color_25b2">#000025b2</color>
+    <color name="i_am_color_25b3">#000025b3</color>
+    <color name="i_am_color_25b4">#000025b4</color>
+    <color name="i_am_color_25b5">#000025b5</color>
+    <color name="i_am_color_25b6">#000025b6</color>
+    <color name="i_am_color_25b7">#000025b7</color>
+    <color name="i_am_color_25b8">#000025b8</color>
+    <color name="i_am_color_25b9">#000025b9</color>
+    <color name="i_am_color_25ba">#000025ba</color>
+    <color name="i_am_color_25bb">#000025bb</color>
+    <color name="i_am_color_25bc">#000025bc</color>
+    <color name="i_am_color_25bd">#000025bd</color>
+    <color name="i_am_color_25be">#000025be</color>
+    <color name="i_am_color_25bf">#000025bf</color>
+    <color name="i_am_color_25c0">#000025c0</color>
+    <color name="i_am_color_25c1">#000025c1</color>
+    <color name="i_am_color_25c2">#000025c2</color>
+    <color name="i_am_color_25c3">#000025c3</color>
+    <color name="i_am_color_25c4">#000025c4</color>
+    <color name="i_am_color_25c5">#000025c5</color>
+    <color name="i_am_color_25c6">#000025c6</color>
+    <color name="i_am_color_25c7">#000025c7</color>
+    <color name="i_am_color_25c8">#000025c8</color>
+    <color name="i_am_color_25c9">#000025c9</color>
+    <color name="i_am_color_25ca">#000025ca</color>
+    <color name="i_am_color_25cb">#000025cb</color>
+    <color name="i_am_color_25cc">#000025cc</color>
+    <color name="i_am_color_25cd">#000025cd</color>
+    <color name="i_am_color_25ce">#000025ce</color>
+    <color name="i_am_color_25cf">#000025cf</color>
+    <color name="i_am_color_25d0">#000025d0</color>
+    <color name="i_am_color_25d1">#000025d1</color>
+    <color name="i_am_color_25d2">#000025d2</color>
+    <color name="i_am_color_25d3">#000025d3</color>
+    <color name="i_am_color_25d4">#000025d4</color>
+    <color name="i_am_color_25d5">#000025d5</color>
+    <color name="i_am_color_25d6">#000025d6</color>
+    <color name="i_am_color_25d7">#000025d7</color>
+    <color name="i_am_color_25d8">#000025d8</color>
+    <color name="i_am_color_25d9">#000025d9</color>
+    <color name="i_am_color_25da">#000025da</color>
+    <color name="i_am_color_25db">#000025db</color>
+    <color name="i_am_color_25dc">#000025dc</color>
+    <color name="i_am_color_25dd">#000025dd</color>
+    <color name="i_am_color_25de">#000025de</color>
+    <color name="i_am_color_25df">#000025df</color>
+    <color name="i_am_color_25e0">#000025e0</color>
+    <color name="i_am_color_25e1">#000025e1</color>
+    <color name="i_am_color_25e2">#000025e2</color>
+    <color name="i_am_color_25e3">#000025e3</color>
+    <color name="i_am_color_25e4">#000025e4</color>
+    <color name="i_am_color_25e5">#000025e5</color>
+    <color name="i_am_color_25e6">#000025e6</color>
+    <color name="i_am_color_25e7">#000025e7</color>
+    <color name="i_am_color_25e8">#000025e8</color>
+    <color name="i_am_color_25e9">#000025e9</color>
+    <color name="i_am_color_25ea">#000025ea</color>
+    <color name="i_am_color_25eb">#000025eb</color>
+    <color name="i_am_color_25ec">#000025ec</color>
+    <color name="i_am_color_25ed">#000025ed</color>
+    <color name="i_am_color_25ee">#000025ee</color>
+    <color name="i_am_color_25ef">#000025ef</color>
+    <color name="i_am_color_25f0">#000025f0</color>
+    <color name="i_am_color_25f1">#000025f1</color>
+    <color name="i_am_color_25f2">#000025f2</color>
+    <color name="i_am_color_25f3">#000025f3</color>
+    <color name="i_am_color_25f4">#000025f4</color>
+    <color name="i_am_color_25f5">#000025f5</color>
+    <color name="i_am_color_25f6">#000025f6</color>
+    <color name="i_am_color_25f7">#000025f7</color>
+    <color name="i_am_color_25f8">#000025f8</color>
+    <color name="i_am_color_25f9">#000025f9</color>
+    <color name="i_am_color_25fa">#000025fa</color>
+    <color name="i_am_color_25fb">#000025fb</color>
+    <color name="i_am_color_25fc">#000025fc</color>
+    <color name="i_am_color_25fd">#000025fd</color>
+    <color name="i_am_color_25fe">#000025fe</color>
+    <color name="i_am_color_25ff">#000025ff</color>
+    <color name="i_am_color_2600">#00002600</color>
+    <color name="i_am_color_2601">#00002601</color>
+    <color name="i_am_color_2602">#00002602</color>
+    <color name="i_am_color_2603">#00002603</color>
+    <color name="i_am_color_2604">#00002604</color>
+    <color name="i_am_color_2605">#00002605</color>
+    <color name="i_am_color_2606">#00002606</color>
+    <color name="i_am_color_2607">#00002607</color>
+    <color name="i_am_color_2608">#00002608</color>
+    <color name="i_am_color_2609">#00002609</color>
+    <color name="i_am_color_260a">#0000260a</color>
+    <color name="i_am_color_260b">#0000260b</color>
+    <color name="i_am_color_260c">#0000260c</color>
+    <color name="i_am_color_260d">#0000260d</color>
+    <color name="i_am_color_260e">#0000260e</color>
+    <color name="i_am_color_260f">#0000260f</color>
+    <color name="i_am_color_2610">#00002610</color>
+    <color name="i_am_color_2611">#00002611</color>
+    <color name="i_am_color_2612">#00002612</color>
+    <color name="i_am_color_2613">#00002613</color>
+    <color name="i_am_color_2614">#00002614</color>
+    <color name="i_am_color_2615">#00002615</color>
+    <color name="i_am_color_2616">#00002616</color>
+    <color name="i_am_color_2617">#00002617</color>
+    <color name="i_am_color_2618">#00002618</color>
+    <color name="i_am_color_2619">#00002619</color>
+    <color name="i_am_color_261a">#0000261a</color>
+    <color name="i_am_color_261b">#0000261b</color>
+    <color name="i_am_color_261c">#0000261c</color>
+    <color name="i_am_color_261d">#0000261d</color>
+    <color name="i_am_color_261e">#0000261e</color>
+    <color name="i_am_color_261f">#0000261f</color>
+    <color name="i_am_color_2620">#00002620</color>
+    <color name="i_am_color_2621">#00002621</color>
+    <color name="i_am_color_2622">#00002622</color>
+    <color name="i_am_color_2623">#00002623</color>
+    <color name="i_am_color_2624">#00002624</color>
+    <color name="i_am_color_2625">#00002625</color>
+    <color name="i_am_color_2626">#00002626</color>
+    <color name="i_am_color_2627">#00002627</color>
+    <color name="i_am_color_2628">#00002628</color>
+    <color name="i_am_color_2629">#00002629</color>
+    <color name="i_am_color_262a">#0000262a</color>
+    <color name="i_am_color_262b">#0000262b</color>
+    <color name="i_am_color_262c">#0000262c</color>
+    <color name="i_am_color_262d">#0000262d</color>
+    <color name="i_am_color_262e">#0000262e</color>
+    <color name="i_am_color_262f">#0000262f</color>
+    <color name="i_am_color_2630">#00002630</color>
+    <color name="i_am_color_2631">#00002631</color>
+    <color name="i_am_color_2632">#00002632</color>
+    <color name="i_am_color_2633">#00002633</color>
+    <color name="i_am_color_2634">#00002634</color>
+    <color name="i_am_color_2635">#00002635</color>
+    <color name="i_am_color_2636">#00002636</color>
+    <color name="i_am_color_2637">#00002637</color>
+    <color name="i_am_color_2638">#00002638</color>
+    <color name="i_am_color_2639">#00002639</color>
+    <color name="i_am_color_263a">#0000263a</color>
+    <color name="i_am_color_263b">#0000263b</color>
+    <color name="i_am_color_263c">#0000263c</color>
+    <color name="i_am_color_263d">#0000263d</color>
+    <color name="i_am_color_263e">#0000263e</color>
+    <color name="i_am_color_263f">#0000263f</color>
+    <color name="i_am_color_2640">#00002640</color>
+    <color name="i_am_color_2641">#00002641</color>
+    <color name="i_am_color_2642">#00002642</color>
+    <color name="i_am_color_2643">#00002643</color>
+    <color name="i_am_color_2644">#00002644</color>
+    <color name="i_am_color_2645">#00002645</color>
+    <color name="i_am_color_2646">#00002646</color>
+    <color name="i_am_color_2647">#00002647</color>
+    <color name="i_am_color_2648">#00002648</color>
+    <color name="i_am_color_2649">#00002649</color>
+    <color name="i_am_color_264a">#0000264a</color>
+    <color name="i_am_color_264b">#0000264b</color>
+    <color name="i_am_color_264c">#0000264c</color>
+    <color name="i_am_color_264d">#0000264d</color>
+    <color name="i_am_color_264e">#0000264e</color>
+    <color name="i_am_color_264f">#0000264f</color>
+    <color name="i_am_color_2650">#00002650</color>
+    <color name="i_am_color_2651">#00002651</color>
+    <color name="i_am_color_2652">#00002652</color>
+    <color name="i_am_color_2653">#00002653</color>
+    <color name="i_am_color_2654">#00002654</color>
+    <color name="i_am_color_2655">#00002655</color>
+    <color name="i_am_color_2656">#00002656</color>
+    <color name="i_am_color_2657">#00002657</color>
+    <color name="i_am_color_2658">#00002658</color>
+    <color name="i_am_color_2659">#00002659</color>
+    <color name="i_am_color_265a">#0000265a</color>
+    <color name="i_am_color_265b">#0000265b</color>
+    <color name="i_am_color_265c">#0000265c</color>
+    <color name="i_am_color_265d">#0000265d</color>
+    <color name="i_am_color_265e">#0000265e</color>
+    <color name="i_am_color_265f">#0000265f</color>
+    <color name="i_am_color_2660">#00002660</color>
+    <color name="i_am_color_2661">#00002661</color>
+    <color name="i_am_color_2662">#00002662</color>
+    <color name="i_am_color_2663">#00002663</color>
+    <color name="i_am_color_2664">#00002664</color>
+    <color name="i_am_color_2665">#00002665</color>
+    <color name="i_am_color_2666">#00002666</color>
+    <color name="i_am_color_2667">#00002667</color>
+    <color name="i_am_color_2668">#00002668</color>
+    <color name="i_am_color_2669">#00002669</color>
+    <color name="i_am_color_266a">#0000266a</color>
+    <color name="i_am_color_266b">#0000266b</color>
+    <color name="i_am_color_266c">#0000266c</color>
+    <color name="i_am_color_266d">#0000266d</color>
+    <color name="i_am_color_266e">#0000266e</color>
+    <color name="i_am_color_266f">#0000266f</color>
+    <color name="i_am_color_2670">#00002670</color>
+    <color name="i_am_color_2671">#00002671</color>
+    <color name="i_am_color_2672">#00002672</color>
+    <color name="i_am_color_2673">#00002673</color>
+    <color name="i_am_color_2674">#00002674</color>
+    <color name="i_am_color_2675">#00002675</color>
+    <color name="i_am_color_2676">#00002676</color>
+    <color name="i_am_color_2677">#00002677</color>
+    <color name="i_am_color_2678">#00002678</color>
+    <color name="i_am_color_2679">#00002679</color>
+    <color name="i_am_color_267a">#0000267a</color>
+    <color name="i_am_color_267b">#0000267b</color>
+    <color name="i_am_color_267c">#0000267c</color>
+    <color name="i_am_color_267d">#0000267d</color>
+    <color name="i_am_color_267e">#0000267e</color>
+    <color name="i_am_color_267f">#0000267f</color>
+    <color name="i_am_color_2680">#00002680</color>
+    <color name="i_am_color_2681">#00002681</color>
+    <color name="i_am_color_2682">#00002682</color>
+    <color name="i_am_color_2683">#00002683</color>
+    <color name="i_am_color_2684">#00002684</color>
+    <color name="i_am_color_2685">#00002685</color>
+    <color name="i_am_color_2686">#00002686</color>
+    <color name="i_am_color_2687">#00002687</color>
+    <color name="i_am_color_2688">#00002688</color>
+    <color name="i_am_color_2689">#00002689</color>
+    <color name="i_am_color_268a">#0000268a</color>
+    <color name="i_am_color_268b">#0000268b</color>
+    <color name="i_am_color_268c">#0000268c</color>
+    <color name="i_am_color_268d">#0000268d</color>
+    <color name="i_am_color_268e">#0000268e</color>
+    <color name="i_am_color_268f">#0000268f</color>
+    <color name="i_am_color_2690">#00002690</color>
+    <color name="i_am_color_2691">#00002691</color>
+    <color name="i_am_color_2692">#00002692</color>
+    <color name="i_am_color_2693">#00002693</color>
+    <color name="i_am_color_2694">#00002694</color>
+    <color name="i_am_color_2695">#00002695</color>
+    <color name="i_am_color_2696">#00002696</color>
+    <color name="i_am_color_2697">#00002697</color>
+    <color name="i_am_color_2698">#00002698</color>
+    <color name="i_am_color_2699">#00002699</color>
+    <color name="i_am_color_269a">#0000269a</color>
+    <color name="i_am_color_269b">#0000269b</color>
+    <color name="i_am_color_269c">#0000269c</color>
+    <color name="i_am_color_269d">#0000269d</color>
+    <color name="i_am_color_269e">#0000269e</color>
+    <color name="i_am_color_269f">#0000269f</color>
+    <color name="i_am_color_26a0">#000026a0</color>
+    <color name="i_am_color_26a1">#000026a1</color>
+    <color name="i_am_color_26a2">#000026a2</color>
+    <color name="i_am_color_26a3">#000026a3</color>
+    <color name="i_am_color_26a4">#000026a4</color>
+    <color name="i_am_color_26a5">#000026a5</color>
+    <color name="i_am_color_26a6">#000026a6</color>
+    <color name="i_am_color_26a7">#000026a7</color>
+    <color name="i_am_color_26a8">#000026a8</color>
+    <color name="i_am_color_26a9">#000026a9</color>
+    <color name="i_am_color_26aa">#000026aa</color>
+    <color name="i_am_color_26ab">#000026ab</color>
+    <color name="i_am_color_26ac">#000026ac</color>
+    <color name="i_am_color_26ad">#000026ad</color>
+    <color name="i_am_color_26ae">#000026ae</color>
+    <color name="i_am_color_26af">#000026af</color>
+    <color name="i_am_color_26b0">#000026b0</color>
+    <color name="i_am_color_26b1">#000026b1</color>
+    <color name="i_am_color_26b2">#000026b2</color>
+    <color name="i_am_color_26b3">#000026b3</color>
+    <color name="i_am_color_26b4">#000026b4</color>
+    <color name="i_am_color_26b5">#000026b5</color>
+    <color name="i_am_color_26b6">#000026b6</color>
+    <color name="i_am_color_26b7">#000026b7</color>
+    <color name="i_am_color_26b8">#000026b8</color>
+    <color name="i_am_color_26b9">#000026b9</color>
+    <color name="i_am_color_26ba">#000026ba</color>
+    <color name="i_am_color_26bb">#000026bb</color>
+    <color name="i_am_color_26bc">#000026bc</color>
+    <color name="i_am_color_26bd">#000026bd</color>
+    <color name="i_am_color_26be">#000026be</color>
+    <color name="i_am_color_26bf">#000026bf</color>
+    <color name="i_am_color_26c0">#000026c0</color>
+    <color name="i_am_color_26c1">#000026c1</color>
+    <color name="i_am_color_26c2">#000026c2</color>
+    <color name="i_am_color_26c3">#000026c3</color>
+    <color name="i_am_color_26c4">#000026c4</color>
+    <color name="i_am_color_26c5">#000026c5</color>
+    <color name="i_am_color_26c6">#000026c6</color>
+    <color name="i_am_color_26c7">#000026c7</color>
+    <color name="i_am_color_26c8">#000026c8</color>
+    <color name="i_am_color_26c9">#000026c9</color>
+    <color name="i_am_color_26ca">#000026ca</color>
+    <color name="i_am_color_26cb">#000026cb</color>
+    <color name="i_am_color_26cc">#000026cc</color>
+    <color name="i_am_color_26cd">#000026cd</color>
+    <color name="i_am_color_26ce">#000026ce</color>
+    <color name="i_am_color_26cf">#000026cf</color>
+    <color name="i_am_color_26d0">#000026d0</color>
+    <color name="i_am_color_26d1">#000026d1</color>
+    <color name="i_am_color_26d2">#000026d2</color>
+    <color name="i_am_color_26d3">#000026d3</color>
+    <color name="i_am_color_26d4">#000026d4</color>
+    <color name="i_am_color_26d5">#000026d5</color>
+    <color name="i_am_color_26d6">#000026d6</color>
+    <color name="i_am_color_26d7">#000026d7</color>
+    <color name="i_am_color_26d8">#000026d8</color>
+    <color name="i_am_color_26d9">#000026d9</color>
+    <color name="i_am_color_26da">#000026da</color>
+    <color name="i_am_color_26db">#000026db</color>
+    <color name="i_am_color_26dc">#000026dc</color>
+    <color name="i_am_color_26dd">#000026dd</color>
+    <color name="i_am_color_26de">#000026de</color>
+    <color name="i_am_color_26df">#000026df</color>
+    <color name="i_am_color_26e0">#000026e0</color>
+    <color name="i_am_color_26e1">#000026e1</color>
+    <color name="i_am_color_26e2">#000026e2</color>
+    <color name="i_am_color_26e3">#000026e3</color>
+    <color name="i_am_color_26e4">#000026e4</color>
+    <color name="i_am_color_26e5">#000026e5</color>
+    <color name="i_am_color_26e6">#000026e6</color>
+    <color name="i_am_color_26e7">#000026e7</color>
+    <color name="i_am_color_26e8">#000026e8</color>
+    <color name="i_am_color_26e9">#000026e9</color>
+    <color name="i_am_color_26ea">#000026ea</color>
+    <color name="i_am_color_26eb">#000026eb</color>
+    <color name="i_am_color_26ec">#000026ec</color>
+    <color name="i_am_color_26ed">#000026ed</color>
+    <color name="i_am_color_26ee">#000026ee</color>
+    <color name="i_am_color_26ef">#000026ef</color>
+    <color name="i_am_color_26f0">#000026f0</color>
+    <color name="i_am_color_26f1">#000026f1</color>
+    <color name="i_am_color_26f2">#000026f2</color>
+    <color name="i_am_color_26f3">#000026f3</color>
+    <color name="i_am_color_26f4">#000026f4</color>
+    <color name="i_am_color_26f5">#000026f5</color>
+    <color name="i_am_color_26f6">#000026f6</color>
+    <color name="i_am_color_26f7">#000026f7</color>
+    <color name="i_am_color_26f8">#000026f8</color>
+    <color name="i_am_color_26f9">#000026f9</color>
+    <color name="i_am_color_26fa">#000026fa</color>
+    <color name="i_am_color_26fb">#000026fb</color>
+    <color name="i_am_color_26fc">#000026fc</color>
+    <color name="i_am_color_26fd">#000026fd</color>
+    <color name="i_am_color_26fe">#000026fe</color>
+    <color name="i_am_color_26ff">#000026ff</color>
+    <color name="i_am_color_2700">#00002700</color>
+    <color name="i_am_color_2701">#00002701</color>
+    <color name="i_am_color_2702">#00002702</color>
+    <color name="i_am_color_2703">#00002703</color>
+    <color name="i_am_color_2704">#00002704</color>
+    <color name="i_am_color_2705">#00002705</color>
+    <color name="i_am_color_2706">#00002706</color>
+    <color name="i_am_color_2707">#00002707</color>
+    <color name="i_am_color_2708">#00002708</color>
+    <color name="i_am_color_2709">#00002709</color>
+    <color name="i_am_color_270a">#0000270a</color>
+    <color name="i_am_color_270b">#0000270b</color>
+    <color name="i_am_color_270c">#0000270c</color>
+    <color name="i_am_color_270d">#0000270d</color>
+    <color name="i_am_color_270e">#0000270e</color>
+    <color name="i_am_color_270f">#0000270f</color>
+    <color name="i_am_color_2710">#00002710</color>
+</resources>
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
index 7216244..54b79b4 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
@@ -37,6 +37,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.Random;
 
 /**
  * Benchmarks for {@link android.content.res.Resources}.
@@ -222,4 +223,24 @@
             state.resumeTiming();
         }
     }
-}
\ No newline at end of file
+
+    @Test
+    public void getIdentifier() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final Random random = new Random(System.currentTimeMillis());
+        final Context context = InstrumentationRegistry.getTargetContext();
+        final String packageName = context.getPackageName();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final int expectedInteger = random.nextInt(10001);
+            final String expectedString = Integer.toHexString(expectedInteger);
+            final String entryName = "i_am_color_" + expectedString;
+            state.resumeTiming();
+
+            final int resIdentifier = mRes.getIdentifier(entryName, "color", packageName);
+            if (resIdentifier == 0) {
+                fail("Color \"" + entryName + "\" is not found");
+            }
+        }
+    }
+}
diff --git a/apex/OWNERS b/apex/OWNERS
index b3e81b9..e867586 100644
--- a/apex/OWNERS
+++ b/apex/OWNERS
@@ -1 +1 @@
-file:platform/packages/modules/common:/OWNERS
+file:platform/packages/modules/common:/OWNERS #{LAST_RESORT_SUGGESTION}
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index a1a46af..161a317 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -235,7 +235,6 @@
     public static final int REASON_LOCKED_BOOT_COMPLETED = 202;
     /**
      * All Bluetooth broadcasts.
-     * @hide
      */
     public static final int REASON_BLUETOOTH_BROADCAST = 203;
     /**
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
deleted file mode 100644
index 1a710a98b..0000000
--- a/apex/media/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
-    default_visibility: [
-        ":__subpackages__",
-        "//frameworks/av/apex",
-        "//frameworks/av/apex/testing",
-    ],
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-sdk {
-    name: "media-module-sdk",
-    bootclasspath_fragments: ["com.android.media-bootclasspath-fragment"],
-    systemserverclasspath_fragments: ["com.android.media-systemserverclasspath-fragment"],
-    java_sdk_libs: [
-        "framework-media",
-    ],
-}
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
deleted file mode 100644
index bed3895..0000000
--- a/apex/media/OWNERS
+++ /dev/null
@@ -1,13 +0,0 @@
-# Bug component: 1344
-hdmoon@google.com
-hkuang@google.com
-jinpark@google.com
-klhyun@google.com
-lnilsson@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
-
-# media reliability team packages/delivers the media mainline builds.
-include platform/frameworks/av:/media/janitors/reliability_mainline_OWNERS
diff --git a/apex/media/aidl/Android.bp b/apex/media/aidl/Android.bp
deleted file mode 100644
index 545a0cd..0000000
--- a/apex/media/aidl/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
-    name: "stable-media-aidl-srcs",
-    srcs: ["stable/**/*.aidl"],
-    path: "stable",
-}
-
-filegroup {
-    name: "private-media-aidl-srcs",
-    srcs: ["private/**/I*.aidl"],
-    path: "private",
-}
-
-filegroup {
-    name: "media-aidl-srcs",
-    srcs: [
-        ":private-media-aidl-srcs",
-        ":stable-media-aidl-srcs",
-    ],
-}
diff --git a/apex/media/aidl/private/android/media/Controller2Link.aidl b/apex/media/aidl/private/android/media/Controller2Link.aidl
deleted file mode 100644
index 64edafc..0000000
--- a/apex/media/aidl/private/android/media/Controller2Link.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-parcelable Controller2Link;
diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
deleted file mode 100644
index fb3172b..0000000
--- a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-import android.media.Session2Token;
-import android.media.IMediaCommunicationServiceCallback;
-import android.media.MediaParceledListSlice;
-
-/** {@hide} */
-interface IMediaCommunicationService {
-    void notifySession2Created(in Session2Token sessionToken);
-    boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
-    MediaParceledListSlice getSession2Tokens(int userId);
-
-    void registerCallback(IMediaCommunicationServiceCallback callback, String packageName);
-    void unregisterCallback(IMediaCommunicationServiceCallback callback);
-}
-
diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl
deleted file mode 100644
index e347ebf..0000000
--- a/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * 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.media;
-
-import android.media.Session2Token;
-import android.media.MediaParceledListSlice;
-
-/** {@hide} */
-oneway interface IMediaCommunicationServiceCallback {
-    void onSession2Created(in Session2Token token);
-    void onSession2Changed(in MediaParceledListSlice tokens);
-}
-
diff --git a/apex/media/aidl/private/android/media/IMediaController2.aidl b/apex/media/aidl/private/android/media/IMediaController2.aidl
deleted file mode 100644
index 42c6e70..0000000
--- a/apex/media/aidl/private/android/media/IMediaController2.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.media.Session2Command;
-
-/**
- * Interface from MediaSession2 to MediaController2.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from session to make session owner(s) frozen.
- * @hide
- */
- // Code for AML only
-oneway interface IMediaController2 {
-    void notifyConnected(int seq, in Bundle connectionResult) = 0;
-    void notifyDisconnected(int seq) = 1;
-    void notifyPlaybackActiveChanged(int seq, boolean playbackActive) = 2;
-    void sendSessionCommand(int seq, in Session2Command command, in Bundle args,
-            in ResultReceiver resultReceiver) = 3;
-    void cancelSessionCommand(int seq) = 4;
-    // Next Id : 5
-}
diff --git a/apex/media/aidl/private/android/media/IMediaSession2.aidl b/apex/media/aidl/private/android/media/IMediaSession2.aidl
deleted file mode 100644
index 26e717b..0000000
--- a/apex/media/aidl/private/android/media/IMediaSession2.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.media.Controller2Link;
-import android.media.Session2Command;
-
-/**
- * Interface from MediaController2 to MediaSession2.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from session to make session owner(s) frozen.
- * @hide
- */
- // Code for AML only
-oneway interface IMediaSession2 {
-    void connect(in Controller2Link caller, int seq, in Bundle connectionRequest) = 0;
-    void disconnect(in Controller2Link caller, int seq) = 1;
-    void sendSessionCommand(in Controller2Link caller, int seq, in Session2Command sessionCommand,
-            in Bundle args, in ResultReceiver resultReceiver) = 2;
-    void cancelSessionCommand(in Controller2Link caller, int seq) = 3;
-    // Next Id : 4
-}
diff --git a/apex/media/aidl/private/android/media/IMediaSession2Service.aidl b/apex/media/aidl/private/android/media/IMediaSession2Service.aidl
deleted file mode 100644
index 10ac1be..0000000
--- a/apex/media/aidl/private/android/media/IMediaSession2Service.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Bundle;
-import android.media.Controller2Link;
-
-/**
- * Interface from MediaController2 to MediaSession2Service.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from controller to make controller owner(s) frozen.
- * @hide
- */
-oneway interface IMediaSession2Service {
-    void connect(in Controller2Link caller, int seq, in Bundle connectionRequest) = 0;
-    // Next Id : 1
-}
diff --git a/apex/media/aidl/private/android/media/Session2Command.aidl b/apex/media/aidl/private/android/media/Session2Command.aidl
deleted file mode 100644
index 43a7b12..0000000
--- a/apex/media/aidl/private/android/media/Session2Command.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-parcelable Session2Command;
diff --git a/apex/media/aidl/stable/android/media/MediaParceledListSlice.aidl b/apex/media/aidl/stable/android/media/MediaParceledListSlice.aidl
deleted file mode 100644
index 92d673f..0000000
--- a/apex/media/aidl/stable/android/media/MediaParceledListSlice.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-parcelable MediaParceledListSlice<T>;
diff --git a/apex/media/aidl/stable/android/media/Session2Token.aidl b/apex/media/aidl/stable/android/media/Session2Token.aidl
deleted file mode 100644
index c5980e9..0000000
--- a/apex/media/aidl/stable/android/media/Session2Token.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-parcelable Session2Token;
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
deleted file mode 100644
index d963e68..0000000
--- a/apex/media/framework/Android.bp
+++ /dev/null
@@ -1,164 +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 {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library {
-    name: "updatable-media",
-
-    srcs: [
-        ":updatable-media-srcs",
-    ],
-
-    permitted_packages: [
-        "android.media",
-    ],
-
-    optimize: {
-        enabled: true,
-        shrink: true,
-        proguard_flags_files: ["updatable-media-proguard.flags"],
-    },
-
-    installable: true,
-
-    sdk_version: "module_current",
-    libs: [
-        "androidx.annotation_annotation",
-        "framework-annotations-lib",
-    ],
-    static_libs: [
-        "exoplayer2-extractor",
-        "mediatranscoding_aidl_interface-java",
-        "modules-annotation-minsdk",
-        "modules-utils-build",
-    ],
-    jarjar_rules: "jarjar_rules.txt",
-
-    plugins: ["java_api_finder"],
-
-    hostdex: true, // for hiddenapi check
-    apex_available: [
-        "com.android.media",
-        "test_com.android.media",
-    ],
-    min_sdk_version: "29",
-    visibility: [
-        "//frameworks/av/apex:__subpackages__",
-        "//frameworks/base", // For framework-all
-        "//frameworks/base/apex/media/service",
-    ],
-}
-
-filegroup {
-    name: "updatable-media-srcs",
-    srcs: [
-        "java/android/media/MediaFrameworkInitializer.java",
-        ":media-aidl-srcs",
-        ":mediaparceledlistslice-java-srcs",
-        ":mediaparser-srcs",
-        ":mediasession2-java-srcs",
-        ":mediatranscoding-srcs",
-    ],
-    visibility: ["//frameworks/base"],
-}
-
-filegroup {
-    name: "mediasession2-java-srcs",
-    srcs: [
-        "java/android/media/Controller2Link.java",
-        "java/android/media/MediaConstants.java",
-        "java/android/media/MediaController2.java",
-        "java/android/media/MediaSession2.java",
-        "java/android/media/MediaSession2Service.java",
-        "java/android/media/Session2Command.java",
-        "java/android/media/Session2CommandGroup.java",
-        "java/android/media/Session2Link.java",
-        "java/android/media/Session2Token.java",
-        "java/android/media/MediaCommunicationManager.java",
-    ],
-    path: "java",
-}
-
-filegroup {
-    name: "mediaparceledlistslice-java-srcs",
-    srcs: [
-        "java/android/media/MediaParceledListSlice.java",
-        "java/android/media/BaseMediaParceledListSlice.java",
-    ],
-    path: "java",
-}
-
-filegroup {
-    name: "mediaparser-srcs",
-    srcs: [
-        "java/android/media/MediaParser.java",
-    ],
-    path: "java",
-}
-
-filegroup {
-    name: "mediatranscoding-srcs",
-    srcs: [
-        "java/android/media/ApplicationMediaCapabilities.java",
-        "java/android/media/MediaFeature.java",
-        "java/android/media/MediaTranscodingManager.java",
-    ],
-    path: "java",
-}
-
-java_sdk_library {
-    name: "framework-media",
-    defaults: ["framework-module-defaults"],
-
-    // This is only used to define the APIs for updatable-media.
-    api_only: true,
-
-    srcs: [
-        ":updatable-media-srcs",
-    ],
-
-    impl_library_visibility: ["//frameworks/av/apex:__subpackages__"],
-}
-
-cc_library_shared {
-    name: "libmediaparser-jni",
-    srcs: [
-        "jni/android_media_MediaParserJNI.cpp",
-    ],
-    header_libs: ["jni_headers"],
-    shared_libs: [
-        "libandroid",
-        "liblog",
-        "libmediametrics",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-unused-parameter",
-        "-Wunreachable-code",
-        "-Wunused",
-    ],
-    apex_available: [
-        "com.android.media",
-    ],
-    min_sdk_version: "29",
-}
diff --git a/apex/media/framework/TEST_MAPPING b/apex/media/framework/TEST_MAPPING
deleted file mode 100644
index 3d21914..0000000
--- a/apex/media/framework/TEST_MAPPING
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "CtsMediaParserTestCases"
-    },
-    {
-      "name": "CtsMediaParserHostTestCases"
-    }
-  ]
-}
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
deleted file mode 100644
index b7d7ed8..0000000
--- a/apex/media/framework/api/current.txt
+++ /dev/null
@@ -1,267 +0,0 @@
-// Signature format: 2.0
-package android.media {
-
-  public final class ApplicationMediaCapabilities implements android.os.Parcelable {
-    method @NonNull public static android.media.ApplicationMediaCapabilities createFromXml(@NonNull org.xmlpull.v1.XmlPullParser);
-    method public int describeContents();
-    method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
-    method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
-    method @NonNull public java.util.List<java.lang.String> getUnsupportedHdrTypes();
-    method @NonNull public java.util.List<java.lang.String> getUnsupportedVideoMimeTypes();
-    method public boolean isFormatSpecified(@NonNull String);
-    method public boolean isHdrTypeSupported(@NonNull String);
-    method public boolean isVideoMimeTypeSupported(@NonNull String);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
-  }
-
-  public static final class ApplicationMediaCapabilities.Builder {
-    ctor public ApplicationMediaCapabilities.Builder();
-    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
-    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
-    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedHdrType(@NonNull String);
-    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedVideoMimeType(@NonNull String);
-    method @NonNull public android.media.ApplicationMediaCapabilities build();
-  }
-
-  public class MediaCommunicationManager {
-    method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
-    method @IntRange(from=1) public int getVersion();
-  }
-
-  public class MediaController2 implements java.lang.AutoCloseable {
-    method public void cancelSessionCommand(@NonNull Object);
-    method public void close();
-    method @Nullable public android.media.Session2Token getConnectedToken();
-    method public boolean isPlaybackActive();
-    method @NonNull public Object sendSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
-  }
-
-  public static final class MediaController2.Builder {
-    ctor public MediaController2.Builder(@NonNull android.content.Context, @NonNull android.media.Session2Token);
-    method @NonNull public android.media.MediaController2 build();
-    method @NonNull public android.media.MediaController2.Builder setConnectionHints(@NonNull android.os.Bundle);
-    method @NonNull public android.media.MediaController2.Builder setControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaController2.ControllerCallback);
-  }
-
-  public abstract static class MediaController2.ControllerCallback {
-    ctor public MediaController2.ControllerCallback();
-    method public void onCommandResult(@NonNull android.media.MediaController2, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
-    method public void onConnected(@NonNull android.media.MediaController2, @NonNull android.media.Session2CommandGroup);
-    method public void onDisconnected(@NonNull android.media.MediaController2);
-    method public void onPlaybackActiveChanged(@NonNull android.media.MediaController2, boolean);
-    method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaController2, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
-  }
-
-  public final class MediaFeature {
-    ctor public MediaFeature();
-  }
-
-  public static final class MediaFeature.HdrType {
-    field public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
-    field public static final String HDR10 = "android.media.feature.hdr.hdr10";
-    field public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
-    field public static final String HLG = "android.media.feature.hdr.hlg";
-  }
-
-  public final class MediaParser {
-    method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
-    method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
-    method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
-    method @NonNull public android.media.metrics.LogSessionId getLogSessionId();
-    method @NonNull public String getParserName();
-    method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat);
-    method public void release();
-    method public void seek(@NonNull android.media.MediaParser.SeekPoint);
-    method public void setLogSessionId(@NonNull android.media.metrics.LogSessionId);
-    method @NonNull public android.media.MediaParser setParameter(@NonNull String, @NonNull Object);
-    method public boolean supportsParameter(@NonNull String);
-    field public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING = "android.media.mediaparser.adts.enableCbrSeeking";
-    field public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "android.media.mediaparser.amr.enableCbrSeeking";
-    field public static final String PARAMETER_FLAC_DISABLE_ID3 = "android.media.mediaparser.flac.disableId3";
-    field public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING = "android.media.mediaparser.matroska.disableCuesSeeking";
-    field public static final String PARAMETER_MP3_DISABLE_ID3 = "android.media.mediaparser.mp3.disableId3";
-    field public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "android.media.mediaparser.mp3.enableCbrSeeking";
-    field public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING = "android.media.mediaparser.mp3.enableIndexSeeking";
-    field public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "android.media.mediaparser.mp4.ignoreEditLists";
-    field public static final String PARAMETER_MP4_IGNORE_TFDT_BOX = "android.media.mediaparser.mp4.ignoreTfdtBox";
-    field public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES = "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
-    field public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES = "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
-    field public static final String PARAMETER_TS_DETECT_ACCESS_UNITS = "android.media.mediaparser.ts.ignoreDetectAccessUnits";
-    field public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS = "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
-    field public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "android.media.mediaparser.ts.ignoreAacStream";
-    field public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "android.media.mediaparser.ts.ignoreAvcStream";
-    field public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM = "android.media.mediaparser.ts.ignoreSpliceInfoStream";
-    field public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
-    field public static final String PARSER_NAME_AC3 = "android.media.mediaparser.Ac3Parser";
-    field public static final String PARSER_NAME_AC4 = "android.media.mediaparser.Ac4Parser";
-    field public static final String PARSER_NAME_ADTS = "android.media.mediaparser.AdtsParser";
-    field public static final String PARSER_NAME_AMR = "android.media.mediaparser.AmrParser";
-    field public static final String PARSER_NAME_FLAC = "android.media.mediaparser.FlacParser";
-    field public static final String PARSER_NAME_FLV = "android.media.mediaparser.FlvParser";
-    field public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser";
-    field public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser";
-    field public static final String PARSER_NAME_MP3 = "android.media.mediaparser.Mp3Parser";
-    field public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser";
-    field public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
-    field public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
-    field public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
-    field public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
-    field public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
-    field public static final int SAMPLE_FLAG_DECODE_ONLY = -2147483648; // 0x80000000
-    field public static final int SAMPLE_FLAG_ENCRYPTED = 1073741824; // 0x40000000
-    field public static final int SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA = 268435456; // 0x10000000
-    field public static final int SAMPLE_FLAG_KEY_FRAME = 1; // 0x1
-    field public static final int SAMPLE_FLAG_LAST_SAMPLE = 536870912; // 0x20000000
-  }
-
-  public static interface MediaParser.InputReader {
-    method public long getLength();
-    method public long getPosition();
-    method public int read(@NonNull byte[], int, int) throws java.io.IOException;
-  }
-
-  public static interface MediaParser.OutputConsumer {
-    method public void onSampleCompleted(int, long, int, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
-    method public void onSampleDataFound(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException;
-    method public void onSeekMapFound(@NonNull android.media.MediaParser.SeekMap);
-    method public void onTrackCountFound(int);
-    method public void onTrackDataFound(int, @NonNull android.media.MediaParser.TrackData);
-  }
-
-  public static final class MediaParser.ParsingException extends java.io.IOException {
-  }
-
-  public static final class MediaParser.SeekMap {
-    method public long getDurationMicros();
-    method @NonNull public android.util.Pair<android.media.MediaParser.SeekPoint,android.media.MediaParser.SeekPoint> getSeekPoints(long);
-    method public boolean isSeekable();
-    field public static final int UNKNOWN_DURATION = -2147483648; // 0x80000000
-  }
-
-  public static final class MediaParser.SeekPoint {
-    field @NonNull public static final android.media.MediaParser.SeekPoint START;
-    field public final long position;
-    field public final long timeMicros;
-  }
-
-  public static interface MediaParser.SeekableInputReader extends android.media.MediaParser.InputReader {
-    method public void seekToPosition(long);
-  }
-
-  public static final class MediaParser.TrackData {
-    field @Nullable public final android.media.DrmInitData drmInitData;
-    field @NonNull public final android.media.MediaFormat mediaFormat;
-  }
-
-  public static final class MediaParser.UnrecognizedInputFormatException extends java.io.IOException {
-  }
-
-  public class MediaSession2 implements java.lang.AutoCloseable {
-    method public void broadcastSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
-    method public void cancelSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object);
-    method public void close();
-    method @NonNull public java.util.List<android.media.MediaSession2.ControllerInfo> getConnectedControllers();
-    method @NonNull public String getId();
-    method @NonNull public android.media.Session2Token getToken();
-    method public boolean isPlaybackActive();
-    method @NonNull public Object sendSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
-    method public void setPlaybackActive(boolean);
-  }
-
-  public static final class MediaSession2.Builder {
-    ctor public MediaSession2.Builder(@NonNull android.content.Context);
-    method @NonNull public android.media.MediaSession2 build();
-    method @NonNull public android.media.MediaSession2.Builder setExtras(@NonNull android.os.Bundle);
-    method @NonNull public android.media.MediaSession2.Builder setId(@NonNull String);
-    method @NonNull public android.media.MediaSession2.Builder setSessionActivity(@Nullable android.app.PendingIntent);
-    method @NonNull public android.media.MediaSession2.Builder setSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaSession2.SessionCallback);
-  }
-
-  public static final class MediaSession2.ControllerInfo {
-    method @NonNull public android.os.Bundle getConnectionHints();
-    method @NonNull public String getPackageName();
-    method @NonNull public android.media.session.MediaSessionManager.RemoteUserInfo getRemoteUserInfo();
-    method public int getUid();
-  }
-
-  public abstract static class MediaSession2.SessionCallback {
-    ctor public MediaSession2.SessionCallback();
-    method public void onCommandResult(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
-    method @Nullable public android.media.Session2CommandGroup onConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
-    method public void onDisconnected(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
-    method public void onPostConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
-    method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
-  }
-
-  public abstract class MediaSession2Service extends android.app.Service {
-    ctor public MediaSession2Service();
-    method public final void addSession(@NonNull android.media.MediaSession2);
-    method @NonNull public final java.util.List<android.media.MediaSession2> getSessions();
-    method @CallSuper @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
-    method @Nullable public abstract android.media.MediaSession2 onGetSession(@NonNull android.media.MediaSession2.ControllerInfo);
-    method @Nullable public abstract android.media.MediaSession2Service.MediaNotification onUpdateNotification(@NonNull android.media.MediaSession2);
-    method public final void removeSession(@NonNull android.media.MediaSession2);
-    field public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";
-  }
-
-  public static class MediaSession2Service.MediaNotification {
-    ctor public MediaSession2Service.MediaNotification(int, @NonNull android.app.Notification);
-    method @NonNull public android.app.Notification getNotification();
-    method public int getNotificationId();
-  }
-
-  public final class Session2Command implements android.os.Parcelable {
-    ctor public Session2Command(int);
-    ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
-    method public int describeContents();
-    method public int getCommandCode();
-    method @Nullable public String getCustomAction();
-    method @Nullable public android.os.Bundle getCustomExtras();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Command> CREATOR;
-  }
-
-  public static final class Session2Command.Result {
-    ctor public Session2Command.Result(int, @Nullable android.os.Bundle);
-    method public int getResultCode();
-    method @Nullable public android.os.Bundle getResultData();
-    field public static final int RESULT_ERROR_UNKNOWN_ERROR = -1; // 0xffffffff
-    field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
-    field public static final int RESULT_SUCCESS = 0; // 0x0
-  }
-
-  public final class Session2CommandGroup implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public java.util.Set<android.media.Session2Command> getCommands();
-    method public boolean hasCommand(@NonNull android.media.Session2Command);
-    method public boolean hasCommand(int);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2CommandGroup> CREATOR;
-  }
-
-  public static final class Session2CommandGroup.Builder {
-    ctor public Session2CommandGroup.Builder();
-    ctor public Session2CommandGroup.Builder(@NonNull android.media.Session2CommandGroup);
-    method @NonNull public android.media.Session2CommandGroup.Builder addCommand(@NonNull android.media.Session2Command);
-    method @NonNull public android.media.Session2CommandGroup build();
-    method @NonNull public android.media.Session2CommandGroup.Builder removeCommand(@NonNull android.media.Session2Command);
-  }
-
-  public final class Session2Token implements android.os.Parcelable {
-    ctor public Session2Token(@NonNull android.content.Context, @NonNull android.content.ComponentName);
-    method public int describeContents();
-    method @NonNull public android.os.Bundle getExtras();
-    method @NonNull public String getPackageName();
-    method @Nullable public String getServiceName();
-    method public int getType();
-    method public int getUid();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Token> CREATOR;
-    field public static final int TYPE_SESSION = 0; // 0x0
-    field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
-  }
-
-}
-
diff --git a/apex/media/framework/api/module-lib-current.txt b/apex/media/framework/api/module-lib-current.txt
deleted file mode 100644
index eb6397a1..0000000
--- a/apex/media/framework/api/module-lib-current.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-// Signature format: 2.0
-package android.media {
-
-  public class MediaCommunicationManager {
-    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaCommunicationManager.SessionCallback);
-    method public void unregisterSessionCallback(@NonNull android.media.MediaCommunicationManager.SessionCallback);
-  }
-
-  public static interface MediaCommunicationManager.SessionCallback {
-    method public default void onSession2TokenCreated(@NonNull android.media.Session2Token);
-    method public default void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
-  }
-
-  public class MediaFrameworkInitializer {
-    method public static void registerServiceWrappers();
-    method public static void setMediaServiceManager(@NonNull android.media.MediaServiceManager);
-  }
-
-  @Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
-    ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
-    method @Deprecated public int describeContents();
-    method @Deprecated @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
-    method @Deprecated public java.util.List<T> getList();
-    method @Deprecated public void setInlineCountLimit(int);
-    method @Deprecated public void writeToParcel(android.os.Parcel, int);
-    field @Deprecated @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
-  }
-
-}
-
diff --git a/apex/media/framework/api/module-lib-removed.txt b/apex/media/framework/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/framework/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
deleted file mode 100644
index 6eea769..0000000
--- a/apex/media/framework/api/system-current.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-// Signature format: 2.0
-package android.media {
-
-  public final class MediaTranscodingManager {
-    method @Nullable public android.media.MediaTranscodingManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodingManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodingManager.OnTranscodingFinishedListener);
-  }
-
-  @java.lang.FunctionalInterface public static interface MediaTranscodingManager.OnTranscodingFinishedListener {
-    method public void onTranscodingFinished(@NonNull android.media.MediaTranscodingManager.TranscodingSession);
-  }
-
-  public abstract static class MediaTranscodingManager.TranscodingRequest {
-    method public int getClientPid();
-    method public int getClientUid();
-    method @Nullable public android.os.ParcelFileDescriptor getDestinationFileDescriptor();
-    method @NonNull public android.net.Uri getDestinationUri();
-    method @Nullable public android.os.ParcelFileDescriptor getSourceFileDescriptor();
-    method @NonNull public android.net.Uri getSourceUri();
-  }
-
-  public static class MediaTranscodingManager.TranscodingRequest.VideoFormatResolver {
-    ctor public MediaTranscodingManager.TranscodingRequest.VideoFormatResolver(@NonNull android.media.ApplicationMediaCapabilities, @NonNull android.media.MediaFormat);
-    method @Nullable public android.media.MediaFormat resolveVideoFormat();
-    method public boolean shouldTranscode();
-  }
-
-  public static final class MediaTranscodingManager.TranscodingSession {
-    method public boolean addClientUid(int);
-    method public void cancel();
-    method @NonNull public java.util.List<java.lang.Integer> getClientUids();
-    method public int getErrorCode();
-    method @IntRange(from=0, to=100) public int getProgress();
-    method public int getResult();
-    method public int getSessionId();
-    method public int getStatus();
-    method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodingManager.TranscodingSession.OnProgressUpdateListener);
-    field public static final int ERROR_DROPPED_BY_SERVICE = 1; // 0x1
-    field public static final int ERROR_NONE = 0; // 0x0
-    field public static final int ERROR_SERVICE_DIED = 2; // 0x2
-    field public static final int RESULT_CANCELED = 4; // 0x4
-    field public static final int RESULT_ERROR = 3; // 0x3
-    field public static final int RESULT_NONE = 1; // 0x1
-    field public static final int RESULT_SUCCESS = 2; // 0x2
-    field public static final int STATUS_FINISHED = 3; // 0x3
-    field public static final int STATUS_PAUSED = 4; // 0x4
-    field public static final int STATUS_PENDING = 1; // 0x1
-    field public static final int STATUS_RUNNING = 2; // 0x2
-  }
-
-  @java.lang.FunctionalInterface public static interface MediaTranscodingManager.TranscodingSession.OnProgressUpdateListener {
-    method public void onProgressUpdate(@NonNull android.media.MediaTranscodingManager.TranscodingSession, @IntRange(from=0, to=100) int);
-  }
-
-  public static final class MediaTranscodingManager.VideoTranscodingRequest extends android.media.MediaTranscodingManager.TranscodingRequest {
-    method @NonNull public android.media.MediaFormat getVideoTrackFormat();
-  }
-
-  public static final class MediaTranscodingManager.VideoTranscodingRequest.Builder {
-    ctor public MediaTranscodingManager.VideoTranscodingRequest.Builder(@NonNull android.net.Uri, @NonNull android.net.Uri, @NonNull android.media.MediaFormat);
-    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest build();
-    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setClientPid(int);
-    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setClientUid(int);
-    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setDestinationFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
-    method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setSourceFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
-  }
-
-}
-
diff --git a/apex/media/framework/api/system-removed.txt b/apex/media/framework/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/framework/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/framework/jarjar_rules.txt b/apex/media/framework/jarjar_rules.txt
deleted file mode 100644
index 91489dc..0000000
--- a/apex/media/framework/jarjar_rules.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rule com.android.modules.** android.media.internal.@1
-rule com.google.android.exoplayer2.** android.media.internal.exo.@1
diff --git a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
deleted file mode 100644
index 97fa0ec..0000000
--- a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
+++ /dev/null
@@ -1,626 +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.media;
-
-import android.annotation.NonNull;
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import com.android.modules.annotation.MinSdk;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- ApplicationMediaCapabilities is an immutable class that encapsulates an application's capabilities
- for handling newer video codec format and media features.
-
- <p>
- Android 12 introduces Compatible media transcoding feature.  See
- <a href="https://developer.android.com/about/versions/12/features#compatible_media_transcoding">
- Compatible media transcoding</a>. By default, Android assumes apps can support playback of all
- media formats. Apps that would like to request that media be transcoded into a more compatible
- format should declare their media capabilities in a media_capabilities.xml resource file and add it
- as a property tag in the AndroidManifest.xml file. Here is a example:
- <pre>
- {@code
- <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-     <format android:name="HEVC" supported="true"/>
-     <format android:name="HDR10" supported="false"/>
-     <format android:name="HDR10Plus" supported="false"/>
- </media-capabilities>
- }
- </pre>
- The ApplicationMediaCapabilities class is generated from this xml and used by the platform to
- represent an application's media capabilities in order to determine whether modern media files need
- to be transcoded for that application.
- </p>
-
- <p>
- ApplicationMediaCapabilities objects can also be built by applications at runtime for use with
- {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)} to provide more
- control over the transcoding that is built into the platform. ApplicationMediaCapabilities
- provided by applications at runtime like this override the default manifest capabilities for that
- media access.The object could be build either through {@link #createFromXml(XmlPullParser)} or
- through the builder class {@link ApplicationMediaCapabilities.Builder}
-
- <h3> Video Codec Support</h3>
- <p>
- Newer video codes include HEVC, VP9 and AV1. Application only needs to indicate their support
- for newer format with this class as they are assumed to support older format like h.264.
-
- <h3>Capability of handling HDR(high dynamic range) video</h3>
- <p>
- There are four types of HDR video(Dolby-Vision, HDR10, HDR10+, HLG) supported by the platform,
- application will only need to specify individual types they supported.
- */
-@MinSdk(Build.VERSION_CODES.S)
-public final class ApplicationMediaCapabilities implements Parcelable {
-    private static final String TAG = "ApplicationMediaCapabilities";
-
-    /** List of supported video codec mime types. */
-    private Set<String> mSupportedVideoMimeTypes = new HashSet<>();
-
-    /** List of unsupported video codec mime types. */
-    private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
-
-    /** List of supported hdr types. */
-    private Set<String> mSupportedHdrTypes = new HashSet<>();
-
-    /** List of unsupported hdr types. */
-    private Set<String> mUnsupportedHdrTypes = new HashSet<>();
-
-    private boolean mIsSlowMotionSupported = false;
-
-    private ApplicationMediaCapabilities(Builder b) {
-        mSupportedVideoMimeTypes.addAll(b.getSupportedVideoMimeTypes());
-        mUnsupportedVideoMimeTypes.addAll(b.getUnsupportedVideoMimeTypes());
-        mSupportedHdrTypes.addAll(b.getSupportedHdrTypes());
-        mUnsupportedHdrTypes.addAll(b.getUnsupportedHdrTypes());
-        mIsSlowMotionSupported = b.mIsSlowMotionSupported;
-    }
-
-    /**
-     * Query if a video codec format is supported by the application.
-     * <p>
-     * If the application has not specified supporting the format or not, this will return false.
-     * Use {@link #isFormatSpecified(String)} to query if a format is specified or not.
-     *
-     * @param videoMime The mime type of the video codec format. Must be the one used in
-     * {@link MediaFormat#KEY_MIME}.
-     * @return true if application supports the video codec format, false otherwise.
-     */
-    public boolean isVideoMimeTypeSupported(
-            @NonNull String videoMime) {
-        if (mSupportedVideoMimeTypes.contains(videoMime.toLowerCase())) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Query if a HDR type is supported by the application.
-     * <p>
-     * If the application has not specified supporting the format or not, this will return false.
-     * Use {@link #isFormatSpecified(String)} to query if a format is specified or not.
-     *
-     * @param hdrType The type of the HDR format.
-     * @return true if application supports the HDR format, false otherwise.
-     */
-    public boolean isHdrTypeSupported(
-            @NonNull @MediaFeature.MediaHdrType String hdrType) {
-        if (mSupportedHdrTypes.contains(hdrType)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Query if a format is specified by the application.
-     * <p>
-     * The format could be either the video format or the hdr format.
-     *
-     * @param format The name of the format.
-     * @return true if application specifies the format, false otherwise.
-     */
-    public boolean isFormatSpecified(@NonNull String format) {
-        if (mSupportedVideoMimeTypes.contains(format) || mUnsupportedVideoMimeTypes.contains(format)
-                || mSupportedHdrTypes.contains(format) || mUnsupportedHdrTypes.contains(format)) {
-            return true;
-
-        }
-        return false;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        // Write out the supported video mime types.
-        dest.writeInt(mSupportedVideoMimeTypes.size());
-        for (String cap : mSupportedVideoMimeTypes) {
-            dest.writeString(cap);
-        }
-        // Write out the unsupported video mime types.
-        dest.writeInt(mUnsupportedVideoMimeTypes.size());
-        for (String cap : mUnsupportedVideoMimeTypes) {
-            dest.writeString(cap);
-        }
-        // Write out the supported hdr types.
-        dest.writeInt(mSupportedHdrTypes.size());
-        for (String cap : mSupportedHdrTypes) {
-            dest.writeString(cap);
-        }
-        // Write out the unsupported hdr types.
-        dest.writeInt(mUnsupportedHdrTypes.size());
-        for (String cap : mUnsupportedHdrTypes) {
-            dest.writeString(cap);
-        }
-        // Write out the supported slow motion.
-        dest.writeBoolean(mIsSlowMotionSupported);
-    }
-
-    @Override
-    public String toString() {
-        String caps = new String(
-                "Supported Video MimeTypes: " + mSupportedVideoMimeTypes.toString());
-        caps += "Unsupported Video MimeTypes: " + mUnsupportedVideoMimeTypes.toString();
-        caps += "Supported HDR types: " + mSupportedHdrTypes.toString();
-        caps += "Unsupported HDR types: " + mUnsupportedHdrTypes.toString();
-        caps += "Supported slow motion: " + mIsSlowMotionSupported;
-        return caps;
-    }
-
-    @NonNull
-    public static final Creator<ApplicationMediaCapabilities> CREATOR =
-            new Creator<ApplicationMediaCapabilities>() {
-                public ApplicationMediaCapabilities createFromParcel(Parcel in) {
-                    ApplicationMediaCapabilities.Builder builder =
-                            new ApplicationMediaCapabilities.Builder();
-
-                    // Parse supported video codec mime types.
-                    int count = in.readInt();
-                    for (int readCount = 0; readCount < count; ++readCount) {
-                        builder.addSupportedVideoMimeType(in.readString());
-                    }
-
-                    // Parse unsupported video codec mime types.
-                    count = in.readInt();
-                    for (int readCount = 0; readCount < count; ++readCount) {
-                        builder.addUnsupportedVideoMimeType(in.readString());
-                    }
-
-                    // Parse supported hdr types.
-                    count = in.readInt();
-                    for (int readCount = 0; readCount < count; ++readCount) {
-                        builder.addSupportedHdrType(in.readString());
-                    }
-
-                    // Parse unsupported hdr types.
-                    count = in.readInt();
-                    for (int readCount = 0; readCount < count; ++readCount) {
-                        builder.addUnsupportedHdrType(in.readString());
-                    }
-
-                    boolean supported = in.readBoolean();
-                    builder.setSlowMotionSupported(supported);
-
-                    return builder.build();
-                }
-
-                public ApplicationMediaCapabilities[] newArray(int size) {
-                    return new ApplicationMediaCapabilities[size];
-                }
-            };
-
-    /**
-     * Query the video codec mime types supported by the application.
-     * @return List of supported video codec mime types. The list will be empty if there are none.
-     */
-    @NonNull
-    public List<String> getSupportedVideoMimeTypes() {
-        return new ArrayList<>(mSupportedVideoMimeTypes);
-    }
-
-    /**
-     * Query the video codec mime types that are not supported by the application.
-     * @return List of unsupported video codec mime types. The list will be empty if there are none.
-     */
-    @NonNull
-    public List<String> getUnsupportedVideoMimeTypes() {
-        return new ArrayList<>(mUnsupportedVideoMimeTypes);
-    }
-
-    /**
-     * Query all hdr types that are supported by the application.
-     * @return List of supported hdr types. The list will be empty if there are none.
-     */
-    @NonNull
-    public List<String> getSupportedHdrTypes() {
-        return new ArrayList<>(mSupportedHdrTypes);
-    }
-
-    /**
-     * Query all hdr types that are not supported by the application.
-     * @return List of unsupported hdr types. The list will be empty if there are none.
-     */
-    @NonNull
-    public List<String> getUnsupportedHdrTypes()  {
-        return new ArrayList<>(mUnsupportedHdrTypes);
-    }
-
-    /**
-     * Whether handling of slow-motion video is supported
-     * @hide
-     */
-    public boolean isSlowMotionSupported() {
-        return mIsSlowMotionSupported;
-    }
-
-    /**
-     * Creates {@link ApplicationMediaCapabilities} from an xml.
-     *
-     * The xml's syntax is the same as the media_capabilities.xml used by the AndroidManifest.xml.
-     * <p> Here is an example:
-     *
-     * <pre>
-     * {@code
-     * <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
-     *     <format android:name="HEVC" supported="true"/>
-     *     <format android:name="HDR10" supported="false"/>
-     *     <format android:name="HDR10Plus" supported="false"/>
-     * </media-capabilities>
-     * }
-     * </pre>
-     * <p>
-     *
-     * @param xmlParser The underlying {@link XmlPullParser} that will read the xml.
-     * @return An ApplicationMediaCapabilities object.
-     * @throws UnsupportedOperationException if the capabilities in xml config are invalid or
-     * incompatible.
-     */
-    // TODO: Add developer.android.com link for the format of the xml.
-    @NonNull
-    public static ApplicationMediaCapabilities createFromXml(@NonNull XmlPullParser xmlParser) {
-        ApplicationMediaCapabilities.Builder builder = new ApplicationMediaCapabilities.Builder();
-        builder.parseXml(xmlParser);
-        return builder.build();
-    }
-
-    /**
-     * Builder class for {@link ApplicationMediaCapabilities} objects.
-     * Use this class to configure and create an ApplicationMediaCapabilities instance. Builder
-     * could be created from an existing ApplicationMediaCapabilities object, from a xml file or
-     * MediaCodecList.
-     * //TODO(hkuang): Add xml parsing support to the builder.
-     */
-    public final static class Builder {
-        /** List of supported video codec mime types. */
-        private Set<String> mSupportedVideoMimeTypes = new HashSet<>();
-
-        /** List of supported hdr types. */
-        private Set<String> mSupportedHdrTypes = new HashSet<>();
-
-        /** List of unsupported video codec mime types. */
-        private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
-
-        /** List of unsupported hdr types. */
-        private Set<String> mUnsupportedHdrTypes = new HashSet<>();
-
-        private boolean mIsSlowMotionSupported = false;
-
-        /* Map to save the format read from the xml. */
-        private Map<String, Boolean> mFormatSupportedMap =  new HashMap<String, Boolean>();
-
-        /**
-         * Constructs a new Builder with all the supports default to false.
-         */
-        public Builder() {
-        }
-
-        private void parseXml(@NonNull XmlPullParser xmlParser)
-                throws UnsupportedOperationException {
-            if (xmlParser == null) {
-                throw new IllegalArgumentException("XmlParser must not be null");
-            }
-
-            try {
-                while (xmlParser.next() != XmlPullParser.START_TAG) {
-                    continue;
-                }
-
-                // Validates the tag is "media-capabilities".
-                if (!xmlParser.getName().equals("media-capabilities")) {
-                    throw new UnsupportedOperationException("Invalid tag");
-                }
-
-                xmlParser.next();
-                while (xmlParser.getEventType() != XmlPullParser.END_TAG) {
-                    while (xmlParser.getEventType() != XmlPullParser.START_TAG) {
-                        if (xmlParser.getEventType() == XmlPullParser.END_DOCUMENT) {
-                            return;
-                        }
-                        xmlParser.next();
-                    }
-
-                    // Validates the tag is "format".
-                    if (xmlParser.getName().equals("format")) {
-                        parseFormatTag(xmlParser);
-                    } else {
-                        throw new UnsupportedOperationException("Invalid tag");
-                    }
-                    while (xmlParser.getEventType() != XmlPullParser.END_TAG) {
-                        xmlParser.next();
-                    }
-                    xmlParser.next();
-                }
-            } catch (XmlPullParserException xppe) {
-                throw new UnsupportedOperationException("Ill-formatted xml file");
-            } catch (java.io.IOException ioe) {
-                throw new UnsupportedOperationException("Unable to read xml file");
-            }
-        }
-
-        private void parseFormatTag(XmlPullParser xmlParser) {
-            String name = null;
-            String supported = null;
-            for (int i = 0; i < xmlParser.getAttributeCount(); i++) {
-                String attrName = xmlParser.getAttributeName(i);
-                if (attrName.equals("name")) {
-                    name = xmlParser.getAttributeValue(i);
-                } else if (attrName.equals("supported")) {
-                    supported = xmlParser.getAttributeValue(i);
-                } else {
-                    throw new UnsupportedOperationException("Invalid attribute name " + attrName);
-                }
-            }
-
-            if (name != null && supported != null) {
-                if (!supported.equals("true") && !supported.equals("false")) {
-                    throw new UnsupportedOperationException(
-                            ("Supported value must be either true or false"));
-                }
-                boolean isSupported = Boolean.parseBoolean(supported);
-
-                // Check if the format is already found before.
-                if (mFormatSupportedMap.get(name) != null && mFormatSupportedMap.get(name)
-                        != isSupported) {
-                    throw new UnsupportedOperationException(
-                            "Format: " + name + " has conflict supported value");
-                }
-
-                switch (name) {
-                    case "HEVC":
-                        if (isSupported) {
-                            mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
-                        } else {
-                            mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
-                        }
-                        break;
-                    case "VP9":
-                        if (isSupported) {
-                            mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
-                        } else {
-                            mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
-                        }
-                        break;
-                    case "AV1":
-                        if (isSupported) {
-                            mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
-                        } else {
-                            mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
-                        }
-                        break;
-                    case "HDR10":
-                        if (isSupported) {
-                            mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
-                        } else {
-                            mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
-                        }
-                        break;
-                    case "HDR10Plus":
-                        if (isSupported) {
-                            mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
-                        } else {
-                            mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
-                        }
-                        break;
-                    case "Dolby-Vision":
-                        if (isSupported) {
-                            mSupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
-                        } else {
-                            mUnsupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
-                        }
-                        break;
-                    case "HLG":
-                        if (isSupported) {
-                            mSupportedHdrTypes.add(MediaFeature.HdrType.HLG);
-                        } else {
-                            mUnsupportedHdrTypes.add(MediaFeature.HdrType.HLG);
-                        }
-                        break;
-                    case "SlowMotion":
-                        mIsSlowMotionSupported = isSupported;
-                        break;
-                    default:
-                        Log.w(TAG, "Invalid format name " + name);
-                }
-                // Save the name and isSupported into the map for validate later.
-                mFormatSupportedMap.put(name, isSupported);
-            } else {
-                throw new UnsupportedOperationException(
-                        "Format name and supported must both be specified");
-            }
-        }
-
-        /**
-         * Builds a {@link ApplicationMediaCapabilities} object.
-         *
-         * @return a new {@link ApplicationMediaCapabilities} instance successfully initialized
-         * with all the parameters set on this <code>Builder</code>.
-         * @throws UnsupportedOperationException if the parameters set on the
-         *                                       <code>Builder</code> were incompatible, or if they
-         *                                       are not supported by the
-         *                                       device.
-         */
-        @NonNull
-        public ApplicationMediaCapabilities build() {
-            Log.d(TAG,
-                    "Building ApplicationMediaCapabilities with: (Supported HDR: "
-                            + mSupportedHdrTypes.toString() + " Unsupported HDR: "
-                            + mUnsupportedHdrTypes.toString() + ") (Supported Codec: "
-                            + " " + mSupportedVideoMimeTypes.toString() + " Unsupported Codec:"
-                            + mUnsupportedVideoMimeTypes.toString() + ") "
-                            + mIsSlowMotionSupported);
-
-            // If hdr is supported, application must also support hevc.
-            if (!mSupportedHdrTypes.isEmpty() && !mSupportedVideoMimeTypes.contains(
-                    MediaFormat.MIMETYPE_VIDEO_HEVC)) {
-                throw new UnsupportedOperationException("Only support HEVC mime type");
-            }
-            return new ApplicationMediaCapabilities(this);
-        }
-
-        /**
-         * Adds a supported video codec mime type.
-         *
-         * @param codecMime Supported codec mime types. Must be one of the mime type defined
-         *                  in {@link MediaFormat}.
-         * @throws IllegalArgumentException if mime type is not valid.
-         */
-        @NonNull
-        public Builder addSupportedVideoMimeType(
-                @NonNull String codecMime) {
-            mSupportedVideoMimeTypes.add(codecMime);
-            return this;
-        }
-
-        private List<String> getSupportedVideoMimeTypes() {
-            return new ArrayList<>(mSupportedVideoMimeTypes);
-        }
-
-        private boolean isValidVideoCodecMimeType(@NonNull String codecMime) {
-            if (!codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)
-                    && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)
-                    && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) {
-                return false;
-            }
-            return true;
-        }
-
-        /**
-         * Adds an unsupported video codec mime type.
-         *
-         * @param codecMime Unsupported codec mime type. Must be one of the mime type defined
-         *                  in {@link MediaFormat}.
-         * @throws IllegalArgumentException if mime type is not valid.
-         */
-        @NonNull
-        public Builder addUnsupportedVideoMimeType(
-                @NonNull String codecMime) {
-            if (!isValidVideoCodecMimeType(codecMime)) {
-                throw new IllegalArgumentException("Invalid codec mime type: " + codecMime);
-            }
-            mUnsupportedVideoMimeTypes.add(codecMime);
-            return this;
-        }
-
-        private List<String> getUnsupportedVideoMimeTypes() {
-            return new ArrayList<>(mUnsupportedVideoMimeTypes);
-        }
-
-        /**
-         * Adds a supported hdr type.
-         *
-         * @param hdrType Supported hdr type. Must be one of the String defined in
-         *                {@link MediaFeature.HdrType}.
-         * @throws IllegalArgumentException if hdrType is not valid.
-         */
-        @NonNull
-        public Builder addSupportedHdrType(
-                @NonNull @MediaFeature.MediaHdrType String hdrType) {
-            if (!isValidVideoCodecHdrType(hdrType)) {
-                throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
-            }
-            mSupportedHdrTypes.add(hdrType);
-            return this;
-        }
-
-        private List<String> getSupportedHdrTypes() {
-            return new ArrayList<>(mSupportedHdrTypes);
-        }
-
-        private boolean isValidVideoCodecHdrType(@NonNull String hdrType) {
-            if (!hdrType.equals(MediaFeature.HdrType.DOLBY_VISION)
-                    && !hdrType.equals(MediaFeature.HdrType.HDR10)
-                    && !hdrType.equals(MediaFeature.HdrType.HDR10_PLUS)
-                    && !hdrType.equals(MediaFeature.HdrType.HLG)) {
-                return false;
-            }
-            return true;
-        }
-
-        /**
-         * Adds an unsupported hdr type.
-         *
-         * @param hdrType Unsupported hdr type. Must be one of the String defined in
-         *                {@link MediaFeature.HdrType}.
-         * @throws IllegalArgumentException if hdrType is not valid.
-         */
-        @NonNull
-        public Builder addUnsupportedHdrType(
-                @NonNull @MediaFeature.MediaHdrType String hdrType) {
-            if (!isValidVideoCodecHdrType(hdrType)) {
-                throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
-            }
-            mUnsupportedHdrTypes.add(hdrType);
-            return this;
-        }
-
-        private List<String> getUnsupportedHdrTypes() {
-            return new ArrayList<>(mUnsupportedHdrTypes);
-        }
-
-        /**
-         * Sets whether slow-motion video is supported.
-         * If an application indicates support for slow-motion, it is application's responsibility
-         * to parse the slow-motion videos using their own parser or using support library.
-         * @see android.media.MediaFormat#KEY_SLOW_MOTION_MARKERS
-         * @hide
-         */
-        @NonNull
-        public Builder setSlowMotionSupported(boolean slowMotionSupported) {
-            mIsSlowMotionSupported = slowMotionSupported;
-            return this;
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java b/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
deleted file mode 100644
index fb66609..0000000
--- a/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This is a copied version of BaseParceledListSlice in framework with hidden API usages
- * removed.
- *
- * Transfer a large list of Parcelable objects across an IPC.  Splits into
- * multiple transactions if needed.
- *
- * Caveat: for efficiency and security, all elements must be the same concrete type.
- * In order to avoid writing the class name of each object, we must ensure that
- * each object is the same type, or else unparceling then reparceling the data may yield
- * a different result if the class name encoded in the Parcelable is a Base type.
- * See b/17671747.
- *
- * @hide
- */
-abstract class BaseMediaParceledListSlice<T> implements Parcelable {
-    private static String TAG = "BaseMediaParceledListSlice";
-    private static boolean DEBUG = false;
-
-    /*
-     * TODO get this number from somewhere else. For now set it to a quarter of
-     * the 1MB limit.
-     */
-    // private static final int MAX_IPC_SIZE = IBinder.getSuggestedMaxIpcSizeBytes();
-    private static final int MAX_IPC_SIZE = 64 * 1024;
-
-    private final List<T> mList;
-
-    private int mInlineCountLimit = Integer.MAX_VALUE;
-
-    public BaseMediaParceledListSlice(List<T> list) {
-        mList = list;
-    }
-
-    @SuppressWarnings("unchecked")
-    BaseMediaParceledListSlice(Parcel p, ClassLoader loader) {
-        final int N = p.readInt();
-        mList = new ArrayList<T>(N);
-        if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
-        if (N <= 0) {
-            return;
-        }
-
-        Parcelable.Creator<?> creator = readParcelableCreator(p, loader);
-        Class<?> listElementClass = null;
-
-        int i = 0;
-        while (i < N) {
-            if (p.readInt() == 0) {
-                break;
-            }
-
-            final T parcelable = readCreator(creator, p, loader);
-            if (listElementClass == null) {
-                listElementClass = parcelable.getClass();
-            } else {
-                verifySameType(listElementClass, parcelable.getClass());
-            }
-
-            mList.add(parcelable);
-
-            if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
-            i++;
-        }
-        if (i >= N) {
-            return;
-        }
-        final IBinder retriever = p.readStrongBinder();
-        while (i < N) {
-            if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
-            Parcel data = Parcel.obtain();
-            Parcel reply = Parcel.obtain();
-            data.writeInt(i);
-            try {
-                retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
-                return;
-            }
-            while (i < N && reply.readInt() != 0) {
-                final T parcelable = readCreator(creator, reply, loader);
-                verifySameType(listElementClass, parcelable.getClass());
-
-                mList.add(parcelable);
-
-                if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
-                i++;
-            }
-            reply.recycle();
-            data.recycle();
-        }
-    }
-
-    private T readCreator(Parcelable.Creator<?> creator, Parcel p, ClassLoader loader) {
-        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
-            Parcelable.ClassLoaderCreator<?> classLoaderCreator =
-                    (Parcelable.ClassLoaderCreator<?>) creator;
-            return (T) classLoaderCreator.createFromParcel(p, loader);
-        }
-        return (T) creator.createFromParcel(p);
-    }
-
-    private static void verifySameType(final Class<?> expected, final Class<?> actual) {
-        if (!actual.equals(expected)) {
-            throw new IllegalArgumentException("Can't unparcel type "
-                    + (actual == null ? null : actual.getName()) + " in list of type "
-                    + (expected == null ? null : expected.getName()));
-        }
-    }
-
-    public List<T> getList() {
-        return mList;
-    }
-
-    /**
-     * Set a limit on the maximum number of entries in the array that will be included
-     * inline in the initial parcelling of this object.
-     */
-    public void setInlineCountLimit(int maxCount) {
-        mInlineCountLimit = maxCount;
-    }
-
-    /**
-     * Write this to another Parcel. Note that this discards the internal Parcel
-     * and should not be used anymore. This is so we can pass this to a Binder
-     * where we won't have a chance to call recycle on this.
-     */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        final int N = mList.size();
-        final int callFlags = flags;
-        dest.writeInt(N);
-        if (DEBUG) Log.d(TAG, "Writing " + N + " items");
-        if (N > 0) {
-            final Class<?> listElementClass = mList.get(0).getClass();
-            writeParcelableCreator(mList.get(0), dest);
-            int i = 0;
-            while (i < N && i < mInlineCountLimit && dest.dataSize() < MAX_IPC_SIZE) {
-                dest.writeInt(1);
-
-                final T parcelable = mList.get(i);
-                verifySameType(listElementClass, parcelable.getClass());
-                writeElement(parcelable, dest, callFlags);
-
-                if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
-                i++;
-            }
-            if (i < N) {
-                dest.writeInt(0);
-                Binder retriever = new Binder() {
-                    @Override
-                    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                            throws RemoteException {
-                        if (code != FIRST_CALL_TRANSACTION) {
-                            return super.onTransact(code, data, reply, flags);
-                        }
-                        int i = data.readInt();
-                        if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
-                        while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
-                            reply.writeInt(1);
-
-                            final T parcelable = mList.get(i);
-                            verifySameType(listElementClass, parcelable.getClass());
-                            writeElement(parcelable, reply, callFlags);
-
-                            if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
-                            i++;
-                        }
-                        if (i < N) {
-                            if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
-                            reply.writeInt(0);
-                        }
-                        return true;
-                    }
-                };
-                if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
-                dest.writeStrongBinder(retriever);
-            }
-        }
-    }
-
-    abstract void writeElement(T parcelable, Parcel reply, int callFlags);
-
-    abstract void writeParcelableCreator(T parcelable, Parcel dest);
-
-    abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
-}
diff --git a/apex/media/framework/java/android/media/BufferingParams.java b/apex/media/framework/java/android/media/BufferingParams.java
deleted file mode 100644
index 04af028..0000000
--- a/apex/media/framework/java/android/media/BufferingParams.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Structure for source buffering management params.
- *
- * Used by {@link MediaPlayer#getBufferingParams()} and
- * {@link MediaPlayer#setBufferingParams(BufferingParams)}
- * to control source buffering behavior.
- *
- * <p>There are two stages of source buffering in {@link MediaPlayer}: initial buffering
- * (when {@link MediaPlayer} is being prepared) and rebuffering (when {@link MediaPlayer}
- * is playing back source). {@link BufferingParams} includes corresponding marks for each
- * stage of source buffering. The marks are time based (in milliseconds).
- *
- * <p>{@link MediaPlayer} source component has default marks which can be queried by
- * calling {@link MediaPlayer#getBufferingParams()} before any change is made by
- * {@link MediaPlayer#setBufferingParams()}.
- * <ul>
- * <li><strong>initial buffering:</strong> initialMarkMs is used when
- * {@link MediaPlayer} is being prepared. When cached data amount exceeds this mark
- * {@link MediaPlayer} is prepared. </li>
- * <li><strong>rebuffering during playback:</strong> resumePlaybackMarkMs is used when
- * {@link MediaPlayer} is playing back content.
- * <ul>
- * <li> {@link MediaPlayer} has internal mark, namely pausePlaybackMarkMs, to decide when
- * to pause playback if cached data amount runs low. This internal mark varies based on
- * type of data source. </li>
- * <li> When cached data amount exceeds resumePlaybackMarkMs, {@link MediaPlayer} will
- * resume playback if it has been paused due to low cached data amount. The internal mark
- * pausePlaybackMarkMs shall be less than resumePlaybackMarkMs. </li>
- * <li> {@link MediaPlayer} has internal mark, namely pauseRebufferingMarkMs, to decide
- * when to pause rebuffering. Apparently, this internal mark shall be no less than
- * resumePlaybackMarkMs. </li>
- * <li> {@link MediaPlayer} has internal mark, namely resumeRebufferingMarkMs, to decide
- * when to resume buffering. This internal mark varies based on type of data source. This
- * mark shall be larger than pausePlaybackMarkMs, and less than pauseRebufferingMarkMs.
- * </li>
- * </ul> </li>
- * </ul>
- * <p>Users should use {@link Builder} to change {@link BufferingParams}.
- * @hide
- */
-public final class BufferingParams implements Parcelable {
-    private static final int BUFFERING_NO_MARK = -1;
-
-    // params
-    private int mInitialMarkMs = BUFFERING_NO_MARK;
-
-    private int mResumePlaybackMarkMs = BUFFERING_NO_MARK;
-
-    private BufferingParams() {
-    }
-
-    /**
-     * Return initial buffering mark in milliseconds.
-     * @return initial buffering mark in milliseconds
-     */
-    public int getInitialMarkMs() {
-        return mInitialMarkMs;
-    }
-
-    /**
-     * Return the mark in milliseconds for resuming playback.
-     * @return the mark for resuming playback in milliseconds
-     */
-    public int getResumePlaybackMarkMs() {
-        return mResumePlaybackMarkMs;
-    }
-
-    /**
-     * Builder class for {@link BufferingParams} objects.
-     * <p> Here is an example where <code>Builder</code> is used to define the
-     * {@link BufferingParams} to be used by a {@link MediaPlayer} instance:
-     *
-     * <pre class="prettyprint">
-     * BufferingParams myParams = mediaplayer.getDefaultBufferingParams();
-     * myParams = new BufferingParams.Builder(myParams)
-     *         .setInitialMarkMs(10000)
-     *         .setResumePlaybackMarkMs(15000)
-     *         .build();
-     * mediaplayer.setBufferingParams(myParams);
-     * </pre>
-     */
-    public static class Builder {
-        private int mInitialMarkMs = BUFFERING_NO_MARK;
-        private int mResumePlaybackMarkMs = BUFFERING_NO_MARK;
-
-        /**
-         * Constructs a new Builder with the defaults.
-         * By default, all marks are -1.
-         */
-        public Builder() {
-        }
-
-        /**
-         * Constructs a new Builder from a given {@link BufferingParams} instance
-         * @param bp the {@link BufferingParams} object whose data will be reused
-         * in the new Builder.
-         */
-        public Builder(BufferingParams bp) {
-            mInitialMarkMs = bp.mInitialMarkMs;
-            mResumePlaybackMarkMs = bp.mResumePlaybackMarkMs;
-        }
-
-        /**
-         * Combines all of the fields that have been set and return a new
-         * {@link BufferingParams} object. <code>IllegalStateException</code> will be
-         * thrown if there is conflict between fields.
-         * @return a new {@link BufferingParams} object
-         */
-        public BufferingParams build() {
-            BufferingParams bp = new BufferingParams();
-            bp.mInitialMarkMs = mInitialMarkMs;
-            bp.mResumePlaybackMarkMs = mResumePlaybackMarkMs;
-
-            return bp;
-        }
-
-        /**
-         * Sets the time based mark in milliseconds for initial buffering.
-         * @param markMs time based mark in milliseconds
-         * @return the same Builder instance.
-         */
-        public Builder setInitialMarkMs(int markMs) {
-            mInitialMarkMs = markMs;
-            return this;
-        }
-
-        /**
-         * Sets the time based mark in milliseconds for resuming playback.
-         * @param markMs time based mark in milliseconds for resuming playback
-         * @return the same Builder instance.
-         */
-        public Builder setResumePlaybackMarkMs(int markMs) {
-            mResumePlaybackMarkMs = markMs;
-            return this;
-        }
-    }
-
-    private BufferingParams(Parcel in) {
-        mInitialMarkMs = in.readInt();
-        mResumePlaybackMarkMs = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BufferingParams> CREATOR =
-            new Parcelable.Creator<BufferingParams>() {
-                @Override
-                public BufferingParams createFromParcel(Parcel in) {
-                    return new BufferingParams(in);
-                }
-
-                @Override
-                public BufferingParams[] newArray(int size) {
-                    return new BufferingParams[size];
-                }
-            };
-
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mInitialMarkMs);
-        dest.writeInt(mResumePlaybackMarkMs);
-    }
-}
diff --git a/apex/media/framework/java/android/media/Controller2Link.java b/apex/media/framework/java/android/media/Controller2Link.java
deleted file mode 100644
index 8eefec7..0000000
--- a/apex/media/framework/java/android/media/Controller2Link.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-
-import java.util.Objects;
-
-/**
- * Handles incoming commands from {@link MediaSession2} to {@link MediaController2}.
- * @hide
- */
-// @SystemApi
-public final class Controller2Link implements Parcelable {
-    private static final String TAG = "Controller2Link";
-    private static final boolean DEBUG = MediaController2.DEBUG;
-
-    public static final @android.annotation.NonNull Parcelable.Creator<Controller2Link> CREATOR =
-            new Parcelable.Creator<Controller2Link>() {
-                @Override
-                public Controller2Link createFromParcel(Parcel in) {
-                    return new Controller2Link(in);
-                }
-
-                @Override
-                public Controller2Link[] newArray(int size) {
-                    return new Controller2Link[size];
-                }
-            };
-
-
-    private final MediaController2 mController;
-    private final IMediaController2 mIController;
-
-    public Controller2Link(MediaController2 controller) {
-        mController = controller;
-        mIController = new Controller2Stub();
-    }
-
-    Controller2Link(Parcel in) {
-        mController = null;
-        mIController = IMediaController2.Stub.asInterface(in.readStrongBinder());
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(mIController.asBinder());
-    }
-
-    @Override
-    public int hashCode() {
-        return mIController.asBinder().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof Controller2Link)) {
-            return false;
-        }
-        Controller2Link other = (Controller2Link) obj;
-        return Objects.equals(mIController.asBinder(), other.mIController.asBinder());
-    }
-
-    /** Interface method for IMediaController2.notifyConnected */
-    public void notifyConnected(int seq, Bundle connectionResult) {
-        try {
-            mIController.notifyConnected(seq, connectionResult);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaController2.notifyDisonnected */
-    public void notifyDisconnected(int seq) {
-        try {
-            mIController.notifyDisconnected(seq);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaController2.notifyPlaybackActiveChanged */
-    public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) {
-        try {
-            mIController.notifyPlaybackActiveChanged(seq, playbackActive);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaController2.sendSessionCommand */
-    public void sendSessionCommand(int seq, Session2Command command, Bundle args,
-            ResultReceiver resultReceiver) {
-        try {
-            mIController.sendSessionCommand(seq, command, args, resultReceiver);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaController2.cancelSessionCommand */
-    public void cancelSessionCommand(int seq) {
-        try {
-            mIController.cancelSessionCommand(seq);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Stub implementation for IMediaController2.notifyConnected */
-    public void onConnected(int seq, Bundle connectionResult) {
-        if (connectionResult == null) {
-            onDisconnected(seq);
-            return;
-        }
-        mController.onConnected(seq, connectionResult);
-    }
-
-    /** Stub implementation for IMediaController2.notifyDisonnected */
-    public void onDisconnected(int seq) {
-        mController.onDisconnected(seq);
-    }
-
-    /** Stub implementation for IMediaController2.notifyPlaybackActiveChanged */
-    public void onPlaybackActiveChanged(int seq, boolean playbackActive) {
-        mController.onPlaybackActiveChanged(seq, playbackActive);
-    }
-
-    /** Stub implementation for IMediaController2.sendSessionCommand */
-    public void onSessionCommand(int seq, Session2Command command, Bundle args,
-            ResultReceiver resultReceiver) {
-        mController.onSessionCommand(seq, command, args, resultReceiver);
-    }
-
-    /** Stub implementation for IMediaController2.cancelSessionCommand */
-    public void onCancelCommand(int seq) {
-        mController.onCancelCommand(seq);
-    }
-
-    private class Controller2Stub extends IMediaController2.Stub {
-        @Override
-        public void notifyConnected(int seq, Bundle connectionResult) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Controller2Link.this.onConnected(seq, connectionResult);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void notifyDisconnected(int seq) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Controller2Link.this.onDisconnected(seq);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Controller2Link.this.onPlaybackActiveChanged(seq, playbackActive);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void sendSessionCommand(int seq, Session2Command command, Bundle args,
-                ResultReceiver resultReceiver) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void cancelSessionCommand(int seq) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Controller2Link.this.onCancelCommand(seq);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/DataSourceCallback.java b/apex/media/framework/java/android/media/DataSourceCallback.java
deleted file mode 100644
index c297ecd..0000000
--- a/apex/media/framework/java/android/media/DataSourceCallback.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package android.media;
-
-import android.annotation.NonNull;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * For supplying media data to the framework. Implement this if your app has
- * special requirements for the way media data is obtained.
- *
- * <p class="note">Methods of this interface may be called on multiple different
- * threads. There will be a thread synchronization point between each call to ensure that
- * modifications to the state of your DataSourceCallback are visible to future calls. This means
- * you don't need to do your own synchronization unless you're modifying the
- * DataSourceCallback from another thread while it's being used by the framework.</p>
- *
- * @hide
- */
-public abstract class DataSourceCallback implements Closeable {
-
-    public static final int END_OF_STREAM = -1;
-
-    /**
-     * Called to request data from the given position.
-     *
-     * Implementations should should write up to {@code size} bytes into
-     * {@code buffer}, and return the number of bytes written.
-     *
-     * Return {@code 0} if size is zero (thus no bytes are read).
-     *
-     * Return {@code -1} to indicate that end of stream is reached.
-     *
-     * @param position the position in the data source to read from.
-     * @param buffer the buffer to read the data into.
-     * @param offset the offset within buffer to read the data into.
-     * @param size the number of bytes to read.
-     * @throws IOException on fatal errors.
-     * @return the number of bytes read, or {@link #END_OF_STREAM} if end of stream is reached.
-     */
-    public abstract int readAt(long position, @NonNull byte[] buffer, int offset, int size)
-            throws IOException;
-
-    /**
-     * Called to get the size of the data source.
-     *
-     * @throws IOException on fatal errors
-     * @return the size of data source in bytes, or -1 if the size is unknown.
-     */
-    public abstract long getSize() throws IOException;
-}
diff --git a/apex/media/framework/java/android/media/MediaCommunicationManager.java b/apex/media/framework/java/android/media/MediaCommunicationManager.java
deleted file mode 100644
index f39bcfb..0000000
--- a/apex/media/framework/java/android/media/MediaCommunicationManager.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-import static android.Manifest.permission.MEDIA_CONTENT_CONTROL;
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.content.Context;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.service.media.MediaBrowserService;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.modules.annotation.MinSdk;
-import com.android.modules.utils.build.SdkLevel;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-
-/**
- * Provides support for interacting with {@link android.media.MediaSession2 MediaSession2s}
- * that applications have published to express their ongoing media playback state.
- */
-@MinSdk(Build.VERSION_CODES.S)
-@SystemService(Context.MEDIA_COMMUNICATION_SERVICE)
-public class MediaCommunicationManager {
-    private static final String TAG = "MediaCommunicationManager";
-
-    /**
-     * The manager version used from beginning.
-     */
-    private static final int VERSION_1 = 1;
-
-    /**
-     * Current manager version.
-     */
-    private static final int CURRENT_VERSION = VERSION_1;
-
-    private final Context mContext;
-    private final IMediaCommunicationService mService;
-
-    private final Object mLock = new Object();
-    private final CopyOnWriteArrayList<SessionCallbackRecord> mTokenCallbackRecords =
-            new CopyOnWriteArrayList<>();
-
-    @GuardedBy("mLock")
-    private MediaCommunicationServiceCallbackStub mCallbackStub;
-
-    /**
-     * @hide
-     */
-    public MediaCommunicationManager(@NonNull Context context) {
-        if (!SdkLevel.isAtLeastS()) {
-            throw new UnsupportedOperationException("Android version must be S or greater.");
-        }
-        mContext = context;
-        mService = IMediaCommunicationService.Stub.asInterface(
-                MediaFrameworkInitializer.getMediaServiceManager()
-                        .getMediaCommunicationServiceRegisterer()
-                        .get());
-    }
-
-    /**
-     * Gets the version of this {@link MediaCommunicationManager}.
-     */
-    public @IntRange(from = 1) int getVersion() {
-        return CURRENT_VERSION;
-    }
-
-    /**
-     * Notifies that a new {@link MediaSession2} with type {@link Session2Token#TYPE_SESSION} is
-     * created.
-     * @param token newly created session2 token
-     * @hide
-     */
-    public void notifySession2Created(@NonNull Session2Token token) {
-        Objects.requireNonNull(token, "token shouldn't be null");
-        if (token.getType() != Session2Token.TYPE_SESSION) {
-            throw new IllegalArgumentException("token's type should be TYPE_SESSION");
-        }
-        try {
-            mService.notifySession2Created(token);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Checks whether the remote user is a trusted app.
-     * <p>
-     * An app is trusted if the app holds the
-     * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
-     * notification listener.
-     *
-     * @param userInfo The remote user info from either
-     *            {@link MediaSession#getCurrentControllerInfo()} or
-     *            {@link MediaBrowserService#getCurrentBrowserInfo()}.
-     * @return {@code true} if the remote user is trusted or {@code false} otherwise.
-     * @hide
-     */
-    public boolean isTrustedForMediaControl(@NonNull MediaSessionManager.RemoteUserInfo userInfo) {
-        Objects.requireNonNull(userInfo, "userInfo shouldn't be null");
-        if (userInfo.getPackageName() == null) {
-            return false;
-        }
-        try {
-            return mService.isTrusted(
-                    userInfo.getPackageName(), userInfo.getPid(), userInfo.getUid());
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot communicate with the service.", e);
-        }
-        return false;
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
-     * current user.
-     * <p>
-     * Although this API can be used without any restriction, each session owners can accept or
-     * reject your uses of {@link MediaSession2}.
-     *
-     * @return A list of {@link Session2Token}.
-     */
-    @NonNull
-    public List<Session2Token> getSession2Tokens() {
-        return getSession2Tokens(UserHandle.myUserId());
-    }
-
-    /**
-     * Adds a callback to be notified when the list of active sessions changes.
-     * <p>
-     * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
-     * held by the calling app.
-     * </p>
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(MEDIA_CONTENT_CONTROL)
-    public void registerSessionCallback(@CallbackExecutor @NonNull Executor executor,
-            @NonNull SessionCallback callback) {
-        Objects.requireNonNull(executor, "executor must not be null");
-        Objects.requireNonNull(callback, "callback must not be null");
-
-        if (!mTokenCallbackRecords.addIfAbsent(
-                new SessionCallbackRecord(executor, callback))) {
-            Log.w(TAG, "registerSession2TokenCallback: Ignoring the same callback");
-            return;
-        }
-        synchronized (mLock) {
-            if (mCallbackStub == null) {
-                MediaCommunicationServiceCallbackStub callbackStub =
-                        new MediaCommunicationServiceCallbackStub();
-                try {
-                    mService.registerCallback(callbackStub, mContext.getPackageName());
-                    mCallbackStub = callbackStub;
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "Failed to register callback.", ex);
-                }
-            }
-        }
-    }
-
-    /**
-     * Stops receiving active sessions updates on the specified callback.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void unregisterSessionCallback(@NonNull SessionCallback callback) {
-        if (!mTokenCallbackRecords.remove(
-                new SessionCallbackRecord(null, callback))) {
-            Log.w(TAG, "unregisterSession2TokenCallback: Ignoring an unknown callback.");
-            return;
-        }
-        synchronized (mLock) {
-            if (mCallbackStub != null && mTokenCallbackRecords.isEmpty()) {
-                try {
-                    mService.unregisterCallback(mCallbackStub);
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "Failed to unregister callback.", ex);
-                }
-                mCallbackStub = null;
-            }
-        }
-    }
-
-    private List<Session2Token> getSession2Tokens(int userId) {
-        try {
-            MediaParceledListSlice slice = mService.getSession2Tokens(userId);
-            return slice == null ? Collections.emptyList() : slice.getList();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get session tokens", e);
-        }
-        return Collections.emptyList();
-    }
-
-    /**
-     * Callback for listening to changes to the sessions.
-     * @see #registerSessionCallback(Executor, SessionCallback)
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public interface SessionCallback {
-        /**
-         * Called when a new {@link MediaSession2 media session2} is created.
-         * @param token the newly created token
-         */
-        default void onSession2TokenCreated(@NonNull Session2Token token) {}
-
-        /**
-         * Called when {@link #getSession2Tokens() session tokens} are changed.
-         */
-        default void onSession2TokensChanged(@NonNull List<Session2Token> tokens) {}
-    }
-
-    private static final class SessionCallbackRecord {
-        public final Executor executor;
-        public final SessionCallback callback;
-
-        SessionCallbackRecord(Executor executor, SessionCallback callback) {
-            this.executor = executor;
-            this.callback = callback;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(callback);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof SessionCallbackRecord)) {
-                return false;
-            }
-            return Objects.equals(this.callback, ((SessionCallbackRecord) obj).callback);
-        }
-    }
-
-    class MediaCommunicationServiceCallbackStub extends IMediaCommunicationServiceCallback.Stub {
-        @Override
-        public void onSession2Created(Session2Token token) throws RemoteException {
-            for (SessionCallbackRecord record : mTokenCallbackRecords) {
-                record.executor.execute(() -> record.callback.onSession2TokenCreated(token));
-            }
-        }
-
-        @Override
-        public void onSession2Changed(MediaParceledListSlice tokens) throws RemoteException {
-            List<Session2Token> tokenList = tokens.getList();
-            for (SessionCallbackRecord record : mTokenCallbackRecords) {
-                record.executor.execute(() -> record.callback.onSession2TokensChanged(tokenList));
-            }
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaConstants.java b/apex/media/framework/java/android/media/MediaConstants.java
deleted file mode 100644
index ce10889..0000000
--- a/apex/media/framework/java/android/media/MediaConstants.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-class MediaConstants {
-    // Bundle key for int
-    static final String KEY_PID = "android.media.key.PID";
-
-    // Bundle key for String
-    static final String KEY_PACKAGE_NAME = "android.media.key.PACKAGE_NAME";
-
-    // Bundle key for Parcelable
-    static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK";
-    static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS";
-    static final String KEY_PLAYBACK_ACTIVE = "android.media.key.PLAYBACK_ACTIVE";
-    static final String KEY_TOKEN_EXTRAS = "android.media.key.TOKEN_EXTRAS";
-    static final String KEY_CONNECTION_HINTS = "android.media.key.CONNECTION_HINTS";
-
-    private MediaConstants() {
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaController2.java b/apex/media/framework/java/android/media/MediaController2.java
deleted file mode 100644
index 159e8e5..0000000
--- a/apex/media/framework/java/android/media/MediaController2.java
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
-import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
-import static android.media.MediaConstants.KEY_PACKAGE_NAME;
-import static android.media.MediaConstants.KEY_PID;
-import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
-import static android.media.MediaConstants.KEY_SESSION2LINK;
-import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
-import static android.media.Session2Command.Result.RESULT_ERROR_UNKNOWN_ERROR;
-import static android.media.Session2Command.Result.RESULT_INFO_SKIPPED;
-import static android.media.Session2Token.TYPE_SESSION;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import java.util.concurrent.Executor;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- *
- * Allows an app to interact with an active {@link MediaSession2} or a
- * {@link MediaSession2Service} which would provide {@link MediaSession2}. Media buttons and other
- * commands can be sent to the session.
- */
-public class MediaController2 implements AutoCloseable {
-    static final String TAG = "MediaController2";
-    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final ControllerCallback mCallback;
-
-    private final IBinder.DeathRecipient mDeathRecipient = () -> close();
-    private final Context mContext;
-    private final Session2Token mSessionToken;
-    private final Executor mCallbackExecutor;
-    private final Controller2Link mControllerStub;
-    private final Handler mResultHandler;
-    private final SessionServiceConnection mServiceConnection;
-
-    private final Object mLock = new Object();
-    //@GuardedBy("mLock")
-    private boolean mClosed;
-    //@GuardedBy("mLock")
-    private int mNextSeqNumber;
-    //@GuardedBy("mLock")
-    private Session2Link mSessionBinder;
-    //@GuardedBy("mLock")
-    private Session2CommandGroup mAllowedCommands;
-    //@GuardedBy("mLock")
-    private Session2Token mConnectedToken;
-    //@GuardedBy("mLock")
-    private ArrayMap<ResultReceiver, Integer> mPendingCommands;
-    //@GuardedBy("mLock")
-    private ArraySet<Integer> mRequestedCommandSeqNumbers;
-    //@GuardedBy("mLock")
-    private boolean mPlaybackActive;
-
-    /**
-     * Create a {@link MediaController2} from the {@link Session2Token}.
-     * This connects to the session and may wake up the service if it's not available.
-     *
-     * @param context context
-     * @param token token to connect to
-     * @param connectionHints a session-specific argument to send to the session when connecting.
-     *                        The contents of this bundle may affect the connection result.
-     * @param executor executor to run callbacks on.
-     * @param callback controller callback to receive changes in.
-     */
-    MediaController2(@NonNull Context context, @NonNull Session2Token token,
-            @NonNull Bundle connectionHints, @NonNull Executor executor,
-            @NonNull ControllerCallback callback) {
-        if (context == null) {
-            throw new IllegalArgumentException("context shouldn't be null");
-        }
-        if (token == null) {
-            throw new IllegalArgumentException("token shouldn't be null");
-        }
-        mContext = context;
-        mSessionToken = token;
-        mCallbackExecutor = (executor == null) ? context.getMainExecutor() : executor;
-        mCallback = (callback == null) ? new ControllerCallback() {} : callback;
-        mControllerStub = new Controller2Link(this);
-        // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
-        mResultHandler = new Handler(context.getMainLooper());
-
-        mNextSeqNumber = 0;
-        mPendingCommands = new ArrayMap<>();
-        mRequestedCommandSeqNumbers = new ArraySet<>();
-
-        boolean connectRequested;
-        if (token.getType() == TYPE_SESSION) {
-            mServiceConnection = null;
-            connectRequested = requestConnectToSession(connectionHints);
-        } else {
-            mServiceConnection = new SessionServiceConnection(connectionHints);
-            connectRequested = requestConnectToService();
-        }
-        if (!connectRequested) {
-            close();
-        }
-    }
-
-    @Override
-    public void close() {
-        synchronized (mLock) {
-            if (mClosed) {
-                // Already closed. Ignore rest of clean up code.
-                // Note: unbindService() throws IllegalArgumentException when it's called twice.
-                return;
-            }
-            if (DEBUG) {
-                Log.d(TAG, "closing " + this);
-            }
-            mClosed = true;
-            if (mServiceConnection != null) {
-                // Note: This should be called even when the bindService() has returned false.
-                mContext.unbindService(mServiceConnection);
-            }
-            if (mSessionBinder != null) {
-                try {
-                    mSessionBinder.disconnect(mControllerStub, getNextSeqNumber());
-                    mSessionBinder.unlinkToDeath(mDeathRecipient, 0);
-                } catch (RuntimeException e) {
-                    // No-op
-                }
-            }
-            mConnectedToken = null;
-            mPendingCommands.clear();
-            mRequestedCommandSeqNumbers.clear();
-            mCallbackExecutor.execute(() -> {
-                mCallback.onDisconnected(MediaController2.this);
-            });
-            mSessionBinder = null;
-        }
-    }
-
-    /**
-     * Returns {@link Session2Token} of the connected session.
-     * If it is not connected yet, it returns {@code null}.
-     * <p>
-     * This may differ with the {@link Session2Token} from the constructor. For example, if the
-     * controller is created with the token for {@link MediaSession2Service}, this would return
-     * token for the {@link MediaSession2} in the service.
-     *
-     * @return Session2Token of the connected session, or {@code null} if not connected
-     */
-    @Nullable
-    public Session2Token getConnectedToken() {
-        synchronized (mLock) {
-            return mConnectedToken;
-        }
-    }
-
-    /**
-     * Returns whether the session's playback is active.
-     *
-     * @return {@code true} if playback active. {@code false} otherwise.
-     * @see ControllerCallback#onPlaybackActiveChanged(MediaController2, boolean)
-     */
-    public boolean isPlaybackActive() {
-        synchronized (mLock) {
-            return mPlaybackActive;
-        }
-    }
-
-    /**
-     * Sends a session command to the session
-     * <p>
-     * @param command the session command
-     * @param args optional arguments
-     * @return a token which will be sent together in {@link ControllerCallback#onCommandResult}
-     *        when its result is received.
-     */
-    @NonNull
-    public Object sendSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
-        if (command == null) {
-            throw new IllegalArgumentException("command shouldn't be null");
-        }
-
-        ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                synchronized (mLock) {
-                    mPendingCommands.remove(this);
-                }
-                mCallbackExecutor.execute(() -> {
-                    mCallback.onCommandResult(MediaController2.this, this,
-                            command, new Session2Command.Result(resultCode, resultData));
-                });
-            }
-        };
-
-        synchronized (mLock) {
-            if (mSessionBinder != null) {
-                int seq = getNextSeqNumber();
-                mPendingCommands.put(resultReceiver, seq);
-                try {
-                    mSessionBinder.sendSessionCommand(mControllerStub, seq, command, args,
-                            resultReceiver);
-                } catch (RuntimeException e)  {
-                    mPendingCommands.remove(resultReceiver);
-                    resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
-                }
-            }
-        }
-        return resultReceiver;
-    }
-
-    /**
-     * Cancels the session command previously sent.
-     *
-     * @param token the token which is returned from {@link #sendSessionCommand}.
-     */
-    public void cancelSessionCommand(@NonNull Object token) {
-        if (token == null) {
-            throw new IllegalArgumentException("token shouldn't be null");
-        }
-        synchronized (mLock) {
-            if (mSessionBinder == null) return;
-            Integer seq = mPendingCommands.remove(token);
-            if (seq != null) {
-                mSessionBinder.cancelSessionCommand(mControllerStub, seq);
-            }
-        }
-    }
-
-    // Called by Controller2Link.onConnected
-    void onConnected(int seq, Bundle connectionResult) {
-        Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK);
-        Session2CommandGroup allowedCommands =
-                connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
-        boolean playbackActive = connectionResult.getBoolean(KEY_PLAYBACK_ACTIVE);
-
-        Bundle tokenExtras = connectionResult.getBundle(KEY_TOKEN_EXTRAS);
-        if (tokenExtras == null) {
-            Log.w(TAG, "extras shouldn't be null.");
-            tokenExtras = Bundle.EMPTY;
-        } else if (MediaSession2.hasCustomParcelable(tokenExtras)) {
-            Log.w(TAG, "extras contain custom parcelable. Ignoring.");
-            tokenExtras = Bundle.EMPTY;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder
-                    + ", allowedCommands=" + allowedCommands);
-        }
-        if (sessionBinder == null || allowedCommands == null) {
-            // Connection rejected.
-            close();
-            return;
-        }
-        synchronized (mLock) {
-            mSessionBinder = sessionBinder;
-            mAllowedCommands = allowedCommands;
-            mPlaybackActive = playbackActive;
-
-            // Implementation for the local binder is no-op,
-            // so can be used without worrying about deadlock.
-            sessionBinder.linkToDeath(mDeathRecipient, 0);
-            mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION,
-                    mSessionToken.getPackageName(), sessionBinder, tokenExtras);
-        }
-        mCallbackExecutor.execute(() -> {
-            mCallback.onConnected(MediaController2.this, allowedCommands);
-        });
-    }
-
-    // Called by Controller2Link.onDisconnected
-    void onDisconnected(int seq) {
-        // close() will call mCallback.onDisconnected
-        close();
-    }
-
-    // Called by Controller2Link.onPlaybackActiveChanged
-    void onPlaybackActiveChanged(int seq, boolean playbackActive) {
-        synchronized (mLock) {
-            mPlaybackActive = playbackActive;
-        }
-        mCallbackExecutor.execute(() -> {
-            mCallback.onPlaybackActiveChanged(MediaController2.this, playbackActive);
-        });
-    }
-
-    // Called by Controller2Link.onSessionCommand
-    void onSessionCommand(int seq, Session2Command command, Bundle args,
-            @Nullable ResultReceiver resultReceiver) {
-        synchronized (mLock) {
-            mRequestedCommandSeqNumbers.add(seq);
-        }
-        mCallbackExecutor.execute(() -> {
-            boolean isCanceled;
-            synchronized (mLock) {
-                isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
-            }
-            if (isCanceled) {
-                if (resultReceiver != null) {
-                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
-                }
-                return;
-            }
-            Session2Command.Result result = mCallback.onSessionCommand(
-                    MediaController2.this, command, args);
-            if (resultReceiver != null) {
-                if (result == null) {
-                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
-                } else {
-                    resultReceiver.send(result.getResultCode(), result.getResultData());
-                }
-            }
-        });
-    }
-
-    // Called by Controller2Link.onSessionCommand
-    void onCancelCommand(int seq) {
-        synchronized (mLock) {
-            mRequestedCommandSeqNumbers.remove(seq);
-        }
-    }
-
-    private int getNextSeqNumber() {
-        synchronized (mLock) {
-            return mNextSeqNumber++;
-        }
-    }
-
-    private Bundle createConnectionRequest(@NonNull Bundle connectionHints) {
-        Bundle connectionRequest = new Bundle();
-        connectionRequest.putString(KEY_PACKAGE_NAME, mContext.getPackageName());
-        connectionRequest.putInt(KEY_PID, Process.myPid());
-        connectionRequest.putBundle(KEY_CONNECTION_HINTS, connectionHints);
-        return connectionRequest;
-    }
-
-    private boolean requestConnectToSession(@NonNull Bundle connectionHints) {
-        Session2Link sessionBinder = mSessionToken.getSessionLink();
-        Bundle connectionRequest = createConnectionRequest(connectionHints);
-        try {
-            sessionBinder.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
-        } catch (RuntimeException e) {
-            Log.w(TAG, "Failed to call connection request", e);
-            return false;
-        }
-        return true;
-    }
-
-    private boolean requestConnectToService() {
-        // Service. Needs to get fresh binder whenever connection is needed.
-        final Intent intent = new Intent(MediaSession2Service.SERVICE_INTERFACE);
-        intent.setClassName(mSessionToken.getPackageName(), mSessionToken.getServiceName());
-
-        // Use bindService() instead of startForegroundService() to start session service for three
-        // reasons.
-        // 1. Prevent session service owner's stopSelf() from destroying service.
-        //    With the startForegroundService(), service's call of stopSelf() will trigger immediate
-        //    onDestroy() calls on the main thread even when onConnect() is running in another
-        //    thread.
-        // 2. Minimize APIs for developers to take care about.
-        //    With bindService(), developers only need to take care about Service.onBind()
-        //    but Service.onStartCommand() should be also taken care about with the
-        //    startForegroundService().
-        // 3. Future support for UI-less playback
-        //    If a service wants to keep running, it should be either foreground service or
-        //    bound service. But there had been request for the feature for system apps
-        //    and using bindService() will be better fit with it.
-        synchronized (mLock) {
-            boolean result = mContext.bindService(
-                    intent, mServiceConnection, Context.BIND_AUTO_CREATE);
-            if (!result) {
-                Log.w(TAG, "bind to " + mSessionToken + " failed");
-                return false;
-            } else if (DEBUG) {
-                Log.d(TAG, "bind to " + mSessionToken + " succeeded");
-            }
-        }
-        return true;
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Builder for {@link MediaController2}.
-     * <p>
-     * Any incoming event from the {@link MediaSession2} will be handled on the callback
-     * executor. If it's not set, {@link Context#getMainExecutor()} will be used by default.
-     */
-    public static final class Builder {
-        private Context mContext;
-        private Session2Token mToken;
-        private Bundle mConnectionHints;
-        private Executor mCallbackExecutor;
-        private ControllerCallback mCallback;
-
-        /**
-         * Creates a builder for {@link MediaController2}.
-         *
-         * @param context context
-         * @param token token of the session to connect to
-         */
-        public Builder(@NonNull Context context, @NonNull Session2Token token) {
-            if (context == null) {
-                throw new IllegalArgumentException("context shouldn't be null");
-            }
-            if (token == null) {
-                throw new IllegalArgumentException("token shouldn't be null");
-            }
-            mContext = context;
-            mToken = token;
-        }
-
-        /**
-         * Set the connection hints for the controller.
-         * <p>
-         * {@code connectionHints} is a session-specific argument to send to the session when
-         * connecting. The contents of this bundle may affect the connection result.
-         * <p>
-         * An {@link IllegalArgumentException} will be thrown if the bundle contains any
-         * non-framework Parcelable objects.
-         *
-         * @param connectionHints a bundle which contains the connection hints
-         * @return The Builder to allow chaining
-         */
-        @NonNull
-        public Builder setConnectionHints(@NonNull Bundle connectionHints) {
-            if (connectionHints == null) {
-                throw new IllegalArgumentException("connectionHints shouldn't be null");
-            }
-            if (MediaSession2.hasCustomParcelable(connectionHints)) {
-                throw new IllegalArgumentException("connectionHints shouldn't contain any custom "
-                        + "parcelables");
-            }
-            mConnectionHints = new Bundle(connectionHints);
-            return this;
-        }
-
-        /**
-         * Set callback for the controller and its executor.
-         *
-         * @param executor callback executor
-         * @param callback session callback.
-         * @return The Builder to allow chaining
-         */
-        @NonNull
-        public Builder setControllerCallback(@NonNull Executor executor,
-                @NonNull ControllerCallback callback) {
-            if (executor == null) {
-                throw new IllegalArgumentException("executor shouldn't be null");
-            }
-            if (callback == null) {
-                throw new IllegalArgumentException("callback shouldn't be null");
-            }
-            mCallbackExecutor = executor;
-            mCallback = callback;
-            return this;
-        }
-
-        /**
-         * Build {@link MediaController2}.
-         *
-         * @return a new controller
-         */
-        @NonNull
-        public MediaController2 build() {
-            if (mCallbackExecutor == null) {
-                mCallbackExecutor = mContext.getMainExecutor();
-            }
-            if (mCallback == null) {
-                mCallback = new ControllerCallback() {};
-            }
-            if (mConnectionHints == null) {
-                mConnectionHints = Bundle.EMPTY;
-            }
-            return new MediaController2(
-                    mContext, mToken, mConnectionHints, mCallbackExecutor, mCallback);
-        }
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Interface for listening to change in activeness of the {@link MediaSession2}.
-     */
-    public abstract static class ControllerCallback {
-        /**
-         * Called when the controller is successfully connected to the session. The controller
-         * becomes available afterwards.
-         *
-         * @param controller the controller for this event
-         * @param allowedCommands commands that's allowed by the session.
-         */
-        public void onConnected(@NonNull MediaController2 controller,
-                @NonNull Session2CommandGroup allowedCommands) {}
-
-        /**
-         * Called when the session refuses the controller or the controller is disconnected from
-         * the session. The controller becomes unavailable afterwards and the callback wouldn't
-         * be called.
-         * <p>
-         * It will be also called after the {@link #close()}, so you can put clean up code here.
-         * You don't need to call {@link #close()} after this.
-         *
-         * @param controller the controller for this event
-         */
-        public void onDisconnected(@NonNull MediaController2 controller) {}
-
-        /**
-         * Called when the session's playback activeness is changed.
-         *
-         * @param controller the controller for this event
-         * @param playbackActive {@code true} if the session's playback is active.
-         *                       {@code false} otherwise.
-         * @see MediaController2#isPlaybackActive()
-         */
-        public void onPlaybackActiveChanged(@NonNull MediaController2 controller,
-                boolean playbackActive) {}
-
-        /**
-         * Called when the connected session sent a session command.
-         *
-         * @param controller the controller for this event
-         * @param command the session command
-         * @param args optional arguments
-         * @return the result for the session command. If {@code null}, RESULT_INFO_SKIPPED
-         *         will be sent to the session.
-         */
-        @Nullable
-        public Session2Command.Result onSessionCommand(@NonNull MediaController2 controller,
-                @NonNull Session2Command command, @Nullable Bundle args) {
-            return null;
-        }
-
-        /**
-         * Called when the command sent to the connected session is finished.
-         *
-         * @param controller the controller for this event
-         * @param token the token got from {@link MediaController2#sendSessionCommand}
-         * @param command the session command
-         * @param result the result of the session command
-         */
-        public void onCommandResult(@NonNull MediaController2 controller, @NonNull Object token,
-                @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
-    }
-
-    // This will be called on the main thread.
-    private class SessionServiceConnection implements ServiceConnection {
-        private final Bundle mConnectionHints;
-
-        SessionServiceConnection(@Nullable Bundle connectionHints) {
-            mConnectionHints = connectionHints;
-        }
-
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            // Note that it's always main-thread.
-            boolean connectRequested = false;
-            try {
-                if (DEBUG) {
-                    Log.d(TAG, "onServiceConnected " + name + " " + this);
-                }
-                if (!mSessionToken.getPackageName().equals(name.getPackageName())) {
-                    Log.wtf(TAG, "Expected connection to " + mSessionToken.getPackageName()
-                            + " but is connected to " + name);
-                    return;
-                }
-                IMediaSession2Service iService = IMediaSession2Service.Stub.asInterface(service);
-                if (iService == null) {
-                    Log.wtf(TAG, "Service interface is missing.");
-                    return;
-                }
-                Bundle connectionRequest = createConnectionRequest(mConnectionHints);
-                iService.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
-                connectRequested = true;
-            } catch (RemoteException e) {
-                Log.w(TAG, "Service " + name + " has died prematurely", e);
-            } finally {
-                if (!connectRequested) {
-                    close();
-                }
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            // Temporal lose of the binding because of the service crash. System will automatically
-            // rebind, so just no-op.
-            if (DEBUG) {
-                Log.w(TAG, "Session service " + name + " is disconnected.");
-            }
-            close();
-        }
-
-        @Override
-        public void onBindingDied(ComponentName name) {
-            // Permanent lose of the binding because of the service package update or removed.
-            // This SessionServiceRecord will be removed accordingly, but forget session binder here
-            // for sure.
-            close();
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaFeature.java b/apex/media/framework/java/android/media/MediaFeature.java
deleted file mode 100644
index 8d1b159..0000000
--- a/apex/media/framework/java/android/media/MediaFeature.java
+++ /dev/null
@@ -1,67 +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.media;
-
-import android.annotation.StringDef;
-import android.os.Build;
-
-import com.android.modules.annotation.MinSdk;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * MediaFeature defines various media features, e.g. hdr type.
- */
-@MinSdk(Build.VERSION_CODES.S)
-public final class MediaFeature {
-     /**
-     * Defines tye type of HDR(high dynamic range) video.
-     */
-    public static final class HdrType {
-        private HdrType() {
-        }
-
-        /**
-         * HDR type for dolby-vision.
-         */
-        public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
-        /**
-         * HDR type for hdr10.
-         */
-        public static final String HDR10 = "android.media.feature.hdr.hdr10";
-        /**
-         * HDR type for hdr10+.
-         */
-        public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
-        /**
-         * HDR type for hlg.
-         */
-        public static final String HLG = "android.media.feature.hdr.hlg";
-    }
-
-    /** @hide */
-    @StringDef({
-            HdrType.DOLBY_VISION,
-            HdrType.HDR10,
-            HdrType.HDR10_PLUS,
-            HdrType.HLG,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface MediaHdrType {
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java
deleted file mode 100644
index 75a56b72..0000000
--- a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.SystemApi.Client;
-import android.app.SystemServiceRegistry;
-import android.content.Context;
-import android.os.Build;
-
-import com.android.modules.annotation.MinSdk;
-import com.android.modules.utils.build.SdkLevel;
-
-/**
- * Class for performing registration for all media services on com.android.media apex.
- *
- * @hide
- */
-@MinSdk(Build.VERSION_CODES.S)
-@SystemApi(client = Client.MODULE_LIBRARIES)
-public class MediaFrameworkInitializer {
-    private MediaFrameworkInitializer() {
-    }
-
-    private static volatile MediaServiceManager sMediaServiceManager;
-
-    /**
-     * Sets an instance of {@link MediaServiceManager} that allows
-     * the media mainline module to register/obtain media binder services. This is called
-     * by the platform during the system initialization.
-     *
-     * @param mediaServiceManager instance of {@link MediaServiceManager} that allows
-     * the media mainline module to register/obtain media binder services.
-     */
-    public static void setMediaServiceManager(
-            @NonNull MediaServiceManager mediaServiceManager) {
-        if (sMediaServiceManager != null) {
-            throw new IllegalStateException("setMediaServiceManager called twice!");
-        }
-
-        if (mediaServiceManager == null) {
-            throw new NullPointerException("mediaServiceManager is null!");
-        }
-
-        sMediaServiceManager = mediaServiceManager;
-    }
-
-    /** @hide */
-    public static MediaServiceManager getMediaServiceManager() {
-        return sMediaServiceManager;
-    }
-
-    /**
-     * Called by {@link SystemServiceRegistry}'s static initializer and registers all media
-     * services to {@link Context}, so that {@link Context#getSystemService} can return them.
-     *
-     * @throws IllegalStateException if this is called from anywhere besides
-     * {@link SystemServiceRegistry}
-     */
-    public static void registerServiceWrappers() {
-        SystemServiceRegistry.registerContextAwareService(
-                Context.MEDIA_TRANSCODING_SERVICE,
-                MediaTranscodingManager.class,
-                context -> new MediaTranscodingManager(context)
-        );
-        if (SdkLevel.isAtLeastS()) {
-            SystemServiceRegistry.registerContextAwareService(
-                    Context.MEDIA_COMMUNICATION_SERVICE,
-                    MediaCommunicationManager.class,
-                    context -> new MediaCommunicationManager(context)
-            );
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaParceledListSlice.java b/apex/media/framework/java/android/media/MediaParceledListSlice.java
deleted file mode 100644
index 47ac193..0000000
--- a/apex/media/framework/java/android/media/MediaParceledListSlice.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * This is a copied version of MediaParceledListSlice in framework with hidden API usages removed,
- * and also with some lint error fixed.
- *
- * Transfer a large list of Parcelable objects across an IPC.  Splits into
- * multiple transactions if needed.
- *
- * TODO: Remove this from @SystemApi once all the MediaSession related classes are moved
- *       to apex (or ParceledListSlice moved to apex). This class is temporaily added to system API
- *       for moving classes step by step.
- *
- * @param <T> The type of the elements in the list.
- * @see BaseMediaParceledListSlice
- * @deprecated This is temporary marked as @SystemApi. Should be removed from the API surface.
- * @hide
- */
-@Deprecated
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public final class MediaParceledListSlice<T extends Parcelable>
-        extends BaseMediaParceledListSlice<T> {
-    public MediaParceledListSlice(@NonNull List<T> list) {
-        super(list);
-    }
-
-    private MediaParceledListSlice(Parcel in, ClassLoader loader) {
-        super(in, loader);
-    }
-
-    @NonNull
-    public static <T extends Parcelable> MediaParceledListSlice<T> emptyList() {
-        return new MediaParceledListSlice<T>(Collections.<T> emptyList());
-    }
-
-    @Override
-    public int describeContents() {
-        int contents = 0;
-        final List<T> list = getList();
-        for (int i=0; i<list.size(); i++) {
-            contents |= list.get(i).describeContents();
-        }
-        return contents;
-    }
-
-    @Override
-    void writeElement(T parcelable, Parcel dest, int callFlags) {
-        parcelable.writeToParcel(dest, callFlags);
-    }
-
-    @Override
-    void writeParcelableCreator(T parcelable, Parcel dest) {
-        dest.writeParcelableCreator((Parcelable) parcelable);
-    }
-
-    @Override
-    Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
-        return from.readParcelableCreator(loader);
-    }
-
-    @NonNull
-    @SuppressWarnings("unchecked")
-    public static final Parcelable.ClassLoaderCreator<MediaParceledListSlice> CREATOR =
-            new Parcelable.ClassLoaderCreator<MediaParceledListSlice>() {
-        public MediaParceledListSlice createFromParcel(Parcel in) {
-            return new MediaParceledListSlice(in, null);
-        }
-
-        @Override
-        public MediaParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
-            return new MediaParceledListSlice(in, loader);
-        }
-
-        @Override
-        public MediaParceledListSlice[] newArray(int size) {
-            return new MediaParceledListSlice[size];
-        }
-    };
-}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
deleted file mode 100644
index 8cc3bc0..0000000
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ /dev/null
@@ -1,2292 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringDef;
-import android.media.MediaCodec.CryptoInfo;
-import android.media.metrics.LogSessionId;
-import android.os.Build;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-
-import androidx.annotation.RequiresApi;
-
-import com.android.modules.utils.build.SdkLevel;
-
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.ParserException;
-import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
-import com.google.android.exoplayer2.extractor.ChunkIndex;
-import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
-import com.google.android.exoplayer2.extractor.Extractor;
-import com.google.android.exoplayer2.extractor.ExtractorInput;
-import com.google.android.exoplayer2.extractor.ExtractorOutput;
-import com.google.android.exoplayer2.extractor.PositionHolder;
-import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints;
-import com.google.android.exoplayer2.extractor.TrackOutput;
-import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
-import com.google.android.exoplayer2.extractor.flac.FlacExtractor;
-import com.google.android.exoplayer2.extractor.flv.FlvExtractor;
-import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
-import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
-import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
-import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
-import com.google.android.exoplayer2.extractor.ogg.OggExtractor;
-import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
-import com.google.android.exoplayer2.extractor.ts.Ac4Extractor;
-import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
-import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory;
-import com.google.android.exoplayer2.extractor.ts.PsExtractor;
-import com.google.android.exoplayer2.extractor.ts.TsExtractor;
-import com.google.android.exoplayer2.extractor.wav.WavExtractor;
-import com.google.android.exoplayer2.upstream.DataReader;
-import com.google.android.exoplayer2.util.ParsableByteArray;
-import com.google.android.exoplayer2.util.TimestampAdjuster;
-import com.google.android.exoplayer2.util.Util;
-import com.google.android.exoplayer2.video.ColorInfo;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.function.Function;
-
-/**
- * Parses media container formats and extracts contained media samples and metadata.
- *
- * <p>This class provides access to a battery of low-level media container parsers. Each instance of
- * this class is associated to a specific media parser implementation which is suitable for
- * extraction from a specific media container format. The media parser implementation assignment
- * depends on the factory method (see {@link #create} and {@link #createByName}) used to create the
- * instance.
- *
- * <p>Users must implement the following to use this class.
- *
- * <ul>
- *   <li>{@link InputReader}: Provides the media container's bytes to parse.
- *   <li>{@link OutputConsumer}: Provides a sink for all extracted data and metadata.
- * </ul>
- *
- * <p>The following code snippet includes a usage example:
- *
- * <pre>
- * MyOutputConsumer myOutputConsumer = new MyOutputConsumer();
- * MyInputReader myInputReader = new MyInputReader("www.example.com");
- * MediaParser mediaParser = MediaParser.create(myOutputConsumer);
- *
- * while (mediaParser.advance(myInputReader)) {}
- *
- * mediaParser.release();
- * mediaParser = null;
- * </pre>
- *
- * <p>The following code snippet provides a rudimentary {@link OutputConsumer} sample implementation
- * which extracts and publishes all video samples:
- *
- * <pre>
- * class VideoOutputConsumer implements MediaParser.OutputConsumer {
- *
- *     private byte[] sampleDataBuffer = new byte[4096];
- *     private byte[] discardedDataBuffer = new byte[4096];
- *     private int videoTrackIndex = -1;
- *     private int bytesWrittenCount = 0;
- *
- *     &#64;Override
- *     public void onSeekMapFound(int i, &#64;NonNull MediaFormat mediaFormat) {
- *       // Do nothing.
- *     }
- *
- *     &#64;Override
- *     public void onTrackDataFound(int i, &#64;NonNull TrackData trackData) {
- *       MediaFormat mediaFormat = trackData.mediaFormat;
- *       if (videoTrackIndex == -1 &amp;&amp;
- *           mediaFormat
- *               .getString(MediaFormat.KEY_MIME, &#47;* defaultValue= *&#47; "")
- *               .startsWith("video/")) {
- *         videoTrackIndex = i;
- *       }
- *     }
- *
- *     &#64;Override
- *     public void onSampleDataFound(int trackIndex, &#64;NonNull InputReader inputReader)
- *         throws IOException {
- *       int numberOfBytesToRead = (int) inputReader.getLength();
- *       if (videoTrackIndex != trackIndex) {
- *         // Discard contents.
- *         inputReader.read(
- *             discardedDataBuffer,
- *             &#47;* offset= *&#47; 0,
- *             Math.min(discardDataBuffer.length, numberOfBytesToRead));
- *       } else {
- *         ensureSpaceInBuffer(numberOfBytesToRead);
- *         int bytesRead = inputReader.read(
- *             sampleDataBuffer, bytesWrittenCount, numberOfBytesToRead);
- *         bytesWrittenCount += bytesRead;
- *       }
- *     }
- *
- *     &#64;Override
- *     public void onSampleCompleted(
- *         int trackIndex,
- *         long timeMicros,
- *         int flags,
- *         int size,
- *         int offset,
- *         &#64;Nullable CryptoInfo cryptoData) {
- *       if (videoTrackIndex != trackIndex) {
- *         return; // It's not the video track. Ignore.
- *       }
- *       byte[] sampleData = new byte[size];
- *       int sampleStartOffset = bytesWrittenCount - size - offset;
- *       System.arraycopy(
- *           sampleDataBuffer,
- *           sampleStartOffset,
- *           sampleData,
- *           &#47;* destPos= *&#47; 0,
- *           size);
- *       // Place trailing bytes at the start of the buffer.
- *       System.arraycopy(
- *           sampleDataBuffer,
- *           bytesWrittenCount - offset,
- *           sampleDataBuffer,
- *           &#47;* destPos= *&#47; 0,
- *           &#47;* size= *&#47; offset);
- *       bytesWrittenCount = bytesWrittenCount - offset;
- *       publishSample(sampleData, timeMicros, flags);
- *     }
- *
- *    private void ensureSpaceInBuffer(int numberOfBytesToRead) {
- *      int requiredLength = bytesWrittenCount + numberOfBytesToRead;
- *      if (requiredLength &gt; sampleDataBuffer.length) {
- *        sampleDataBuffer = Arrays.copyOf(sampleDataBuffer, requiredLength);
- *      }
- *    }
- *
- *   }
- *
- * </pre>
- */
-public final class MediaParser {
-
-    /**
-     * Maps seek positions to {@link SeekPoint SeekPoints} in the stream.
-     *
-     * <p>A {@link SeekPoint} is a position in the stream from which a player may successfully start
-     * playing media samples.
-     */
-    public static final class SeekMap {
-
-        /** Returned by {@link #getDurationMicros()} when the duration is unknown. */
-        public static final int UNKNOWN_DURATION = Integer.MIN_VALUE;
-
-        /**
-         * For each {@link #getSeekPoints} call, returns a single {@link SeekPoint} whose {@link
-         * SeekPoint#timeMicros} matches the requested timestamp, and whose {@link
-         * SeekPoint#position} is 0.
-         *
-         * @hide
-         */
-        public static final SeekMap DUMMY = new SeekMap(new DummyExoPlayerSeekMap());
-
-        private final com.google.android.exoplayer2.extractor.SeekMap mExoPlayerSeekMap;
-
-        private SeekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
-            mExoPlayerSeekMap = exoplayerSeekMap;
-        }
-
-        /** Returns whether seeking is supported. */
-        public boolean isSeekable() {
-            return mExoPlayerSeekMap.isSeekable();
-        }
-
-        /**
-         * Returns the duration of the stream in microseconds or {@link #UNKNOWN_DURATION} if the
-         * duration is unknown.
-         */
-        public long getDurationMicros() {
-            long durationUs = mExoPlayerSeekMap.getDurationUs();
-            return durationUs != C.TIME_UNSET ? durationUs : UNKNOWN_DURATION;
-        }
-
-        /**
-         * Obtains {@link SeekPoint SeekPoints} for the specified seek time in microseconds.
-         *
-         * <p>{@code getSeekPoints(timeMicros).first} contains the latest seek point for samples
-         * with timestamp equal to or smaller than {@code timeMicros}.
-         *
-         * <p>{@code getSeekPoints(timeMicros).second} contains the earliest seek point for samples
-         * with timestamp equal to or greater than {@code timeMicros}. If a seek point exists for
-         * {@code timeMicros}, the returned pair will contain the same {@link SeekPoint} twice.
-         *
-         * @param timeMicros A seek time in microseconds.
-         * @return The corresponding {@link SeekPoint SeekPoints}.
-         */
-        @NonNull
-        public Pair<SeekPoint, SeekPoint> getSeekPoints(long timeMicros) {
-            SeekPoints seekPoints = mExoPlayerSeekMap.getSeekPoints(timeMicros);
-            return new Pair<>(toSeekPoint(seekPoints.first), toSeekPoint(seekPoints.second));
-        }
-    }
-
-    /** Holds information associated with a track. */
-    public static final class TrackData {
-
-        /** Holds {@link MediaFormat} information for the track. */
-        @NonNull public final MediaFormat mediaFormat;
-
-        /**
-         * Holds {@link DrmInitData} necessary to acquire keys associated with the track, or null if
-         * the track has no encryption data.
-         */
-        @Nullable public final DrmInitData drmInitData;
-
-        private TrackData(MediaFormat mediaFormat, DrmInitData drmInitData) {
-            this.mediaFormat = mediaFormat;
-            this.drmInitData = drmInitData;
-        }
-    }
-
-    /** Defines a seek point in a media stream. */
-    public static final class SeekPoint {
-
-        /** A {@link SeekPoint} whose time and byte offset are both set to 0. */
-        @NonNull public static final SeekPoint START = new SeekPoint(0, 0);
-
-        /** The time of the seek point, in microseconds. */
-        public final long timeMicros;
-
-        /** The byte offset of the seek point. */
-        public final long position;
-
-        /**
-         * @param timeMicros The time of the seek point, in microseconds.
-         * @param position The byte offset of the seek point.
-         */
-        private SeekPoint(long timeMicros, long position) {
-            this.timeMicros = timeMicros;
-            this.position = position;
-        }
-
-        @Override
-        @NonNull
-        public String toString() {
-            return "[timeMicros=" + timeMicros + ", position=" + position + "]";
-        }
-
-        @Override
-        public boolean equals(@Nullable Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null || getClass() != obj.getClass()) {
-                return false;
-            }
-            SeekPoint other = (SeekPoint) obj;
-            return timeMicros == other.timeMicros && position == other.position;
-        }
-
-        @Override
-        public int hashCode() {
-            int result = (int) timeMicros;
-            result = 31 * result + (int) position;
-            return result;
-        }
-    }
-
-    /** Provides input data to {@link MediaParser}. */
-    public interface InputReader {
-
-        /**
-         * Reads up to {@code readLength} bytes of data and stores them into {@code buffer},
-         * starting at index {@code offset}.
-         *
-         * <p>This method blocks until at least one byte is read, the end of input is detected, or
-         * an exception is thrown. The read position advances to the first unread byte.
-         *
-         * @param buffer The buffer into which the read data should be stored.
-         * @param offset The start offset into {@code buffer} at which data should be written.
-         * @param readLength The maximum number of bytes to read.
-         * @return The non-zero number of bytes read, or -1 if no data is available because the end
-         *     of the input has been reached.
-         * @throws java.io.IOException If an error occurs reading from the source.
-         */
-        int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException;
-
-        /** Returns the current read position (byte offset) in the stream. */
-        long getPosition();
-
-        /** Returns the length of the input in bytes, or -1 if the length is unknown. */
-        long getLength();
-    }
-
-    /** {@link InputReader} that allows setting the read position. */
-    public interface SeekableInputReader extends InputReader {
-
-        /**
-         * Sets the read position at the given {@code position}.
-         *
-         * <p>{@link #advance} will immediately return after calling this method.
-         *
-         * @param position The position to seek to, in bytes.
-         */
-        void seekToPosition(long position);
-    }
-
-    /** Receives extracted media sample data and metadata from {@link MediaParser}. */
-    public interface OutputConsumer {
-
-        /**
-         * Called when a {@link SeekMap} has been extracted from the stream.
-         *
-         * <p>This method is called at least once before any samples are {@link #onSampleCompleted
-         * complete}. May be called multiple times after that in order to add {@link SeekPoint
-         * SeekPoints}.
-         *
-         * @param seekMap The extracted {@link SeekMap}.
-         */
-        void onSeekMapFound(@NonNull SeekMap seekMap);
-
-        /**
-         * Called when the number of tracks is found.
-         *
-         * @param numberOfTracks The number of tracks in the stream.
-         */
-        void onTrackCountFound(int numberOfTracks);
-
-        /**
-         * Called when new {@link TrackData} is found in the stream.
-         *
-         * @param trackIndex The index of the track for which the {@link TrackData} was extracted.
-         * @param trackData The extracted {@link TrackData}.
-         */
-        void onTrackDataFound(int trackIndex, @NonNull TrackData trackData);
-
-        /**
-         * Called when sample data is found in the stream.
-         *
-         * <p>If the invocation of this method returns before the entire {@code inputReader} {@link
-         * InputReader#getLength() length} is consumed, the method will be called again for the
-         * implementer to read the remaining data. Implementers should surface any thrown {@link
-         * IOException} caused by reading from {@code input}.
-         *
-         * @param trackIndex The index of the track to which the sample data corresponds.
-         * @param inputReader The {@link InputReader} from which to read the data.
-         * @throws IOException If an exception occurs while reading from {@code inputReader}.
-         */
-        void onSampleDataFound(int trackIndex, @NonNull InputReader inputReader) throws IOException;
-
-        /**
-         * Called once all the data of a sample has been passed to {@link #onSampleDataFound}.
-         *
-         * <p>Includes sample metadata, like presentation timestamp and flags.
-         *
-         * @param trackIndex The index of the track to which the sample corresponds.
-         * @param timeMicros The media timestamp associated with the sample, in microseconds.
-         * @param flags Flags associated with the sample. See the {@code SAMPLE_FLAG_*} constants.
-         * @param size The size of the sample data, in bytes.
-         * @param offset The number of bytes that have been consumed by {@code
-         *     onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the
-         *     last byte belonging to the sample whose metadata is being passed.
-         * @param cryptoInfo Encryption data required to decrypt the sample. May be null for
-         *     unencrypted samples. Implementors should treat any output {@link CryptoInfo}
-         *     instances as immutable. MediaParser will not modify any output {@code cryptoInfos}
-         *     and implementors should not modify them either.
-         */
-        void onSampleCompleted(
-                int trackIndex,
-                long timeMicros,
-                @SampleFlags int flags,
-                int size,
-                int offset,
-                @Nullable CryptoInfo cryptoInfo);
-    }
-
-    /**
-     * Thrown if all parser implementations provided to {@link #create} failed to sniff the input
-     * content.
-     */
-    public static final class UnrecognizedInputFormatException extends IOException {
-
-        /**
-         * Creates a new instance which signals that the parsers with the given names failed to
-         * parse the input.
-         */
-        @NonNull
-        @CheckResult
-        private static UnrecognizedInputFormatException createForExtractors(
-                @NonNull String... extractorNames) {
-            StringBuilder builder = new StringBuilder();
-            builder.append("None of the available parsers ( ");
-            builder.append(extractorNames[0]);
-            for (int i = 1; i < extractorNames.length; i++) {
-                builder.append(", ");
-                builder.append(extractorNames[i]);
-            }
-            builder.append(") could read the stream.");
-            return new UnrecognizedInputFormatException(builder.toString());
-        }
-
-        private UnrecognizedInputFormatException(String extractorNames) {
-            super(extractorNames);
-        }
-    }
-
-    /** Thrown when an error occurs while parsing a media stream. */
-    public static final class ParsingException extends IOException {
-
-        private ParsingException(ParserException cause) {
-            super(cause);
-        }
-    }
-
-    // Sample flags.
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-            flag = true,
-            value = {
-                SAMPLE_FLAG_KEY_FRAME,
-                SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA,
-                SAMPLE_FLAG_LAST_SAMPLE,
-                SAMPLE_FLAG_ENCRYPTED,
-                SAMPLE_FLAG_DECODE_ONLY
-            })
-    public @interface SampleFlags {}
-    /** Indicates that the sample holds a synchronization sample. */
-    public static final int SAMPLE_FLAG_KEY_FRAME = MediaCodec.BUFFER_FLAG_KEY_FRAME;
-    /**
-     * Indicates that the sample has supplemental data.
-     *
-     * <p>Samples will not have this flag set unless the {@code
-     * "android.media.mediaparser.includeSupplementalData"} parameter is set to {@code true} via
-     * {@link #setParameter}.
-     *
-     * <p>Samples with supplemental data have the following sample data format:
-     *
-     * <ul>
-     *   <li>If the {@code "android.media.mediaparser.inBandCryptoInfo"} parameter is set, all
-     *       encryption information.
-     *   <li>(4 bytes) {@code sample_data_size}: The size of the actual sample data, not including
-     *       supplemental data or encryption information.
-     *   <li>({@code sample_data_size} bytes): The media sample data.
-     *   <li>(remaining bytes) The supplemental data.
-     * </ul>
-     */
-    public static final int SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA = 1 << 28;
-    /** Indicates that the sample is known to contain the last media sample of the stream. */
-    public static final int SAMPLE_FLAG_LAST_SAMPLE = 1 << 29;
-    /** Indicates that the sample is (at least partially) encrypted. */
-    public static final int SAMPLE_FLAG_ENCRYPTED = 1 << 30;
-    /** Indicates that the sample should be decoded but not rendered. */
-    public static final int SAMPLE_FLAG_DECODE_ONLY = 1 << 31;
-
-    // Parser implementation names.
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @StringDef(
-            prefix = {"PARSER_NAME_"},
-            value = {
-                PARSER_NAME_UNKNOWN,
-                PARSER_NAME_MATROSKA,
-                PARSER_NAME_FMP4,
-                PARSER_NAME_MP4,
-                PARSER_NAME_MP3,
-                PARSER_NAME_ADTS,
-                PARSER_NAME_AC3,
-                PARSER_NAME_TS,
-                PARSER_NAME_FLV,
-                PARSER_NAME_OGG,
-                PARSER_NAME_PS,
-                PARSER_NAME_WAV,
-                PARSER_NAME_AMR,
-                PARSER_NAME_AC4,
-                PARSER_NAME_FLAC
-            })
-    public @interface ParserName {}
-
-    /** Parser name returned by {@link #getParserName()} when no parser has been selected yet. */
-    public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
-    /**
-     * Parser for the Matroska container format, as defined in the <a
-     * href="https://matroska.org/technical/specs/">spec</a>.
-     */
-    public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser";
-    /**
-     * Parser for fragmented files using the MP4 container format, as defined in ISO/IEC 14496-12.
-     */
-    public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser";
-    /**
-     * Parser for non-fragmented files using the MP4 container format, as defined in ISO/IEC
-     * 14496-12.
-     */
-    public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser";
-    /** Parser for the MP3 container format, as defined in ISO/IEC 11172-3. */
-    public static final String PARSER_NAME_MP3 = "android.media.mediaparser.Mp3Parser";
-    /** Parser for the ADTS container format, as defined in ISO/IEC 13818-7. */
-    public static final String PARSER_NAME_ADTS = "android.media.mediaparser.AdtsParser";
-    /**
-     * Parser for the AC-3 container format, as defined in Digital Audio Compression Standard
-     * (AC-3).
-     */
-    public static final String PARSER_NAME_AC3 = "android.media.mediaparser.Ac3Parser";
-    /** Parser for the TS container format, as defined in ISO/IEC 13818-1. */
-    public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
-    /**
-     * Parser for the FLV container format, as defined in Adobe Flash Video File Format
-     * Specification.
-     */
-    public static final String PARSER_NAME_FLV = "android.media.mediaparser.FlvParser";
-    /** Parser for the OGG container format, as defined in RFC 3533. */
-    public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
-    /** Parser for the PS container format, as defined in ISO/IEC 11172-1. */
-    public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
-    /**
-     * Parser for the WAV container format, as defined in Multimedia Programming Interface and Data
-     * Specifications.
-     */
-    public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
-    /** Parser for the AMR container format, as defined in RFC 4867. */
-    public static final String PARSER_NAME_AMR = "android.media.mediaparser.AmrParser";
-    /**
-     * Parser for the AC-4 container format, as defined by Dolby AC-4: Audio delivery for
-     * Next-Generation Entertainment Services.
-     */
-    public static final String PARSER_NAME_AC4 = "android.media.mediaparser.Ac4Parser";
-    /**
-     * Parser for the FLAC container format, as defined in the <a
-     * href="https://xiph.org/flac/">spec</a>.
-     */
-    public static final String PARSER_NAME_FLAC = "android.media.mediaparser.FlacParser";
-
-    // MediaParser parameters.
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @StringDef(
-            prefix = {"PARAMETER_"},
-            value = {
-                PARAMETER_ADTS_ENABLE_CBR_SEEKING,
-                PARAMETER_AMR_ENABLE_CBR_SEEKING,
-                PARAMETER_FLAC_DISABLE_ID3,
-                PARAMETER_MP4_IGNORE_EDIT_LISTS,
-                PARAMETER_MP4_IGNORE_TFDT_BOX,
-                PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES,
-                PARAMETER_MATROSKA_DISABLE_CUES_SEEKING,
-                PARAMETER_MP3_DISABLE_ID3,
-                PARAMETER_MP3_ENABLE_CBR_SEEKING,
-                PARAMETER_MP3_ENABLE_INDEX_SEEKING,
-                PARAMETER_TS_MODE,
-                PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES,
-                PARAMETER_TS_IGNORE_AAC_STREAM,
-                PARAMETER_TS_IGNORE_AVC_STREAM,
-                PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM,
-                PARAMETER_TS_DETECT_ACCESS_UNITS,
-                PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS,
-                PARAMETER_IN_BAND_CRYPTO_INFO,
-                PARAMETER_INCLUDE_SUPPLEMENTAL_DATA
-            })
-    public @interface ParameterName {}
-
-    /**
-     * Sets whether constant bitrate seeking should be enabled for ADTS parsing. {@code boolean}
-     * expected. Default value is {@code false}.
-     */
-    public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING =
-            "android.media.mediaparser.adts.enableCbrSeeking";
-    /**
-     * Sets whether constant bitrate seeking should be enabled for AMR. {@code boolean} expected.
-     * Default value is {@code false}.
-     */
-    public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING =
-            "android.media.mediaparser.amr.enableCbrSeeking";
-    /**
-     * Sets whether the ID3 track should be disabled for FLAC. {@code boolean} expected. Default
-     * value is {@code false}.
-     */
-    public static final String PARAMETER_FLAC_DISABLE_ID3 =
-            "android.media.mediaparser.flac.disableId3";
-    /**
-     * Sets whether MP4 parsing should ignore edit lists. {@code boolean} expected. Default value is
-     * {@code false}.
-     */
-    public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS =
-            "android.media.mediaparser.mp4.ignoreEditLists";
-    /**
-     * Sets whether MP4 parsing should ignore the tfdt box. {@code boolean} expected. Default value
-     * is {@code false}.
-     */
-    public static final String PARAMETER_MP4_IGNORE_TFDT_BOX =
-            "android.media.mediaparser.mp4.ignoreTfdtBox";
-    /**
-     * Sets whether MP4 parsing should treat all video frames as key frames. {@code boolean}
-     * expected. Default value is {@code false}.
-     */
-    public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES =
-            "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
-    /**
-     * Sets whether Matroska parsing should avoid seeking to the cues element. {@code boolean}
-     * expected. Default value is {@code false}.
-     *
-     * <p>If this flag is enabled and the cues element occurs after the first cluster, then the
-     * media is treated as unseekable.
-     */
-    public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING =
-            "android.media.mediaparser.matroska.disableCuesSeeking";
-    /**
-     * Sets whether the ID3 track should be disabled for MP3. {@code boolean} expected. Default
-     * value is {@code false}.
-     */
-    public static final String PARAMETER_MP3_DISABLE_ID3 =
-            "android.media.mediaparser.mp3.disableId3";
-    /**
-     * Sets whether constant bitrate seeking should be enabled for MP3. {@code boolean} expected.
-     * Default value is {@code false}.
-     */
-    public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING =
-            "android.media.mediaparser.mp3.enableCbrSeeking";
-    /**
-     * Sets whether MP3 parsing should generate a time-to-byte mapping. {@code boolean} expected.
-     * Default value is {@code false}.
-     *
-     * <p>Enabling this flag may require to scan a significant portion of the file to compute a seek
-     * point. Therefore, it should only be used if:
-     *
-     * <ul>
-     *   <li>the file is small, or
-     *   <li>the bitrate is variable (or the type of bitrate is unknown) and the seeking metadata
-     *       provided in the file is not precise enough (or is not present).
-     * </ul>
-     */
-    public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING =
-            "android.media.mediaparser.mp3.enableIndexSeeking";
-    /**
-     * Sets the operation mode for TS parsing. {@code String} expected. Valid values are {@code
-     * "single_pmt"}, {@code "multi_pmt"}, and {@code "hls"}. Default value is {@code "single_pmt"}.
-     *
-     * <p>The operation modes alter the way TS behaves so that it can handle certain kinds of
-     * commonly-occurring malformed media.
-     *
-     * <ul>
-     *   <li>{@code "single_pmt"}: Only the first found PMT is parsed. Others are ignored, even if
-     *       more PMTs are declared in the PAT.
-     *   <li>{@code "multi_pmt"}: Behave as described in ISO/IEC 13818-1.
-     *   <li>{@code "hls"}: Enable {@code "single_pmt"} mode, and ignore continuity counters.
-     * </ul>
-     */
-    public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
-    /**
-     * Sets whether TS should treat samples consisting of non-IDR I slices as synchronization
-     * samples (key-frames). {@code boolean} expected. Default value is {@code false}.
-     */
-    public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES =
-            "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
-    /**
-     * Sets whether TS parsing should ignore AAC elementary streams. {@code boolean} expected.
-     * Default value is {@code false}.
-     */
-    public static final String PARAMETER_TS_IGNORE_AAC_STREAM =
-            "android.media.mediaparser.ts.ignoreAacStream";
-    /**
-     * Sets whether TS parsing should ignore AVC elementary streams. {@code boolean} expected.
-     * Default value is {@code false}.
-     */
-    public static final String PARAMETER_TS_IGNORE_AVC_STREAM =
-            "android.media.mediaparser.ts.ignoreAvcStream";
-    /**
-     * Sets whether TS parsing should ignore splice information streams. {@code boolean} expected.
-     * Default value is {@code false}.
-     */
-    public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM =
-            "android.media.mediaparser.ts.ignoreSpliceInfoStream";
-    /**
-     * Sets whether TS parsing should split AVC stream into access units based on slice headers.
-     * {@code boolean} expected. Default value is {@code false}.
-     *
-     * <p>This flag should be left disabled if the stream contains access units delimiters in order
-     * to avoid unnecessary computational costs.
-     */
-    public static final String PARAMETER_TS_DETECT_ACCESS_UNITS =
-            "android.media.mediaparser.ts.ignoreDetectAccessUnits";
-    /**
-     * Sets whether TS parsing should handle HDMV DTS audio streams. {@code boolean} expected.
-     * Default value is {@code false}.
-     *
-     * <p>Enabling this flag will disable the detection of SCTE subtitles.
-     */
-    public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS =
-            "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
-    /**
-     * Sets whether encryption data should be sent in-band with the sample data, as per {@link
-     * OutputConsumer#onSampleDataFound}. {@code boolean} expected. Default value is {@code false}.
-     *
-     * <p>If this parameter is set, encrypted samples' data will be prefixed with the encryption
-     * information bytes. The format for in-band encryption information is:
-     *
-     * <ul>
-     *   <li>(1 byte) {@code encryption_signal_byte}: Most significant bit signals whether the
-     *       encryption data contains subsample encryption data. The remaining bits contain {@code
-     *       initialization_vector_size}.
-     *   <li>({@code initialization_vector_size} bytes) Initialization vector.
-     *   <li>If subsample encryption data is present, as per {@code encryption_signal_byte}, the
-     *       encryption data also contains:
-     *       <ul>
-     *         <li>(2 bytes) {@code subsample_encryption_data_length}.
-     *         <li>({@code subsample_encryption_data_length * 6} bytes) Subsample encryption data
-     *             (repeated {@code subsample_encryption_data_length} times):
-     *             <ul>
-     *               <li>(2 bytes) Size of a clear section in sample.
-     *               <li>(4 bytes) Size of an encryption section in sample.
-     *             </ul>
-     *       </ul>
-     * </ul>
-     *
-     * @hide
-     */
-    public static final String PARAMETER_IN_BAND_CRYPTO_INFO =
-            "android.media.mediaparser.inBandCryptoInfo";
-    /**
-     * Sets whether supplemental data should be included as part of the sample data. {@code boolean}
-     * expected. Default value is {@code false}. See {@link #SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA} for
-     * information about the sample data format.
-     *
-     * @hide
-     */
-    public static final String PARAMETER_INCLUDE_SUPPLEMENTAL_DATA =
-            "android.media.mediaparser.includeSupplementalData";
-    /**
-     * Sets whether sample timestamps may start from non-zero offsets. {@code boolean} expected.
-     * Default value is {@code false}.
-     *
-     * <p>When set to true, sample timestamps will not be offset to start from zero, and the media
-     * provided timestamps will be used instead. For example, transport stream sample timestamps
-     * will not be converted to a zero-based timebase.
-     *
-     * @hide
-     */
-    public static final String PARAMETER_IGNORE_TIMESTAMP_OFFSET =
-            "android.media.mediaparser.ignoreTimestampOffset";
-    /**
-     * Sets whether each track type should be eagerly exposed. {@code boolean} expected. Default
-     * value is {@code false}.
-     *
-     * <p>When set to true, each track type will be eagerly exposed through a call to {@link
-     * OutputConsumer#onTrackDataFound} containing a single-value {@link MediaFormat}. The key for
-     * the track type is {@code "track-type-string"}, and the possible values are {@code "video"},
-     * {@code "audio"}, {@code "text"}, {@code "metadata"}, and {@code "unknown"}.
-     *
-     * @hide
-     */
-    public static final String PARAMETER_EAGERLY_EXPOSE_TRACKTYPE =
-            "android.media.mediaparser.eagerlyExposeTrackType";
-    /**
-     * Sets whether a dummy {@link SeekMap} should be exposed before starting extraction. {@code
-     * boolean} expected. Default value is {@code false}.
-     *
-     * <p>For each {@link SeekMap#getSeekPoints} call, the dummy {@link SeekMap} returns a single
-     * {@link SeekPoint} whose {@link SeekPoint#timeMicros} matches the requested timestamp, and
-     * whose {@link SeekPoint#position} is 0.
-     *
-     * @hide
-     */
-    public static final String PARAMETER_EXPOSE_DUMMY_SEEKMAP =
-            "android.media.mediaparser.exposeDummySeekMap";
-
-    /**
-     * Sets whether chunk indices available in the extracted media should be exposed as {@link
-     * MediaFormat MediaFormats}. {@code boolean} expected. Default value is {@link false}.
-     *
-     * <p>When set to true, any information about media segmentation will be exposed as a {@link
-     * MediaFormat} (with track index 0) containing four {@link ByteBuffer} elements under the
-     * following keys:
-     *
-     * <ul>
-     *   <li>"chunk-index-int-sizes": Contains {@code ints} representing the sizes in bytes of each
-     *       of the media segments.
-     *   <li>"chunk-index-long-offsets": Contains {@code longs} representing the byte offsets of
-     *       each segment in the stream.
-     *   <li>"chunk-index-long-us-durations": Contains {@code longs} representing the media duration
-     *       of each segment, in microseconds.
-     *   <li>"chunk-index-long-us-times": Contains {@code longs} representing the start time of each
-     *       segment, in microseconds.
-     * </ul>
-     *
-     * @hide
-     */
-    public static final String PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT =
-            "android.media.mediaParser.exposeChunkIndexAsMediaFormat";
-    /**
-     * Sets a list of closed-caption {@link MediaFormat MediaFormats} that should be exposed as part
-     * of the extracted media. {@code List<MediaFormat>} expected. Default value is an empty list.
-     *
-     * <p>Expected keys in the {@link MediaFormat} are:
-     *
-     * <ul>
-     *   <p>{@link MediaFormat#KEY_MIME}: Determine the type of captions (for example,
-     *   application/cea-608). Mandatory.
-     *   <p>{@link MediaFormat#KEY_CAPTION_SERVICE_NUMBER}: Determine the channel on which the
-     *   captions are transmitted. Optional.
-     * </ul>
-     *
-     * @hide
-     */
-    public static final String PARAMETER_EXPOSE_CAPTION_FORMATS =
-            "android.media.mediaParser.exposeCaptionFormats";
-    /**
-     * Sets whether the value associated with {@link #PARAMETER_EXPOSE_CAPTION_FORMATS} should
-     * override any in-band caption service declarations. {@code boolean} expected. Default value is
-     * {@link false}.
-     *
-     * <p>When {@code false}, any present in-band caption services information will override the
-     * values associated with {@link #PARAMETER_EXPOSE_CAPTION_FORMATS}.
-     *
-     * @hide
-     */
-    public static final String PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS =
-            "android.media.mediaParser.overrideInBandCaptionDeclarations";
-    /**
-     * Sets whether a track for EMSG events should be exposed in case of parsing a container that
-     * supports them. {@code boolean} expected. Default value is {@link false}.
-     *
-     * @hide
-     */
-    public static final String PARAMETER_EXPOSE_EMSG_TRACK =
-            "android.media.mediaParser.exposeEmsgTrack";
-
-    // Private constants.
-
-    private static final String TAG = "MediaParser";
-    private static final String JNI_LIBRARY_NAME = "mediaparser-jni";
-    private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
-    private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
-    private static final String TS_MODE_SINGLE_PMT = "single_pmt";
-    private static final String TS_MODE_MULTI_PMT = "multi_pmt";
-    private static final String TS_MODE_HLS = "hls";
-    private static final int BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY = 6;
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-    private static final String MEDIAMETRICS_ELEMENT_SEPARATOR = "|";
-    private static final int MEDIAMETRICS_MAX_STRING_SIZE = 200;
-    private static final int MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH;
-    /**
-     * Intentional error introduced to reported metrics to prevent identification of the parsed
-     * media. Note: Increasing this value may cause older hostside CTS tests to fail.
-     */
-    private static final float MEDIAMETRICS_DITHER = .02f;
-
-    @IntDef(
-            value = {
-                STATE_READING_SIGNAL_BYTE,
-                STATE_READING_INIT_VECTOR,
-                STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE,
-                STATE_READING_SUBSAMPLE_ENCRYPTION_DATA
-            })
-    private @interface EncryptionDataReadState {}
-
-    private static final int STATE_READING_SIGNAL_BYTE = 0;
-    private static final int STATE_READING_INIT_VECTOR = 1;
-    private static final int STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE = 2;
-    private static final int STATE_READING_SUBSAMPLE_ENCRYPTION_DATA = 3;
-
-    // Instance creation methods.
-
-    /**
-     * Creates an instance backed by the parser with the given {@code name}. The returned instance
-     * will attempt parsing without sniffing the content.
-     *
-     * @param name The name of the parser that will be associated with the created instance.
-     * @param outputConsumer The {@link OutputConsumer} to which track data and samples are pushed.
-     * @return A new instance.
-     * @throws IllegalArgumentException If an invalid name is provided.
-     */
-    @NonNull
-    public static MediaParser createByName(
-            @NonNull @ParserName String name, @NonNull OutputConsumer outputConsumer) {
-        String[] nameAsArray = new String[] {name};
-        assertValidNames(nameAsArray);
-        return new MediaParser(outputConsumer, /* createdByName= */ true, name);
-    }
-
-    /**
-     * Creates an instance whose backing parser will be selected by sniffing the content during the
-     * first {@link #advance} call. Parser implementations will sniff the content in order of
-     * appearance in {@code parserNames}.
-     *
-     * @param outputConsumer The {@link OutputConsumer} to which extracted data is output.
-     * @param parserNames The names of the parsers to sniff the content with. If empty, a default
-     *     array of names is used.
-     * @return A new instance.
-     */
-    @NonNull
-    public static MediaParser create(
-            @NonNull OutputConsumer outputConsumer, @NonNull @ParserName String... parserNames) {
-        assertValidNames(parserNames);
-        if (parserNames.length == 0) {
-            parserNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
-        }
-        return new MediaParser(outputConsumer, /* createdByName= */ false, parserNames);
-    }
-
-    // Misc static methods.
-
-    /**
-     * Returns an immutable list with the names of the parsers that are suitable for container
-     * formats with the given {@link MediaFormat}.
-     *
-     * <p>A parser supports a {@link MediaFormat} if the mime type associated with {@link
-     * MediaFormat#KEY_MIME} corresponds to the supported container format.
-     *
-     * @param mediaFormat The {@link MediaFormat} to check support for.
-     * @return The parser names that support the given {@code mediaFormat}, or the list of all
-     *     parsers available if no container specific format information is provided.
-     */
-    @NonNull
-    @ParserName
-    public static List<String> getParserNames(@NonNull MediaFormat mediaFormat) {
-        String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
-        mimeType = mimeType == null ? null : Util.toLowerInvariant(mimeType.trim());
-        if (TextUtils.isEmpty(mimeType)) {
-            // No MIME type provided. Return all.
-            return Collections.unmodifiableList(
-                    new ArrayList<>(EXTRACTOR_FACTORIES_BY_NAME.keySet()));
-        }
-        ArrayList<String> result = new ArrayList<>();
-        switch (mimeType) {
-            case "video/x-matroska":
-            case "audio/x-matroska":
-            case "video/x-webm":
-            case "audio/x-webm":
-                result.add(PARSER_NAME_MATROSKA);
-                break;
-            case "video/mp4":
-            case "audio/mp4":
-            case "application/mp4":
-                result.add(PARSER_NAME_MP4);
-                result.add(PARSER_NAME_FMP4);
-                break;
-            case "audio/mpeg":
-                result.add(PARSER_NAME_MP3);
-                break;
-            case "audio/aac":
-                result.add(PARSER_NAME_ADTS);
-                break;
-            case "audio/ac3":
-                result.add(PARSER_NAME_AC3);
-                break;
-            case "video/mp2t":
-            case "audio/mp2t":
-                result.add(PARSER_NAME_TS);
-                break;
-            case "video/x-flv":
-                result.add(PARSER_NAME_FLV);
-                break;
-            case "video/ogg":
-            case "audio/ogg":
-            case "application/ogg":
-                result.add(PARSER_NAME_OGG);
-                break;
-            case "video/mp2p":
-            case "video/mp1s":
-                result.add(PARSER_NAME_PS);
-                break;
-            case "audio/vnd.wave":
-            case "audio/wav":
-            case "audio/wave":
-            case "audio/x-wav":
-                result.add(PARSER_NAME_WAV);
-                break;
-            case "audio/amr":
-                result.add(PARSER_NAME_AMR);
-                break;
-            case "audio/ac4":
-                result.add(PARSER_NAME_AC4);
-                break;
-            case "audio/flac":
-            case "audio/x-flac":
-                result.add(PARSER_NAME_FLAC);
-                break;
-            default:
-                // No parsers support the given mime type. Do nothing.
-                break;
-        }
-        return Collections.unmodifiableList(result);
-    }
-
-    // Private fields.
-
-    private final Map<String, Object> mParserParameters;
-    private final OutputConsumer mOutputConsumer;
-    private final String[] mParserNamesPool;
-    private final PositionHolder mPositionHolder;
-    private final InputReadingDataReader mExoDataReader;
-    private final DataReaderAdapter mScratchDataReaderAdapter;
-    private final ParsableByteArrayAdapter mScratchParsableByteArrayAdapter;
-    @Nullable private final Constructor<DrmInitData.SchemeInitData> mSchemeInitDataConstructor;
-    private final ArrayList<Format> mMuxedCaptionFormats;
-    private boolean mInBandCryptoInfo;
-    private boolean mIncludeSupplementalData;
-    private boolean mIgnoreTimestampOffset;
-    private boolean mEagerlyExposeTrackType;
-    private boolean mExposeDummySeekMap;
-    private boolean mExposeChunkIndexAsMediaFormat;
-    private String mParserName;
-    private Extractor mExtractor;
-    private ExtractorInput mExtractorInput;
-    private boolean mPendingExtractorInit;
-    private long mPendingSeekPosition;
-    private long mPendingSeekTimeMicros;
-    private boolean mLoggedSchemeInitDataCreationException;
-    private boolean mReleased;
-
-    // MediaMetrics fields.
-    @Nullable private LogSessionId mLogSessionId;
-    private final boolean mCreatedByName;
-    private final SparseArray<Format> mTrackFormats;
-    private String mLastObservedExceptionName;
-    private long mDurationMillis;
-    private long mResourceByteCount;
-
-    // Public methods.
-
-    /**
-     * Sets parser-specific parameters which allow customizing behavior.
-     *
-     * <p>Must be called before the first call to {@link #advance}.
-     *
-     * @param parameterName The name of the parameter to set. See {@code PARAMETER_*} constants for
-     *     documentation on possible values.
-     * @param value The value to set for the given {@code parameterName}. See {@code PARAMETER_*}
-     *     constants for documentation on the expected types.
-     * @return This instance, for convenience.
-     * @throws IllegalStateException If called after calling {@link #advance} on the same instance.
-     */
-    @NonNull
-    public MediaParser setParameter(
-            @NonNull @ParameterName String parameterName, @NonNull Object value) {
-        if (mExtractor != null) {
-            throw new IllegalStateException(
-                    "setParameters() must be called before the first advance() call.");
-        }
-        Class expectedType = EXPECTED_TYPE_BY_PARAMETER_NAME.get(parameterName);
-        // Ignore parameter names that are not contained in the map, in case the client is passing
-        // a parameter that is being added in a future version of this library.
-        if (expectedType != null && !expectedType.isInstance(value)) {
-            throw new IllegalArgumentException(
-                    parameterName
-                            + " expects a "
-                            + expectedType.getSimpleName()
-                            + " but a "
-                            + value.getClass().getSimpleName()
-                            + " was passed.");
-        }
-        if (PARAMETER_TS_MODE.equals(parameterName)
-                && !TS_MODE_SINGLE_PMT.equals(value)
-                && !TS_MODE_HLS.equals(value)
-                && !TS_MODE_MULTI_PMT.equals(value)) {
-            throw new IllegalArgumentException(PARAMETER_TS_MODE + " does not accept: " + value);
-        }
-        if (PARAMETER_IN_BAND_CRYPTO_INFO.equals(parameterName)) {
-            mInBandCryptoInfo = (boolean) value;
-        }
-        if (PARAMETER_INCLUDE_SUPPLEMENTAL_DATA.equals(parameterName)) {
-            mIncludeSupplementalData = (boolean) value;
-        }
-        if (PARAMETER_IGNORE_TIMESTAMP_OFFSET.equals(parameterName)) {
-            mIgnoreTimestampOffset = (boolean) value;
-        }
-        if (PARAMETER_EAGERLY_EXPOSE_TRACKTYPE.equals(parameterName)) {
-            mEagerlyExposeTrackType = (boolean) value;
-        }
-        if (PARAMETER_EXPOSE_DUMMY_SEEKMAP.equals(parameterName)) {
-            mExposeDummySeekMap = (boolean) value;
-        }
-        if (PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT.equals(parameterName)) {
-            mExposeChunkIndexAsMediaFormat = (boolean) value;
-        }
-        if (PARAMETER_EXPOSE_CAPTION_FORMATS.equals(parameterName)) {
-            setMuxedCaptionFormats((List<MediaFormat>) value);
-        }
-        mParserParameters.put(parameterName, value);
-        return this;
-    }
-
-    /**
-     * Returns whether the given {@code parameterName} is supported by this parser.
-     *
-     * @param parameterName The parameter name to check support for. One of the {@code PARAMETER_*}
-     *     constants.
-     * @return Whether the given {@code parameterName} is supported.
-     */
-    public boolean supportsParameter(@NonNull @ParameterName String parameterName) {
-        return EXPECTED_TYPE_BY_PARAMETER_NAME.containsKey(parameterName);
-    }
-
-    /**
-     * Returns the name of the backing parser implementation.
-     *
-     * <p>If this instance was creating using {@link #createByName}, the provided name is returned.
-     * If this instance was created using {@link #create}, this method will return {@link
-     * #PARSER_NAME_UNKNOWN} until the first call to {@link #advance}, after which the name of the
-     * backing parser implementation is returned.
-     *
-     * @return The name of the backing parser implementation, or null if the backing parser
-     *     implementation has not yet been selected.
-     */
-    @NonNull
-    @ParserName
-    public String getParserName() {
-        return mParserName;
-    }
-
-    /**
-     * Makes progress in the extraction of the input media stream, unless the end of the input has
-     * been reached.
-     *
-     * <p>This method will block until some progress has been made.
-     *
-     * <p>If this instance was created using {@link #create}, the first call to this method will
-     * sniff the content using the selected parser implementations.
-     *
-     * @param seekableInputReader The {@link SeekableInputReader} from which to obtain the media
-     *     container data.
-     * @return Whether there is any data left to extract. Returns false if the end of input has been
-     *     reached.
-     * @throws IOException If an error occurs while reading from the {@link SeekableInputReader}.
-     * @throws UnrecognizedInputFormatException If the format cannot be recognized by any of the
-     *     underlying parser implementations.
-     */
-    public boolean advance(@NonNull SeekableInputReader seekableInputReader) throws IOException {
-        if (mExtractorInput == null) {
-            // TODO: For efficiency, the same implementation should be used, by providing a
-            // clearBuffers() method, or similar.
-            long resourceLength = seekableInputReader.getLength();
-            if (mResourceByteCount == 0) {
-                // For resource byte count metric collection, we only take into account the length
-                // of the first provided input reader.
-                mResourceByteCount = resourceLength;
-            }
-            mExtractorInput =
-                    new DefaultExtractorInput(
-                            mExoDataReader, seekableInputReader.getPosition(), resourceLength);
-        }
-        mExoDataReader.mInputReader = seekableInputReader;
-
-        if (mExtractor == null) {
-            mPendingExtractorInit = true;
-            if (!mParserName.equals(PARSER_NAME_UNKNOWN)) {
-                mExtractor = createExtractor(mParserName);
-            } else {
-                for (String parserName : mParserNamesPool) {
-                    Extractor extractor = createExtractor(parserName);
-                    try {
-                        if (extractor.sniff(mExtractorInput)) {
-                            mParserName = parserName;
-                            mExtractor = extractor;
-                            mPendingExtractorInit = true;
-                            break;
-                        }
-                    } catch (EOFException e) {
-                        // Do nothing.
-                    } finally {
-                        mExtractorInput.resetPeekPosition();
-                    }
-                }
-                if (mExtractor == null) {
-                    UnrecognizedInputFormatException exception =
-                            UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
-                    mLastObservedExceptionName = exception.getClass().getName();
-                    throw exception;
-                }
-                return true;
-            }
-        }
-
-        if (mPendingExtractorInit) {
-            if (mExposeDummySeekMap) {
-                // We propagate the dummy seek map before initializing the extractor, in case the
-                // extractor initialization outputs a seek map.
-                mOutputConsumer.onSeekMapFound(SeekMap.DUMMY);
-            }
-            mExtractor.init(new ExtractorOutputAdapter());
-            mPendingExtractorInit = false;
-            // We return after initialization to allow clients use any output information before
-            // starting actual extraction.
-            return true;
-        }
-
-        if (isPendingSeek()) {
-            mExtractor.seek(mPendingSeekPosition, mPendingSeekTimeMicros);
-            removePendingSeek();
-        }
-
-        mPositionHolder.position = seekableInputReader.getPosition();
-        int result;
-        try {
-            result = mExtractor.read(mExtractorInput, mPositionHolder);
-        } catch (Exception e) {
-            mLastObservedExceptionName = e.getClass().getName();
-            if (e instanceof ParserException) {
-                throw new ParsingException((ParserException) e);
-            } else {
-                throw e;
-            }
-        }
-        if (result == Extractor.RESULT_END_OF_INPUT) {
-            mExtractorInput = null;
-            return false;
-        }
-        if (result == Extractor.RESULT_SEEK) {
-            mExtractorInput = null;
-            seekableInputReader.seekToPosition(mPositionHolder.position);
-        }
-        return true;
-    }
-
-    /**
-     * Seeks within the media container being extracted.
-     *
-     * <p>{@link SeekPoint SeekPoints} can be obtained from the {@link SeekMap} passed to {@link
-     * OutputConsumer#onSeekMapFound(SeekMap)}.
-     *
-     * <p>Following a call to this method, the {@link InputReader} passed to the next invocation of
-     * {@link #advance} must provide data starting from {@link SeekPoint#position} in the stream.
-     *
-     * @param seekPoint The {@link SeekPoint} to seek to.
-     */
-    public void seek(@NonNull SeekPoint seekPoint) {
-        if (mExtractor == null) {
-            mPendingSeekPosition = seekPoint.position;
-            mPendingSeekTimeMicros = seekPoint.timeMicros;
-        } else {
-            mExtractor.seek(seekPoint.position, seekPoint.timeMicros);
-        }
-    }
-
-    /**
-     * Releases any acquired resources.
-     *
-     * <p>After calling this method, this instance becomes unusable and no other methods should be
-     * invoked.
-     */
-    public void release() {
-        mExtractorInput = null;
-        mExtractor = null;
-        if (mReleased) {
-            // Nothing to do.
-            return;
-        }
-        mReleased = true;
-
-        String trackMimeTypes = buildMediaMetricsString(format -> format.sampleMimeType);
-        String trackCodecs = buildMediaMetricsString(format -> format.codecs);
-        int videoWidth = -1;
-        int videoHeight = -1;
-        for (int i = 0; i < mTrackFormats.size(); i++) {
-            Format format = mTrackFormats.valueAt(i);
-            if (format.width != Format.NO_VALUE && format.height != Format.NO_VALUE) {
-                videoWidth = format.width;
-                videoHeight = format.height;
-                break;
-            }
-        }
-
-        String alteredParameters =
-                String.join(
-                        MEDIAMETRICS_ELEMENT_SEPARATOR,
-                        mParserParameters.keySet().toArray(new String[0]));
-        alteredParameters =
-                alteredParameters.substring(
-                        0,
-                        Math.min(
-                                alteredParameters.length(),
-                                MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH));
-
-        nativeSubmitMetrics(
-                SdkLevel.isAtLeastS() ? getLogSessionIdStringV31() : "",
-                mParserName,
-                mCreatedByName,
-                String.join(MEDIAMETRICS_ELEMENT_SEPARATOR, mParserNamesPool),
-                mLastObservedExceptionName,
-                addDither(mResourceByteCount),
-                addDither(mDurationMillis),
-                trackMimeTypes,
-                trackCodecs,
-                alteredParameters,
-                videoWidth,
-                videoHeight);
-    }
-
-    @RequiresApi(31)
-    public void setLogSessionId(@NonNull LogSessionId logSessionId) {
-        this.mLogSessionId = Objects.requireNonNull(logSessionId);
-    }
-
-    @RequiresApi(31)
-    @NonNull
-    public LogSessionId getLogSessionId() {
-        return mLogSessionId != null ? mLogSessionId : LogSessionId.LOG_SESSION_ID_NONE;
-    }
-
-    // Private methods.
-
-    private MediaParser(
-            OutputConsumer outputConsumer, boolean createdByName, String... parserNamesPool) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
-            throw new UnsupportedOperationException("Android version must be R or greater.");
-        }
-        mParserParameters = new HashMap<>();
-        mOutputConsumer = outputConsumer;
-        mParserNamesPool = parserNamesPool;
-        mCreatedByName = createdByName;
-        mParserName = createdByName ? parserNamesPool[0] : PARSER_NAME_UNKNOWN;
-        mPositionHolder = new PositionHolder();
-        mExoDataReader = new InputReadingDataReader();
-        removePendingSeek();
-        mScratchDataReaderAdapter = new DataReaderAdapter();
-        mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
-        mSchemeInitDataConstructor = getSchemeInitDataConstructor();
-        mMuxedCaptionFormats = new ArrayList<>();
-
-        // MediaMetrics.
-        mTrackFormats = new SparseArray<>();
-        mLastObservedExceptionName = "";
-        mDurationMillis = -1;
-    }
-
-    private String buildMediaMetricsString(Function<Format, String> formatFieldGetter) {
-        StringBuilder stringBuilder = new StringBuilder();
-        for (int i = 0; i < mTrackFormats.size(); i++) {
-            if (i > 0) {
-                stringBuilder.append(MEDIAMETRICS_ELEMENT_SEPARATOR);
-            }
-            String fieldValue = formatFieldGetter.apply(mTrackFormats.valueAt(i));
-            stringBuilder.append(fieldValue != null ? fieldValue : "");
-        }
-        return stringBuilder.substring(
-                0, Math.min(stringBuilder.length(), MEDIAMETRICS_MAX_STRING_SIZE));
-    }
-
-    private void setMuxedCaptionFormats(List<MediaFormat> mediaFormats) {
-        mMuxedCaptionFormats.clear();
-        for (MediaFormat mediaFormat : mediaFormats) {
-            mMuxedCaptionFormats.add(toExoPlayerCaptionFormat(mediaFormat));
-        }
-    }
-
-    private boolean isPendingSeek() {
-        return mPendingSeekPosition >= 0;
-    }
-
-    private void removePendingSeek() {
-        mPendingSeekPosition = -1;
-        mPendingSeekTimeMicros = -1;
-    }
-
-    private Extractor createExtractor(String parserName) {
-        int flags = 0;
-        TimestampAdjuster timestampAdjuster = null;
-        if (mIgnoreTimestampOffset) {
-            timestampAdjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET);
-        }
-        switch (parserName) {
-            case PARSER_NAME_MATROSKA:
-                flags =
-                        getBooleanParameter(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING)
-                                ? MatroskaExtractor.FLAG_DISABLE_SEEK_FOR_CUES
-                                : 0;
-                return new MatroskaExtractor(flags);
-            case PARSER_NAME_FMP4:
-                flags |=
-                        getBooleanParameter(PARAMETER_EXPOSE_EMSG_TRACK)
-                                ? FragmentedMp4Extractor.FLAG_ENABLE_EMSG_TRACK
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
-                                ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_MP4_IGNORE_TFDT_BOX)
-                                ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES)
-                                ? FragmentedMp4Extractor
-                                        .FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
-                                : 0;
-                return new FragmentedMp4Extractor(
-                        flags,
-                        timestampAdjuster,
-                        /* sideloadedTrack= */ null,
-                        mMuxedCaptionFormats);
-            case PARSER_NAME_MP4:
-                flags |=
-                        getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
-                                ? Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
-                                : 0;
-                return new Mp4Extractor(flags);
-            case PARSER_NAME_MP3:
-                flags |=
-                        getBooleanParameter(PARAMETER_MP3_DISABLE_ID3)
-                                ? Mp3Extractor.FLAG_DISABLE_ID3_METADATA
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_MP3_ENABLE_CBR_SEEKING)
-                                ? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
-                                : 0;
-                // TODO: Add index seeking once we update the ExoPlayer version.
-                return new Mp3Extractor(flags);
-            case PARSER_NAME_ADTS:
-                flags |=
-                        getBooleanParameter(PARAMETER_ADTS_ENABLE_CBR_SEEKING)
-                                ? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
-                                : 0;
-                return new AdtsExtractor(flags);
-            case PARSER_NAME_AC3:
-                return new Ac3Extractor();
-            case PARSER_NAME_TS:
-                flags |=
-                        getBooleanParameter(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES)
-                                ? DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_TS_DETECT_ACCESS_UNITS)
-                                ? DefaultTsPayloadReaderFactory.FLAG_DETECT_ACCESS_UNITS
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS)
-                                ? DefaultTsPayloadReaderFactory.FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_TS_IGNORE_AAC_STREAM)
-                                ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_AAC_STREAM
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_TS_IGNORE_AVC_STREAM)
-                                ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_H264_STREAM
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM)
-                                ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_SPLICE_INFO_STREAM
-                                : 0;
-                flags |=
-                        getBooleanParameter(PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS)
-                                ? DefaultTsPayloadReaderFactory.FLAG_OVERRIDE_CAPTION_DESCRIPTORS
-                                : 0;
-                String tsMode = getStringParameter(PARAMETER_TS_MODE, TS_MODE_SINGLE_PMT);
-                int hlsMode =
-                        TS_MODE_SINGLE_PMT.equals(tsMode)
-                                ? TsExtractor.MODE_SINGLE_PMT
-                                : TS_MODE_HLS.equals(tsMode)
-                                        ? TsExtractor.MODE_HLS
-                                        : TsExtractor.MODE_MULTI_PMT;
-                return new TsExtractor(
-                        hlsMode,
-                        timestampAdjuster != null
-                                ? timestampAdjuster
-                                : new TimestampAdjuster(/* firstSampleTimestampUs= */ 0),
-                        new DefaultTsPayloadReaderFactory(flags, mMuxedCaptionFormats));
-            case PARSER_NAME_FLV:
-                return new FlvExtractor();
-            case PARSER_NAME_OGG:
-                return new OggExtractor();
-            case PARSER_NAME_PS:
-                return new PsExtractor();
-            case PARSER_NAME_WAV:
-                return new WavExtractor();
-            case PARSER_NAME_AMR:
-                flags |=
-                        getBooleanParameter(PARAMETER_AMR_ENABLE_CBR_SEEKING)
-                                ? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
-                                : 0;
-                return new AmrExtractor(flags);
-            case PARSER_NAME_AC4:
-                return new Ac4Extractor();
-            case PARSER_NAME_FLAC:
-                flags |=
-                        getBooleanParameter(PARAMETER_FLAC_DISABLE_ID3)
-                                ? FlacExtractor.FLAG_DISABLE_ID3_METADATA
-                                : 0;
-                return new FlacExtractor(flags);
-            default:
-                // Should never happen.
-                throw new IllegalStateException("Unexpected attempt to create: " + parserName);
-        }
-    }
-
-    private boolean getBooleanParameter(String name) {
-        return (boolean) mParserParameters.getOrDefault(name, false);
-    }
-
-    private String getStringParameter(String name, String defaultValue) {
-        return (String) mParserParameters.getOrDefault(name, defaultValue);
-    }
-
-    @RequiresApi(31)
-    private String getLogSessionIdStringV31() {
-        return mLogSessionId != null ? mLogSessionId.getStringId() : "";
-    }
-
-    // Private classes.
-
-    private static final class InputReadingDataReader implements DataReader {
-
-        public InputReader mInputReader;
-
-        @Override
-        public int read(byte[] buffer, int offset, int readLength) throws IOException {
-            return mInputReader.read(buffer, offset, readLength);
-        }
-    }
-
-    private final class MediaParserDrmInitData extends DrmInitData {
-
-        private final SchemeInitData[] mSchemeDatas;
-
-        private MediaParserDrmInitData(com.google.android.exoplayer2.drm.DrmInitData exoDrmInitData)
-                throws IllegalAccessException, InstantiationException, InvocationTargetException {
-            mSchemeDatas = new SchemeInitData[exoDrmInitData.schemeDataCount];
-            for (int i = 0; i < mSchemeDatas.length; i++) {
-                mSchemeDatas[i] = toFrameworkSchemeInitData(exoDrmInitData.get(i));
-            }
-        }
-
-        @Override
-        @Nullable
-        public SchemeInitData get(UUID schemeUuid) {
-            for (SchemeInitData schemeInitData : mSchemeDatas) {
-                if (schemeInitData.uuid.equals(schemeUuid)) {
-                    return schemeInitData;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public SchemeInitData getSchemeInitDataAt(int index) {
-            return mSchemeDatas[index];
-        }
-
-        @Override
-        public int getSchemeInitDataCount() {
-            return mSchemeDatas.length;
-        }
-
-        private DrmInitData.SchemeInitData toFrameworkSchemeInitData(SchemeData exoSchemeData)
-                throws IllegalAccessException, InvocationTargetException, InstantiationException {
-            return mSchemeInitDataConstructor.newInstance(
-                    exoSchemeData.uuid, exoSchemeData.mimeType, exoSchemeData.data);
-        }
-    }
-
-    private final class ExtractorOutputAdapter implements ExtractorOutput {
-
-        private final SparseArray<TrackOutput> mTrackOutputAdapters;
-        private boolean mTracksEnded;
-
-        private ExtractorOutputAdapter() {
-            mTrackOutputAdapters = new SparseArray<>();
-        }
-
-        @Override
-        public TrackOutput track(int id, int type) {
-            TrackOutput trackOutput = mTrackOutputAdapters.get(id);
-            if (trackOutput == null) {
-                int trackIndex = mTrackOutputAdapters.size();
-                trackOutput = new TrackOutputAdapter(trackIndex);
-                mTrackOutputAdapters.put(id, trackOutput);
-                if (mEagerlyExposeTrackType) {
-                    MediaFormat mediaFormat = new MediaFormat();
-                    mediaFormat.setString("track-type-string", toTypeString(type));
-                    mOutputConsumer.onTrackDataFound(
-                            trackIndex, new TrackData(mediaFormat, /* drmInitData= */ null));
-                }
-            }
-            return trackOutput;
-        }
-
-        @Override
-        public void endTracks() {
-            mOutputConsumer.onTrackCountFound(mTrackOutputAdapters.size());
-        }
-
-        @Override
-        public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
-            long durationUs = exoplayerSeekMap.getDurationUs();
-            if (durationUs != C.TIME_UNSET) {
-                mDurationMillis = C.usToMs(durationUs);
-            }
-            if (mExposeChunkIndexAsMediaFormat && exoplayerSeekMap instanceof ChunkIndex) {
-                ChunkIndex chunkIndex = (ChunkIndex) exoplayerSeekMap;
-                MediaFormat mediaFormat = new MediaFormat();
-                mediaFormat.setByteBuffer("chunk-index-int-sizes", toByteBuffer(chunkIndex.sizes));
-                mediaFormat.setByteBuffer(
-                        "chunk-index-long-offsets", toByteBuffer(chunkIndex.offsets));
-                mediaFormat.setByteBuffer(
-                        "chunk-index-long-us-durations", toByteBuffer(chunkIndex.durationsUs));
-                mediaFormat.setByteBuffer(
-                        "chunk-index-long-us-times", toByteBuffer(chunkIndex.timesUs));
-                mOutputConsumer.onTrackDataFound(
-                        /* trackIndex= */ 0, new TrackData(mediaFormat, /* drmInitData= */ null));
-            }
-            mOutputConsumer.onSeekMapFound(new SeekMap(exoplayerSeekMap));
-        }
-    }
-
-    private class TrackOutputAdapter implements TrackOutput {
-
-        private final int mTrackIndex;
-
-        private CryptoInfo mLastOutputCryptoInfo;
-        private CryptoInfo.Pattern mLastOutputEncryptionPattern;
-        private CryptoData mLastReceivedCryptoData;
-
-        @EncryptionDataReadState private int mEncryptionDataReadState;
-        private int mEncryptionDataSizeToSubtractFromSampleDataSize;
-        private int mEncryptionVectorSize;
-        private byte[] mScratchIvSpace;
-        private int mSubsampleEncryptionDataSize;
-        private int[] mScratchSubsampleEncryptedBytesCount;
-        private int[] mScratchSubsampleClearBytesCount;
-        private boolean mHasSubsampleEncryptionData;
-        private int mSkippedSupplementalDataBytes;
-
-        private TrackOutputAdapter(int trackIndex) {
-            mTrackIndex = trackIndex;
-            mScratchIvSpace = new byte[16]; // Size documented in CryptoInfo.
-            mScratchSubsampleEncryptedBytesCount = new int[32];
-            mScratchSubsampleClearBytesCount = new int[32];
-            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
-            mLastOutputEncryptionPattern =
-                    new CryptoInfo.Pattern(/* blocksToEncrypt= */ 0, /* blocksToSkip= */ 0);
-        }
-
-        @Override
-        public void format(Format format) {
-            mTrackFormats.put(mTrackIndex, format);
-            mOutputConsumer.onTrackDataFound(
-                    mTrackIndex,
-                    new TrackData(
-                            toMediaFormat(format), toFrameworkDrmInitData(format.drmInitData)));
-        }
-
-        @Override
-        public int sampleData(
-                DataReader input,
-                int length,
-                boolean allowEndOfInput,
-                @SampleDataPart int sampleDataPart)
-                throws IOException {
-            mScratchDataReaderAdapter.setDataReader(input, length);
-            long positionBeforeReading = mScratchDataReaderAdapter.getPosition();
-            mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchDataReaderAdapter);
-            return (int) (mScratchDataReaderAdapter.getPosition() - positionBeforeReading);
-        }
-
-        @Override
-        public void sampleData(
-                ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
-            if (sampleDataPart == SAMPLE_DATA_PART_ENCRYPTION && !mInBandCryptoInfo) {
-                while (length > 0) {
-                    switch (mEncryptionDataReadState) {
-                        case STATE_READING_SIGNAL_BYTE:
-                            int encryptionSignalByte = data.readUnsignedByte();
-                            length--;
-                            mHasSubsampleEncryptionData = ((encryptionSignalByte >> 7) & 1) != 0;
-                            mEncryptionVectorSize = encryptionSignalByte & 0x7F;
-                            mEncryptionDataSizeToSubtractFromSampleDataSize =
-                                    mEncryptionVectorSize + 1; // Signal byte.
-                            mEncryptionDataReadState = STATE_READING_INIT_VECTOR;
-                            break;
-                        case STATE_READING_INIT_VECTOR:
-                            Arrays.fill(mScratchIvSpace, (byte) 0); // Ensure 0-padding.
-                            data.readBytes(mScratchIvSpace, /* offset= */ 0, mEncryptionVectorSize);
-                            length -= mEncryptionVectorSize;
-                            if (mHasSubsampleEncryptionData) {
-                                mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE;
-                            } else {
-                                mSubsampleEncryptionDataSize = 0;
-                                mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
-                            }
-                            break;
-                        case STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE:
-                            mSubsampleEncryptionDataSize = data.readUnsignedShort();
-                            if (mScratchSubsampleClearBytesCount.length
-                                    < mSubsampleEncryptionDataSize) {
-                                mScratchSubsampleClearBytesCount =
-                                        new int[mSubsampleEncryptionDataSize];
-                                mScratchSubsampleEncryptedBytesCount =
-                                        new int[mSubsampleEncryptionDataSize];
-                            }
-                            length -= 2;
-                            mEncryptionDataSizeToSubtractFromSampleDataSize +=
-                                    2
-                                            + mSubsampleEncryptionDataSize
-                                                    * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
-                            mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_DATA;
-                            break;
-                        case STATE_READING_SUBSAMPLE_ENCRYPTION_DATA:
-                            for (int i = 0; i < mSubsampleEncryptionDataSize; i++) {
-                                mScratchSubsampleClearBytesCount[i] = data.readUnsignedShort();
-                                mScratchSubsampleEncryptedBytesCount[i] = data.readInt();
-                            }
-                            length -=
-                                    mSubsampleEncryptionDataSize
-                                            * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
-                            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
-                            if (length != 0) {
-                                throw new IllegalStateException();
-                            }
-                            break;
-                        default:
-                            // Never happens.
-                            throw new IllegalStateException();
-                    }
-                }
-            } else if (sampleDataPart == SAMPLE_DATA_PART_SUPPLEMENTAL
-                    && !mIncludeSupplementalData) {
-                mSkippedSupplementalDataBytes += length;
-                data.skipBytes(length);
-            } else {
-                outputSampleData(data, length);
-            }
-        }
-
-        @Override
-        public void sampleMetadata(
-                long timeUs, int flags, int size, int offset, @Nullable CryptoData cryptoData) {
-            size -= mSkippedSupplementalDataBytes;
-            mSkippedSupplementalDataBytes = 0;
-            mOutputConsumer.onSampleCompleted(
-                    mTrackIndex,
-                    timeUs,
-                    getMediaParserFlags(flags),
-                    size - mEncryptionDataSizeToSubtractFromSampleDataSize,
-                    offset,
-                    getPopulatedCryptoInfo(cryptoData));
-            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
-            mEncryptionDataSizeToSubtractFromSampleDataSize = 0;
-        }
-
-        @Nullable
-        private CryptoInfo getPopulatedCryptoInfo(@Nullable CryptoData cryptoData) {
-            if (cryptoData == null) {
-                // The sample is not encrypted.
-                return null;
-            } else if (mInBandCryptoInfo) {
-                if (cryptoData != mLastReceivedCryptoData) {
-                    mLastOutputCryptoInfo =
-                            createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
-                    // We are using in-band crypto info, so the IV will be ignored. But we prevent
-                    // it from being null because toString assumes it non-null.
-                    mLastOutputCryptoInfo.iv = EMPTY_BYTE_ARRAY;
-                }
-            } else /* We must populate the full CryptoInfo. */ {
-                // CryptoInfo.pattern is not accessible to the user, so the user needs to feed
-                // this CryptoInfo directly to MediaCodec. We need to create a new CryptoInfo per
-                // sample because of per-sample initialization vector changes.
-                CryptoInfo newCryptoInfo = createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
-                newCryptoInfo.iv = Arrays.copyOf(mScratchIvSpace, mScratchIvSpace.length);
-                boolean canReuseSubsampleInfo =
-                        mLastOutputCryptoInfo != null
-                                && mLastOutputCryptoInfo.numSubSamples
-                                        == mSubsampleEncryptionDataSize;
-                for (int i = 0; i < mSubsampleEncryptionDataSize && canReuseSubsampleInfo; i++) {
-                    canReuseSubsampleInfo =
-                            mLastOutputCryptoInfo.numBytesOfClearData[i]
-                                            == mScratchSubsampleClearBytesCount[i]
-                                    && mLastOutputCryptoInfo.numBytesOfEncryptedData[i]
-                                            == mScratchSubsampleEncryptedBytesCount[i];
-                }
-                newCryptoInfo.numSubSamples = mSubsampleEncryptionDataSize;
-                if (canReuseSubsampleInfo) {
-                    newCryptoInfo.numBytesOfClearData = mLastOutputCryptoInfo.numBytesOfClearData;
-                    newCryptoInfo.numBytesOfEncryptedData =
-                            mLastOutputCryptoInfo.numBytesOfEncryptedData;
-                } else {
-                    newCryptoInfo.numBytesOfClearData =
-                            Arrays.copyOf(
-                                    mScratchSubsampleClearBytesCount, mSubsampleEncryptionDataSize);
-                    newCryptoInfo.numBytesOfEncryptedData =
-                            Arrays.copyOf(
-                                    mScratchSubsampleEncryptedBytesCount,
-                                    mSubsampleEncryptionDataSize);
-                }
-                mLastOutputCryptoInfo = newCryptoInfo;
-            }
-            mLastReceivedCryptoData = cryptoData;
-            return mLastOutputCryptoInfo;
-        }
-
-        private CryptoInfo createNewCryptoInfoAndPopulateWithCryptoData(CryptoData cryptoData) {
-            CryptoInfo cryptoInfo = new CryptoInfo();
-            cryptoInfo.key = cryptoData.encryptionKey;
-            cryptoInfo.mode = cryptoData.cryptoMode;
-            if (cryptoData.clearBlocks != mLastOutputEncryptionPattern.getSkipBlocks()
-                    || cryptoData.encryptedBlocks
-                            != mLastOutputEncryptionPattern.getEncryptBlocks()) {
-                mLastOutputEncryptionPattern =
-                        new CryptoInfo.Pattern(cryptoData.encryptedBlocks, cryptoData.clearBlocks);
-            }
-            cryptoInfo.setPattern(mLastOutputEncryptionPattern);
-            return cryptoInfo;
-        }
-
-        private void outputSampleData(ParsableByteArray data, int length) {
-            mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
-            try {
-                // Read all bytes from data. ExoPlayer extractors expect all sample data to be
-                // consumed by TrackOutput implementations when passing a ParsableByteArray.
-                while (mScratchParsableByteArrayAdapter.getLength() > 0) {
-                    mOutputConsumer.onSampleDataFound(
-                            mTrackIndex, mScratchParsableByteArrayAdapter);
-                }
-            } catch (IOException e) {
-                // Unexpected.
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
-    private static final class DataReaderAdapter implements InputReader {
-
-        private DataReader mDataReader;
-        private int mCurrentPosition;
-        private long mLength;
-
-        public void setDataReader(DataReader dataReader, long length) {
-            mDataReader = dataReader;
-            mCurrentPosition = 0;
-            mLength = length;
-        }
-
-        // Input implementation.
-
-        @Override
-        public int read(byte[] buffer, int offset, int readLength) throws IOException {
-            int readBytes = 0;
-            readBytes = mDataReader.read(buffer, offset, readLength);
-            mCurrentPosition += readBytes;
-            return readBytes;
-        }
-
-        @Override
-        public long getPosition() {
-            return mCurrentPosition;
-        }
-
-        @Override
-        public long getLength() {
-            return mLength - mCurrentPosition;
-        }
-    }
-
-    private static final class ParsableByteArrayAdapter implements InputReader {
-
-        private ParsableByteArray mByteArray;
-        private long mLength;
-        private int mCurrentPosition;
-
-        public void resetWithByteArray(ParsableByteArray byteArray, long length) {
-            mByteArray = byteArray;
-            mCurrentPosition = 0;
-            mLength = length;
-        }
-
-        // Input implementation.
-
-        @Override
-        public int read(byte[] buffer, int offset, int readLength) {
-            mByteArray.readBytes(buffer, offset, readLength);
-            mCurrentPosition += readLength;
-            return readLength;
-        }
-
-        @Override
-        public long getPosition() {
-            return mCurrentPosition;
-        }
-
-        @Override
-        public long getLength() {
-            return mLength - mCurrentPosition;
-        }
-    }
-
-    private static final class DummyExoPlayerSeekMap
-            implements com.google.android.exoplayer2.extractor.SeekMap {
-
-        @Override
-        public boolean isSeekable() {
-            return true;
-        }
-
-        @Override
-        public long getDurationUs() {
-            return C.TIME_UNSET;
-        }
-
-        @Override
-        public SeekPoints getSeekPoints(long timeUs) {
-            com.google.android.exoplayer2.extractor.SeekPoint seekPoint =
-                    new com.google.android.exoplayer2.extractor.SeekPoint(
-                            timeUs, /* position= */ 0);
-            return new SeekPoints(seekPoint, seekPoint);
-        }
-    }
-
-    /** Creates extractor instances. */
-    private interface ExtractorFactory {
-
-        /** Returns a new extractor instance. */
-        Extractor createInstance();
-    }
-
-    // Private static methods.
-
-    private static Format toExoPlayerCaptionFormat(MediaFormat mediaFormat) {
-        Format.Builder formatBuilder =
-                new Format.Builder().setSampleMimeType(mediaFormat.getString(MediaFormat.KEY_MIME));
-        if (mediaFormat.containsKey(MediaFormat.KEY_CAPTION_SERVICE_NUMBER)) {
-            formatBuilder.setAccessibilityChannel(
-                    mediaFormat.getInteger(MediaFormat.KEY_CAPTION_SERVICE_NUMBER));
-        }
-        return formatBuilder.build();
-    }
-
-    private static MediaFormat toMediaFormat(Format format) {
-        MediaFormat result = new MediaFormat();
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_BIT_RATE, format.bitrate);
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_CHANNEL_COUNT, format.channelCount);
-
-        ColorInfo colorInfo = format.colorInfo;
-        if (colorInfo != null) {
-            setOptionalMediaFormatInt(
-                    result, MediaFormat.KEY_COLOR_TRANSFER, colorInfo.colorTransfer);
-            setOptionalMediaFormatInt(result, MediaFormat.KEY_COLOR_RANGE, colorInfo.colorRange);
-            setOptionalMediaFormatInt(result, MediaFormat.KEY_COLOR_STANDARD, colorInfo.colorSpace);
-
-            if (format.colorInfo.hdrStaticInfo != null) {
-                result.setByteBuffer(
-                        MediaFormat.KEY_HDR_STATIC_INFO,
-                        ByteBuffer.wrap(format.colorInfo.hdrStaticInfo));
-            }
-        }
-
-        setOptionalMediaFormatString(result, MediaFormat.KEY_MIME, format.sampleMimeType);
-        setOptionalMediaFormatString(result, MediaFormat.KEY_CODECS_STRING, format.codecs);
-        if (format.frameRate != Format.NO_VALUE) {
-            result.setFloat(MediaFormat.KEY_FRAME_RATE, format.frameRate);
-        }
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_WIDTH, format.width);
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_HEIGHT, format.height);
-
-        List<byte[]> initData = format.initializationData;
-        for (int i = 0; i < initData.size(); i++) {
-            result.setByteBuffer("csd-" + i, ByteBuffer.wrap(initData.get(i)));
-        }
-        setPcmEncoding(format, result);
-        setOptionalMediaFormatString(result, MediaFormat.KEY_LANGUAGE, format.language);
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_ROTATION, format.rotationDegrees);
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_SAMPLE_RATE, format.sampleRate);
-        setOptionalMediaFormatInt(
-                result, MediaFormat.KEY_CAPTION_SERVICE_NUMBER, format.accessibilityChannel);
-
-        int selectionFlags = format.selectionFlags;
-        result.setInteger(
-                MediaFormat.KEY_IS_AUTOSELECT, selectionFlags & C.SELECTION_FLAG_AUTOSELECT);
-        result.setInteger(MediaFormat.KEY_IS_DEFAULT, selectionFlags & C.SELECTION_FLAG_DEFAULT);
-        result.setInteger(
-                MediaFormat.KEY_IS_FORCED_SUBTITLE, selectionFlags & C.SELECTION_FLAG_FORCED);
-
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_ENCODER_DELAY, format.encoderDelay);
-        setOptionalMediaFormatInt(result, MediaFormat.KEY_ENCODER_PADDING, format.encoderPadding);
-
-        if (format.pixelWidthHeightRatio != Format.NO_VALUE && format.pixelWidthHeightRatio != 0) {
-            int parWidth = 1;
-            int parHeight = 1;
-            if (format.pixelWidthHeightRatio < 1.0f) {
-                parHeight = 1 << 30;
-                parWidth = (int) (format.pixelWidthHeightRatio * parHeight);
-            } else if (format.pixelWidthHeightRatio > 1.0f) {
-                parWidth = 1 << 30;
-                parHeight = (int) (parWidth / format.pixelWidthHeightRatio);
-            }
-            result.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_WIDTH, parWidth);
-            result.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_HEIGHT, parHeight);
-            result.setFloat("pixel-width-height-ratio-float", format.pixelWidthHeightRatio);
-        }
-        if (format.drmInitData != null) {
-            // The crypto mode is propagated along with sample metadata. We also include it in the
-            // format for convenient use from ExoPlayer.
-            result.setString("crypto-mode-fourcc", format.drmInitData.schemeType);
-        }
-        if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
-            result.setLong("subsample-offset-us-long", format.subsampleOffsetUs);
-        }
-        // LACK OF SUPPORT FOR:
-        //    format.id;
-        //    format.metadata;
-        //    format.stereoMode;
-        return result;
-    }
-
-    private static ByteBuffer toByteBuffer(long[] longArray) {
-        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(longArray.length * Long.BYTES);
-        for (long element : longArray) {
-            byteBuffer.putLong(element);
-        }
-        byteBuffer.flip();
-        return byteBuffer;
-    }
-
-    private static ByteBuffer toByteBuffer(int[] intArray) {
-        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(intArray.length * Integer.BYTES);
-        for (int element : intArray) {
-            byteBuffer.putInt(element);
-        }
-        byteBuffer.flip();
-        return byteBuffer;
-    }
-
-    private static String toTypeString(int type) {
-        switch (type) {
-            case C.TRACK_TYPE_VIDEO:
-                return "video";
-            case C.TRACK_TYPE_AUDIO:
-                return "audio";
-            case C.TRACK_TYPE_TEXT:
-                return "text";
-            case C.TRACK_TYPE_METADATA:
-                return "metadata";
-            default:
-                return "unknown";
-        }
-    }
-
-    private static void setPcmEncoding(Format format, MediaFormat result) {
-        int exoPcmEncoding = format.pcmEncoding;
-        setOptionalMediaFormatInt(result, "exo-pcm-encoding", format.pcmEncoding);
-        int mediaFormatPcmEncoding;
-        switch (exoPcmEncoding) {
-            case C.ENCODING_PCM_8BIT:
-                mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_8BIT;
-                break;
-            case C.ENCODING_PCM_16BIT:
-                mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_16BIT;
-                break;
-            case C.ENCODING_PCM_FLOAT:
-                mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_FLOAT;
-                break;
-            default:
-                // No matching value. Do nothing.
-                return;
-        }
-        result.setInteger(MediaFormat.KEY_PCM_ENCODING, mediaFormatPcmEncoding);
-    }
-
-    private static void setOptionalMediaFormatInt(MediaFormat mediaFormat, String key, int value) {
-        if (value != Format.NO_VALUE) {
-            mediaFormat.setInteger(key, value);
-        }
-    }
-
-    private static void setOptionalMediaFormatString(
-            MediaFormat mediaFormat, String key, @Nullable String value) {
-        if (value != null) {
-            mediaFormat.setString(key, value);
-        }
-    }
-
-    private DrmInitData toFrameworkDrmInitData(
-            com.google.android.exoplayer2.drm.DrmInitData exoDrmInitData) {
-        try {
-            return exoDrmInitData != null && mSchemeInitDataConstructor != null
-                    ? new MediaParserDrmInitData(exoDrmInitData)
-                    : null;
-        } catch (Throwable e) {
-            if (!mLoggedSchemeInitDataCreationException) {
-                mLoggedSchemeInitDataCreationException = true;
-                Log.e(TAG, "Unable to create SchemeInitData instance.");
-            }
-            return null;
-        }
-    }
-
-    /** Returns a new {@link SeekPoint} equivalent to the given {@code exoPlayerSeekPoint}. */
-    private static SeekPoint toSeekPoint(
-            com.google.android.exoplayer2.extractor.SeekPoint exoPlayerSeekPoint) {
-        return new SeekPoint(exoPlayerSeekPoint.timeUs, exoPlayerSeekPoint.position);
-    }
-
-    /**
-     * Introduces random error to the given metric value in order to prevent the identification of
-     * the parsed media.
-     */
-    private static long addDither(long value) {
-        // Generate a random in [0, 1].
-        double randomDither = ThreadLocalRandom.current().nextFloat();
-        // Clamp the random number to [0, 2 * MEDIAMETRICS_DITHER].
-        randomDither *= 2 * MEDIAMETRICS_DITHER;
-        // Translate the random number to [1 - MEDIAMETRICS_DITHER, 1 + MEDIAMETRICS_DITHER].
-        randomDither += 1 - MEDIAMETRICS_DITHER;
-        return value != -1 ? (long) (value * randomDither) : -1;
-    }
-
-    private static void assertValidNames(@NonNull String[] names) {
-        for (String name : names) {
-            if (!EXTRACTOR_FACTORIES_BY_NAME.containsKey(name)) {
-                throw new IllegalArgumentException(
-                        "Invalid extractor name: "
-                                + name
-                                + ". Supported parsers are: "
-                                + TextUtils.join(", ", EXTRACTOR_FACTORIES_BY_NAME.keySet())
-                                + ".");
-            }
-        }
-    }
-
-    private int getMediaParserFlags(int flags) {
-        @SampleFlags int result = 0;
-        result |= (flags & C.BUFFER_FLAG_ENCRYPTED) != 0 ? SAMPLE_FLAG_ENCRYPTED : 0;
-        result |= (flags & C.BUFFER_FLAG_KEY_FRAME) != 0 ? SAMPLE_FLAG_KEY_FRAME : 0;
-        result |= (flags & C.BUFFER_FLAG_DECODE_ONLY) != 0 ? SAMPLE_FLAG_DECODE_ONLY : 0;
-        result |=
-                (flags & C.BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA) != 0 && mIncludeSupplementalData
-                        ? SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA
-                        : 0;
-        result |= (flags & C.BUFFER_FLAG_LAST_SAMPLE) != 0 ? SAMPLE_FLAG_LAST_SAMPLE : 0;
-        return result;
-    }
-
-    @Nullable
-    private static Constructor<DrmInitData.SchemeInitData> getSchemeInitDataConstructor() {
-        // TODO: Use constructor statically when available.
-        Constructor<DrmInitData.SchemeInitData> constructor;
-        try {
-            return DrmInitData.SchemeInitData.class.getConstructor(
-                    UUID.class, String.class, byte[].class);
-        } catch (Throwable e) {
-            Log.e(TAG, "Unable to get SchemeInitData constructor.");
-            return null;
-        }
-    }
-
-    // Native methods.
-
-    private native void nativeSubmitMetrics(
-            String logSessionId,
-            String parserName,
-            boolean createdByName,
-            String parserPool,
-            String lastObservedExceptionName,
-            long resourceByteCount,
-            long durationMillis,
-            String trackMimeTypes,
-            String trackCodecs,
-            String alteredParameters,
-            int videoWidth,
-            int videoHeight);
-
-    // Static initialization.
-
-    static {
-        System.loadLibrary(JNI_LIBRARY_NAME);
-
-        // Using a LinkedHashMap to keep the insertion order when iterating over the keys.
-        LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
-        // Parsers are ordered to match ExoPlayer's DefaultExtractorsFactory extractor ordering,
-        // which in turn aims to minimize the chances of incorrect extractor selections.
-        extractorFactoriesByName.put(PARSER_NAME_MATROSKA, MatroskaExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_FMP4, FragmentedMp4Extractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_MP4, Mp4Extractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_MP3, Mp3Extractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_ADTS, AdtsExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_AC3, Ac3Extractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_TS, TsExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_FLV, FlvExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_OGG, OggExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_PS, PsExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_WAV, WavExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_AMR, AmrExtractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_AC4, Ac4Extractor::new);
-        extractorFactoriesByName.put(PARSER_NAME_FLAC, FlacExtractor::new);
-        EXTRACTOR_FACTORIES_BY_NAME = Collections.unmodifiableMap(extractorFactoriesByName);
-
-        HashMap<String, Class> expectedTypeByParameterName = new HashMap<>();
-        expectedTypeByParameterName.put(PARAMETER_ADTS_ENABLE_CBR_SEEKING, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_AMR_ENABLE_CBR_SEEKING, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_FLAC_DISABLE_ID3, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_EDIT_LISTS, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_TFDT_BOX, Boolean.class);
-        expectedTypeByParameterName.put(
-                PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_MP3_DISABLE_ID3, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_CBR_SEEKING, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_INDEX_SEEKING, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_MODE, String.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AAC_STREAM, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AVC_STREAM, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_DETECT_ACCESS_UNITS, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_IN_BAND_CRYPTO_INFO, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_INCLUDE_SUPPLEMENTAL_DATA, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_IGNORE_TIMESTAMP_OFFSET, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_EAGERLY_EXPOSE_TRACKTYPE, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_EXPOSE_DUMMY_SEEKMAP, Boolean.class);
-        expectedTypeByParameterName.put(
-                PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT, Boolean.class);
-        expectedTypeByParameterName.put(
-                PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS, Boolean.class);
-        expectedTypeByParameterName.put(PARAMETER_EXPOSE_EMSG_TRACK, Boolean.class);
-        // We do not check PARAMETER_EXPOSE_CAPTION_FORMATS here, and we do it in setParameters
-        // instead. Checking that the value is a List is insufficient to catch wrong parameter
-        // value types.
-        int sumOfParameterNameLengths =
-                expectedTypeByParameterName.keySet().stream()
-                        .map(String::length)
-                        .reduce(0, Integer::sum);
-        sumOfParameterNameLengths += PARAMETER_EXPOSE_CAPTION_FORMATS.length();
-        // Add space for any required separators.
-        MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH =
-                sumOfParameterNameLengths + expectedTypeByParameterName.size();
-
-        EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
deleted file mode 100644
index e76d61c..0000000
--- a/apex/media/framework/java/android/media/MediaSession2.java
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
-import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
-import static android.media.MediaConstants.KEY_PACKAGE_NAME;
-import static android.media.MediaConstants.KEY_PID;
-import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
-import static android.media.MediaConstants.KEY_SESSION2LINK;
-import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
-import static android.media.Session2Command.Result.RESULT_ERROR_UNKNOWN_ERROR;
-import static android.media.Session2Command.Result.RESULT_INFO_SKIPPED;
-import static android.media.Session2Token.TYPE_SESSION;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.media.session.MediaSessionManager;
-import android.media.session.MediaSessionManager.RemoteUserInfo;
-import android.os.BadParcelableException;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Process;
-import android.os.ResultReceiver;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.modules.utils.build.SdkLevel;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Allows a media app to expose its transport controls and playback information in a process to
- * other processes including the Android framework and other apps.
- */
-public class MediaSession2 implements AutoCloseable {
-    static final String TAG = "MediaSession2";
-    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    // Note: This checks the uniqueness of a session ID only in a single process.
-    // When the framework becomes able to check the uniqueness, this logic should be removed.
-    //@GuardedBy("MediaSession.class")
-    private static final List<String> SESSION_ID_LIST = new ArrayList<>();
-
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final Object mLock = new Object();
-    //@GuardedBy("mLock")
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final Map<Controller2Link, ControllerInfo> mConnectedControllers = new HashMap<>();
-
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final Context mContext;
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final Executor mCallbackExecutor;
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final SessionCallback mCallback;
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    final Session2Link mSessionStub;
-
-    private final String mSessionId;
-    private final PendingIntent mSessionActivity;
-    private final Session2Token mSessionToken;
-    private final MediaSessionManager mMediaSessionManager;
-    private final MediaCommunicationManager mCommunicationManager;
-    private final Handler mResultHandler;
-
-    //@GuardedBy("mLock")
-    private boolean mClosed;
-    //@GuardedBy("mLock")
-    private boolean mPlaybackActive;
-    //@GuardedBy("mLock")
-    private ForegroundServiceEventCallback mForegroundServiceEventCallback;
-
-    MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity,
-            @NonNull Executor callbackExecutor, @NonNull SessionCallback callback,
-            @NonNull Bundle tokenExtras) {
-        synchronized (MediaSession2.class) {
-            if (SESSION_ID_LIST.contains(id)) {
-                throw new IllegalStateException("Session ID must be unique. ID=" + id);
-            }
-            SESSION_ID_LIST.add(id);
-        }
-
-        mContext = context;
-        mSessionId = id;
-        mSessionActivity = sessionActivity;
-        mCallbackExecutor = callbackExecutor;
-        mCallback = callback;
-        mSessionStub = new Session2Link(this);
-        mSessionToken = new Session2Token(Process.myUid(), TYPE_SESSION, context.getPackageName(),
-                mSessionStub, tokenExtras);
-        if (SdkLevel.isAtLeastS()) {
-            mCommunicationManager = mContext.getSystemService(MediaCommunicationManager.class);
-            mMediaSessionManager = null;
-        } else {
-            mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class);
-            mCommunicationManager = null;
-        }
-        // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
-        mResultHandler = new Handler(context.getMainLooper());
-        mClosed = false;
-    }
-
-    @Override
-    public void close() {
-        try {
-            List<ControllerInfo> controllerInfos;
-            ForegroundServiceEventCallback callback;
-            synchronized (mLock) {
-                if (mClosed) {
-                    return;
-                }
-                mClosed = true;
-                controllerInfos = getConnectedControllers();
-                mConnectedControllers.clear();
-                callback = mForegroundServiceEventCallback;
-                mForegroundServiceEventCallback = null;
-            }
-            synchronized (MediaSession2.class) {
-                SESSION_ID_LIST.remove(mSessionId);
-            }
-            if (callback != null) {
-                callback.onSessionClosed(this);
-            }
-            for (ControllerInfo info : controllerInfos) {
-                info.notifyDisconnected();
-            }
-        } catch (Exception e) {
-            // Should not be here.
-        }
-    }
-
-    /**
-     * Returns the session ID
-     */
-    @NonNull
-    public String getId() {
-        return mSessionId;
-    }
-
-    /**
-     * Returns the {@link Session2Token} for creating {@link MediaController2}.
-     */
-    @NonNull
-    public Session2Token getToken() {
-        return mSessionToken;
-    }
-
-    /**
-     * Broadcasts a session command to all the connected controllers
-     * <p>
-     * @param command the session command
-     * @param args optional arguments
-     */
-    public void broadcastSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
-        if (command == null) {
-            throw new IllegalArgumentException("command shouldn't be null");
-        }
-        List<ControllerInfo> controllerInfos = getConnectedControllers();
-        for (ControllerInfo controller : controllerInfos) {
-            controller.sendSessionCommand(command, args, null);
-        }
-    }
-
-    /**
-     * Sends a session command to a specific controller
-     * <p>
-     * @param controller the controller to get the session command
-     * @param command the session command
-     * @param args optional arguments
-     * @return a token which will be sent together in {@link SessionCallback#onCommandResult}
-     *     when its result is received.
-     */
-    @NonNull
-    public Object sendSessionCommand(@NonNull ControllerInfo controller,
-            @NonNull Session2Command command, @Nullable Bundle args) {
-        if (controller == null) {
-            throw new IllegalArgumentException("controller shouldn't be null");
-        }
-        if (command == null) {
-            throw new IllegalArgumentException("command shouldn't be null");
-        }
-        ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                controller.receiveCommandResult(this);
-                mCallbackExecutor.execute(() -> {
-                    mCallback.onCommandResult(MediaSession2.this, controller, this,
-                            command, new Session2Command.Result(resultCode, resultData));
-                });
-            }
-        };
-        controller.sendSessionCommand(command, args, resultReceiver);
-        return resultReceiver;
-    }
-
-    /**
-     * Cancels the session command previously sent.
-     *
-     * @param controller the controller to get the session command
-     * @param token the token which is returned from {@link #sendSessionCommand}.
-     */
-    public void cancelSessionCommand(@NonNull ControllerInfo controller, @NonNull Object token) {
-        if (controller == null) {
-            throw new IllegalArgumentException("controller shouldn't be null");
-        }
-        if (token == null) {
-            throw new IllegalArgumentException("token shouldn't be null");
-        }
-        controller.cancelSessionCommand(token);
-    }
-
-    /**
-     * Sets whether the playback is active (i.e. playing something)
-     *
-     * @param playbackActive {@code true} if the playback active, {@code false} otherwise.
-     **/
-    public void setPlaybackActive(boolean playbackActive) {
-        final ForegroundServiceEventCallback serviceCallback;
-        synchronized (mLock) {
-            if (mPlaybackActive == playbackActive) {
-                return;
-            }
-            mPlaybackActive = playbackActive;
-            serviceCallback = mForegroundServiceEventCallback;
-        }
-        if (serviceCallback != null) {
-            serviceCallback.onPlaybackActiveChanged(this, playbackActive);
-        }
-        List<ControllerInfo> controllerInfos = getConnectedControllers();
-        for (ControllerInfo controller : controllerInfos) {
-            controller.notifyPlaybackActiveChanged(playbackActive);
-        }
-    }
-
-    /**
-     * Returns whehther the playback is active (i.e. playing something)
-     *
-     * @return {@code true} if the playback active, {@code false} otherwise.
-     */
-    public boolean isPlaybackActive() {
-        synchronized (mLock) {
-            return mPlaybackActive;
-        }
-    }
-
-    /**
-     * Gets the list of the connected controllers
-     *
-     * @return list of the connected controllers.
-     */
-    @NonNull
-    public List<ControllerInfo> getConnectedControllers() {
-        List<ControllerInfo> controllers = new ArrayList<>();
-        synchronized (mLock) {
-            controllers.addAll(mConnectedControllers.values());
-        }
-        return controllers;
-    }
-
-    /**
-     * Returns whether the given bundle includes non-framework Parcelables.
-     */
-    static boolean hasCustomParcelable(@Nullable Bundle bundle) {
-        if (bundle == null) {
-            return false;
-        }
-
-        // Try writing the bundle to parcel, and read it with framework classloader.
-        Parcel parcel = null;
-        try {
-            parcel = Parcel.obtain();
-            parcel.writeBundle(bundle);
-            parcel.setDataPosition(0);
-            Bundle out = parcel.readBundle(null);
-
-            // Calling Bundle#size() will trigger Bundle#unparcel().
-            out.size();
-        } catch (BadParcelableException e) {
-            Log.d(TAG, "Custom parcelable in bundle.", e);
-            return true;
-        } finally {
-            if (parcel != null) {
-                parcel.recycle();
-            }
-        }
-        return false;
-    }
-
-    boolean isClosed() {
-        synchronized (mLock) {
-            return mClosed;
-        }
-    }
-
-    SessionCallback getCallback() {
-        return mCallback;
-    }
-
-    boolean isTrustedForMediaControl(RemoteUserInfo remoteUserInfo) {
-        if (SdkLevel.isAtLeastS()) {
-            return mCommunicationManager.isTrustedForMediaControl(remoteUserInfo);
-        } else {
-            return mMediaSessionManager.isTrustedForMediaControl(remoteUserInfo);
-        }
-    }
-
-    void setForegroundServiceEventCallback(ForegroundServiceEventCallback callback) {
-        synchronized (mLock) {
-            if (mForegroundServiceEventCallback == callback) {
-                return;
-            }
-            if (mForegroundServiceEventCallback != null && callback != null) {
-                throw new IllegalStateException("A session cannot be added to multiple services");
-            }
-            mForegroundServiceEventCallback = callback;
-        }
-    }
-
-    // Called by Session2Link.onConnect and MediaSession2Service.MediaSession2ServiceStub.connect
-    void onConnect(final Controller2Link controller, int callingPid, int callingUid, int seq,
-            Bundle connectionRequest) {
-        if (callingPid == 0) {
-            // The pid here is from Binder.getCallingPid(), which can be 0 for an oneway call from
-            // the remote process. If it's the case, use PID from the connectionRequest.
-            callingPid = connectionRequest.getInt(KEY_PID);
-        }
-        String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME);
-
-        RemoteUserInfo remoteUserInfo = new RemoteUserInfo(callingPkg, callingPid, callingUid);
-
-        Bundle connectionHints = connectionRequest.getBundle(KEY_CONNECTION_HINTS);
-        if (connectionHints == null) {
-            Log.w(TAG, "connectionHints shouldn't be null.");
-            connectionHints = Bundle.EMPTY;
-        } else if (hasCustomParcelable(connectionHints)) {
-            Log.w(TAG, "connectionHints contain custom parcelable. Ignoring.");
-            connectionHints = Bundle.EMPTY;
-        }
-
-        final ControllerInfo controllerInfo = new ControllerInfo(
-                remoteUserInfo,
-                isTrustedForMediaControl(remoteUserInfo),
-                controller,
-                connectionHints);
-        mCallbackExecutor.execute(() -> {
-            boolean connected = false;
-            try {
-                if (isClosed()) {
-                    return;
-                }
-                controllerInfo.mAllowedCommands =
-                        mCallback.onConnect(MediaSession2.this, controllerInfo);
-                // Don't reject connection for the request from trusted app.
-                // Otherwise server will fail to retrieve session's information to dispatch
-                // media keys to.
-                if (controllerInfo.mAllowedCommands == null && !controllerInfo.isTrusted()) {
-                    return;
-                }
-                if (controllerInfo.mAllowedCommands == null) {
-                    // For trusted apps, send non-null allowed commands to keep
-                    // connection.
-                    controllerInfo.mAllowedCommands =
-                            new Session2CommandGroup.Builder().build();
-                }
-                if (DEBUG) {
-                    Log.d(TAG, "Accepting connection: " + controllerInfo);
-                }
-                // If connection is accepted, notify the current state to the controller.
-                // It's needed because we cannot call synchronous calls between
-                // session/controller.
-                Bundle connectionResult = new Bundle();
-                connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub);
-                connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
-                        controllerInfo.mAllowedCommands);
-                connectionResult.putBoolean(KEY_PLAYBACK_ACTIVE, isPlaybackActive());
-                connectionResult.putBundle(KEY_TOKEN_EXTRAS, mSessionToken.getExtras());
-
-                // Double check if session is still there, because close() can be called in
-                // another thread.
-                if (isClosed()) {
-                    return;
-                }
-                controllerInfo.notifyConnected(connectionResult);
-                synchronized (mLock) {
-                    if (mConnectedControllers.containsKey(controller)) {
-                        Log.w(TAG, "Controller " + controllerInfo + " has sent connection"
-                                + " request multiple times");
-                    }
-                    mConnectedControllers.put(controller, controllerInfo);
-                }
-                mCallback.onPostConnect(MediaSession2.this, controllerInfo);
-                connected = true;
-            } finally {
-                if (!connected || isClosed()) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Rejecting connection or notifying that session is closed"
-                                + ", controllerInfo=" + controllerInfo);
-                    }
-                    synchronized (mLock) {
-                        mConnectedControllers.remove(controller);
-                    }
-                    controllerInfo.notifyDisconnected();
-                }
-            }
-        });
-    }
-
-    // Called by Session2Link.onDisconnect
-    void onDisconnect(@NonNull final Controller2Link controller, int seq) {
-        final ControllerInfo controllerInfo;
-        synchronized (mLock) {
-            controllerInfo = mConnectedControllers.remove(controller);
-        }
-        if (controllerInfo == null) {
-            return;
-        }
-        mCallbackExecutor.execute(() -> {
-            mCallback.onDisconnected(MediaSession2.this, controllerInfo);
-        });
-    }
-
-    // Called by Session2Link.onSessionCommand
-    void onSessionCommand(@NonNull final Controller2Link controller, final int seq,
-            final Session2Command command, final Bundle args,
-            @Nullable ResultReceiver resultReceiver) {
-        if (controller == null) {
-            return;
-        }
-        final ControllerInfo controllerInfo;
-        synchronized (mLock) {
-            controllerInfo = mConnectedControllers.get(controller);
-        }
-        if (controllerInfo == null) {
-            return;
-        }
-
-        // TODO: check allowed commands.
-        synchronized (mLock) {
-            controllerInfo.addRequestedCommandSeqNumber(seq);
-        }
-        mCallbackExecutor.execute(() -> {
-            if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) {
-                if (resultReceiver != null) {
-                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
-                }
-                return;
-            }
-            Session2Command.Result result = mCallback.onSessionCommand(
-                    MediaSession2.this, controllerInfo, command, args);
-            if (resultReceiver != null) {
-                if (result == null) {
-                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
-                } else {
-                    resultReceiver.send(result.getResultCode(), result.getResultData());
-                }
-            }
-        });
-    }
-
-    // Called by Session2Link.onCancelCommand
-    void onCancelCommand(@NonNull final Controller2Link controller, final int seq) {
-        final ControllerInfo controllerInfo;
-        synchronized (mLock) {
-            controllerInfo = mConnectedControllers.get(controller);
-        }
-        if (controllerInfo == null) {
-            return;
-        }
-        controllerInfo.removeRequestedCommandSeqNumber(seq);
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Builder for {@link MediaSession2}.
-     * <p>
-     * Any incoming event from the {@link MediaController2} will be handled on the callback
-     * executor. If it's not set, {@link Context#getMainExecutor()} will be used by default.
-     */
-    public static final class Builder {
-        private Context mContext;
-        private String mId;
-        private PendingIntent mSessionActivity;
-        private Executor mCallbackExecutor;
-        private SessionCallback mCallback;
-        private Bundle mExtras;
-
-        /**
-         * Creates a builder for {@link MediaSession2}.
-         *
-         * @param context Context
-         * @throws IllegalArgumentException if context is {@code null}.
-         */
-        public Builder(@NonNull Context context) {
-            if (context == null) {
-                throw new IllegalArgumentException("context shouldn't be null");
-            }
-            mContext = context;
-        }
-
-        /**
-         * Set an intent for launching UI for this Session. This can be used as a
-         * quick link to an ongoing media screen. The intent should be for an
-         * activity that may be started using {@link Context#startActivity(Intent)}.
-         *
-         * @param pi The intent to launch to show UI for this session.
-         * @return The Builder to allow chaining
-         */
-        @NonNull
-        public Builder setSessionActivity(@Nullable PendingIntent pi) {
-            mSessionActivity = pi;
-            return this;
-        }
-
-        /**
-         * Set ID of the session. If it's not set, an empty string will be used to create a session.
-         * <p>
-         * Use this if and only if your app supports multiple playback at the same time and also
-         * wants to provide external apps to have finer controls of them.
-         *
-         * @param id id of the session. Must be unique per package.
-         * @throws IllegalArgumentException if id is {@code null}.
-         * @return The Builder to allow chaining
-         */
-        @NonNull
-        public Builder setId(@NonNull String id) {
-            if (id == null) {
-                throw new IllegalArgumentException("id shouldn't be null");
-            }
-            mId = id;
-            return this;
-        }
-
-        /**
-         * Set callback for the session and its executor.
-         *
-         * @param executor callback executor
-         * @param callback session callback.
-         * @return The Builder to allow chaining
-         */
-        @NonNull
-        public Builder setSessionCallback(@NonNull Executor executor,
-                @NonNull SessionCallback callback) {
-            mCallbackExecutor = executor;
-            mCallback = callback;
-            return this;
-        }
-
-        /**
-         * Set extras for the session token. If null or not set, {@link Session2Token#getExtras()}
-         * will return an empty {@link Bundle}. An {@link IllegalArgumentException} will be thrown
-         * if the bundle contains any non-framework Parcelable objects.
-         *
-         * @return The Builder to allow chaining
-         * @see Session2Token#getExtras()
-         */
-        @NonNull
-        public Builder setExtras(@NonNull Bundle extras) {
-            if (extras == null) {
-                throw new NullPointerException("extras shouldn't be null");
-            }
-            if (hasCustomParcelable(extras)) {
-                throw new IllegalArgumentException(
-                        "extras shouldn't contain any custom parcelables");
-            }
-            mExtras = new Bundle(extras);
-            return this;
-        }
-
-        /**
-         * Build {@link MediaSession2}.
-         *
-         * @return a new session
-         * @throws IllegalStateException if the session with the same id is already exists for the
-         *      package.
-         */
-        @NonNull
-        public MediaSession2 build() {
-            if (mCallbackExecutor == null) {
-                mCallbackExecutor = mContext.getMainExecutor();
-            }
-            if (mCallback == null) {
-                mCallback = new SessionCallback() {};
-            }
-            if (mId == null) {
-                mId = "";
-            }
-            if (mExtras == null) {
-                mExtras = Bundle.EMPTY;
-            }
-            MediaSession2 session2 = new MediaSession2(mContext, mId, mSessionActivity,
-                    mCallbackExecutor, mCallback, mExtras);
-
-            // Notify framework about the newly create session after the constructor is finished.
-            // Otherwise, framework may access the session before the initialization is finished.
-            try {
-                if (SdkLevel.isAtLeastS()) {
-                    MediaCommunicationManager manager =
-                            mContext.getSystemService(MediaCommunicationManager.class);
-                    manager.notifySession2Created(session2.getToken());
-                } else {
-                    MediaSessionManager manager =
-                            mContext.getSystemService(MediaSessionManager.class);
-                    manager.notifySession2Created(session2.getToken());
-                }
-            } catch (Exception e) {
-                session2.close();
-                throw e;
-            }
-
-            return session2;
-        }
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Information of a controller.
-     */
-    public static final class ControllerInfo {
-        private final RemoteUserInfo mRemoteUserInfo;
-        private final boolean mIsTrusted;
-        private final Controller2Link mControllerBinder;
-        private final Bundle mConnectionHints;
-        private final Object mLock = new Object();
-        //@GuardedBy("mLock")
-        private int mNextSeqNumber;
-        //@GuardedBy("mLock")
-        private ArrayMap<ResultReceiver, Integer> mPendingCommands;
-        //@GuardedBy("mLock")
-        private ArraySet<Integer> mRequestedCommandSeqNumbers;
-
-        @SuppressWarnings("WeakerAccess") /* synthetic access */
-        Session2CommandGroup mAllowedCommands;
-
-        /**
-         * @param remoteUserInfo remote user info
-         * @param trusted {@code true} if trusted, {@code false} otherwise
-         * @param controllerBinder Controller2Link for the connected controller.
-         * @param connectionHints a session-specific argument sent from the controller for the
-         *                        connection. The contents of this bundle may affect the
-         *                        connection result.
-         */
-        ControllerInfo(@NonNull RemoteUserInfo remoteUserInfo, boolean trusted,
-                @Nullable Controller2Link controllerBinder, @NonNull Bundle connectionHints) {
-            mRemoteUserInfo = remoteUserInfo;
-            mIsTrusted = trusted;
-            mControllerBinder = controllerBinder;
-            mConnectionHints = connectionHints;
-            mPendingCommands = new ArrayMap<>();
-            mRequestedCommandSeqNumbers = new ArraySet<>();
-        }
-
-        /**
-         * @return remote user info of the controller.
-         */
-        @NonNull
-        public RemoteUserInfo getRemoteUserInfo() {
-            return mRemoteUserInfo;
-        }
-
-        /**
-         * @return package name of the controller.
-         */
-        @NonNull
-        public String getPackageName() {
-            return mRemoteUserInfo.getPackageName();
-        }
-
-        /**
-         * @return uid of the controller. Can be a negative value if the uid cannot be obtained.
-         */
-        public int getUid() {
-            return mRemoteUserInfo.getUid();
-        }
-
-        /**
-         * @return connection hints sent from controller.
-         */
-        @NonNull
-        public Bundle getConnectionHints() {
-            return new Bundle(mConnectionHints);
-        }
-
-        /**
-         * Return if the controller has granted {@code android.permission.MEDIA_CONTENT_CONTROL} or
-         * has a enabled notification listener so can be trusted to accept connection and incoming
-         * command request.
-         *
-         * @return {@code true} if the controller is trusted.
-         * @hide
-         */
-        public boolean isTrusted() {
-            return mIsTrusted;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mControllerBinder, mRemoteUserInfo);
-        }
-
-        @Override
-        public boolean equals(@Nullable Object obj) {
-            if (!(obj instanceof ControllerInfo)) return false;
-            if (this == obj) return true;
-
-            ControllerInfo other = (ControllerInfo) obj;
-            if (mControllerBinder != null || other.mControllerBinder != null) {
-                return Objects.equals(mControllerBinder, other.mControllerBinder);
-            }
-            return mRemoteUserInfo.equals(other.mRemoteUserInfo);
-        }
-
-        @Override
-        @NonNull
-        public String toString() {
-            return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid="
-                    + mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})";
-        }
-
-        void notifyConnected(Bundle connectionResult) {
-            if (mControllerBinder == null) return;
-
-            try {
-                mControllerBinder.notifyConnected(getNextSeqNumber(), connectionResult);
-            } catch (RuntimeException e) {
-                // Controller may be died prematurely.
-            }
-        }
-
-        void notifyDisconnected() {
-            if (mControllerBinder == null) return;
-
-            try {
-                mControllerBinder.notifyDisconnected(getNextSeqNumber());
-            } catch (RuntimeException e) {
-                // Controller may be died prematurely.
-            }
-        }
-
-        void notifyPlaybackActiveChanged(boolean playbackActive) {
-            if (mControllerBinder == null) return;
-
-            try {
-                mControllerBinder.notifyPlaybackActiveChanged(getNextSeqNumber(), playbackActive);
-            } catch (RuntimeException e) {
-                // Controller may be died prematurely.
-            }
-        }
-
-        void sendSessionCommand(Session2Command command, Bundle args,
-                ResultReceiver resultReceiver) {
-            if (mControllerBinder == null) return;
-
-            try {
-                int seq = getNextSeqNumber();
-                synchronized (mLock) {
-                    mPendingCommands.put(resultReceiver, seq);
-                }
-                mControllerBinder.sendSessionCommand(seq, command, args, resultReceiver);
-            } catch (RuntimeException e) {
-                // Controller may be died prematurely.
-                synchronized (mLock) {
-                    mPendingCommands.remove(resultReceiver);
-                }
-                resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
-            }
-        }
-
-        void cancelSessionCommand(@NonNull Object token) {
-            if (mControllerBinder == null) return;
-            Integer seq;
-            synchronized (mLock) {
-                seq = mPendingCommands.remove(token);
-            }
-            if (seq != null) {
-                mControllerBinder.cancelSessionCommand(seq);
-            }
-        }
-
-        void receiveCommandResult(ResultReceiver resultReceiver) {
-            synchronized (mLock) {
-                mPendingCommands.remove(resultReceiver);
-            }
-        }
-
-        void addRequestedCommandSeqNumber(int seq) {
-            synchronized (mLock) {
-                mRequestedCommandSeqNumbers.add(seq);
-            }
-        }
-
-        boolean removeRequestedCommandSeqNumber(int seq) {
-            synchronized (mLock) {
-                return mRequestedCommandSeqNumbers.remove(seq);
-            }
-        }
-
-        private int getNextSeqNumber() {
-            synchronized (mLock) {
-                return mNextSeqNumber++;
-            }
-        }
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Callback to be called for all incoming commands from {@link MediaController2}s.
-     */
-    public abstract static class SessionCallback {
-        /**
-         * Called when a controller is created for this session. Return allowed commands for
-         * controller. By default it returns {@code null}.
-         * <p>
-         * You can reject the connection by returning {@code null}. In that case, controller
-         * receives {@link MediaController2.ControllerCallback#onDisconnected(MediaController2)}
-         * and cannot be used.
-         * <p>
-         * The controller hasn't connected yet in this method, so calls to the controller
-         * (e.g. {@link #sendSessionCommand}) would be ignored. Override {@link #onPostConnect} for
-         * the custom initialization for the controller instead.
-         *
-         * @param session the session for this event
-         * @param controller controller information.
-         * @return allowed commands. Can be {@code null} to reject connection.
-         */
-        @Nullable
-        public Session2CommandGroup onConnect(@NonNull MediaSession2 session,
-                @NonNull ControllerInfo controller) {
-            return null;
-        }
-
-        /**
-         * Called immediately after a controller is connected. This is a convenient method to add
-         * custom initialization between the session and a controller.
-         * <p>
-         * Note that calls to the controller (e.g. {@link #sendSessionCommand}) work here but don't
-         * work in {@link #onConnect} because the controller hasn't connected yet in
-         * {@link #onConnect}.
-         *
-         * @param session the session for this event
-         * @param controller controller information.
-         */
-        public void onPostConnect(@NonNull MediaSession2 session,
-                @NonNull ControllerInfo controller) {
-        }
-
-        /**
-         * Called when a controller is disconnected
-         *
-         * @param session the session for this event
-         * @param controller controller information
-         */
-        public void onDisconnected(@NonNull MediaSession2 session,
-                @NonNull ControllerInfo controller) {}
-
-        /**
-         * Called when a controller sent a session command.
-         *
-         * @param session the session for this event
-         * @param controller controller information
-         * @param command the session command
-         * @param args optional arguments
-         * @return the result for the session command. If {@code null}, RESULT_INFO_SKIPPED
-         *         will be sent to the session.
-         */
-        @Nullable
-        public Session2Command.Result onSessionCommand(@NonNull MediaSession2 session,
-                @NonNull ControllerInfo controller, @NonNull Session2Command command,
-                @Nullable Bundle args) {
-            return null;
-        }
-
-        /**
-         * Called when the command sent to the controller is finished.
-         *
-         * @param session the session for this event
-         * @param controller controller information
-         * @param token the token got from {@link MediaSession2#sendSessionCommand}
-         * @param command the session command
-         * @param result the result of the session command
-         */
-        public void onCommandResult(@NonNull MediaSession2 session,
-                @NonNull ControllerInfo controller, @NonNull Object token,
-                @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
-    }
-
-    abstract static class ForegroundServiceEventCallback {
-        public void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {}
-        public void onSessionClosed(MediaSession2 session) {}
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaSession2Service.java b/apex/media/framework/java/android/media/MediaSession2Service.java
deleted file mode 100644
index f6fd509..0000000
--- a/apex/media/framework/java/android/media/MediaSession2Service.java
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
-import static android.media.MediaConstants.KEY_PACKAGE_NAME;
-import static android.media.MediaConstants.KEY_PID;
-
-import android.annotation.CallSuper;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.media.MediaSession2.ControllerInfo;
-import android.media.session.MediaSessionManager;
-import android.media.session.MediaSessionManager.RemoteUserInfo;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Service containing {@link MediaSession2}.
- */
-public abstract class MediaSession2Service extends Service {
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     */
-    public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";
-
-    private static final String TAG = "MediaSession2Service";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private final MediaSession2.ForegroundServiceEventCallback mForegroundServiceEventCallback =
-            new MediaSession2.ForegroundServiceEventCallback() {
-                @Override
-                public void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {
-                    MediaSession2Service.this.onPlaybackActiveChanged(session, playbackActive);
-                }
-
-                @Override
-                public void onSessionClosed(MediaSession2 session) {
-                    removeSession(session);
-                }
-            };
-
-    private final Object mLock = new Object();
-    //@GuardedBy("mLock")
-    private NotificationManager mNotificationManager;
-    //@GuardedBy("mLock")
-    private MediaSessionManager mMediaSessionManager;
-    //@GuardedBy("mLock")
-    private Intent mStartSelfIntent;
-    //@GuardedBy("mLock")
-    private Map<String, MediaSession2> mSessions = new ArrayMap<>();
-    //@GuardedBy("mLock")
-    private Map<MediaSession2, MediaNotification> mNotifications = new ArrayMap<>();
-    //@GuardedBy("mLock")
-    private MediaSession2ServiceStub mStub;
-
-    /**
-     * Called by the system when the service is first created. Do not call this method directly.
-     * <p>
-     * Override this method if you need your own initialization. Derived classes MUST call through
-     * to the super class's implementation of this method.
-     */
-    @CallSuper
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        synchronized (mLock) {
-            mStub = new MediaSession2ServiceStub(this);
-            mStartSelfIntent = new Intent(this, this.getClass());
-            mNotificationManager =
-                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-            mMediaSessionManager =
-                    (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
-        }
-    }
-
-    @CallSuper
-    @Override
-    @Nullable
-    public IBinder onBind(@NonNull Intent intent) {
-        if (SERVICE_INTERFACE.equals(intent.getAction())) {
-            synchronized (mLock) {
-                return mStub;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Called by the system to notify that it is no longer used and is being removed. Do not call
-     * this method directly.
-     * <p>
-     * Override this method if you need your own clean up. Derived classes MUST call through
-     * to the super class's implementation of this method.
-     */
-    @CallSuper
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        synchronized (mLock) {
-            List<MediaSession2> sessions = getSessions();
-            for (MediaSession2 session : sessions) {
-                removeSession(session);
-            }
-            mSessions.clear();
-            mNotifications.clear();
-        }
-        mStub.close();
-    }
-
-    /**
-     * Called when a {@link MediaController2} is created with the this service's
-     * {@link Session2Token}. Return the session for telling the controller which session to
-     * connect. Return {@code null} to reject the connection from this controller.
-     * <p>
-     * Session returned here will be added to this service automatically. You don't need to call
-     * {@link #addSession(MediaSession2)} for that.
-     * <p>
-     * This method is always called on the main thread.
-     *
-     * @param controllerInfo information of the controller which is trying to connect.
-     * @return a {@link MediaSession2} instance for the controller to connect to, or {@code null}
-     *         to reject connection
-     * @see MediaSession2.Builder
-     * @see #getSessions()
-     */
-    @Nullable
-    public abstract MediaSession2 onGetSession(@NonNull ControllerInfo controllerInfo);
-
-    /**
-     * Called when notification UI needs update. Override this method to show or cancel your own
-     * notification UI.
-     * <p>
-     * This would be called on {@link MediaSession2}'s callback executor when playback state is
-     * changed.
-     * <p>
-     * With the notification returned here, the service becomes foreground service when the playback
-     * is started. Apps must request the permission
-     * {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to use this API. It becomes
-     * background service after the playback is stopped.
-     *
-     * @param session a session that needs notification update.
-     * @return a {@link MediaNotification}. Can be {@code null}.
-     */
-    @Nullable
-    public abstract MediaNotification onUpdateNotification(@NonNull MediaSession2 session);
-
-    /**
-     * Adds a session to this service.
-     * <p>
-     * Added session will be removed automatically when it's closed, or removed when
-     * {@link #removeSession} is called.
-     *
-     * @param session a session to be added.
-     * @see #removeSession(MediaSession2)
-     */
-    public final void addSession(@NonNull MediaSession2 session) {
-        if (session == null) {
-            throw new IllegalArgumentException("session shouldn't be null");
-        }
-        if (session.isClosed()) {
-            throw new IllegalArgumentException("session is already closed");
-        }
-        synchronized (mLock) {
-            MediaSession2 previousSession = mSessions.get(session.getId());
-            if (previousSession != null) {
-                if (previousSession != session) {
-                    Log.w(TAG, "Session ID should be unique, ID=" + session.getId()
-                            + ", previous=" + previousSession + ", session=" + session);
-                }
-                return;
-            }
-            mSessions.put(session.getId(), session);
-            session.setForegroundServiceEventCallback(mForegroundServiceEventCallback);
-        }
-    }
-
-    /**
-     * Removes a session from this service.
-     *
-     * @param session a session to be removed.
-     * @see #addSession(MediaSession2)
-     */
-    public final void removeSession(@NonNull MediaSession2 session) {
-        if (session == null) {
-            throw new IllegalArgumentException("session shouldn't be null");
-        }
-        MediaNotification notification;
-        synchronized (mLock) {
-            if (mSessions.get(session.getId()) != session) {
-                // Session isn't added or removed already.
-                return;
-            }
-            mSessions.remove(session.getId());
-            notification = mNotifications.remove(session);
-        }
-        session.setForegroundServiceEventCallback(null);
-        if (notification != null) {
-            mNotificationManager.cancel(notification.getNotificationId());
-        }
-        if (getSessions().isEmpty()) {
-            stopForeground(false);
-        }
-    }
-
-    /**
-     * Gets the list of {@link MediaSession2}s that you've added to this service.
-     *
-     * @return sessions
-     */
-    public final @NonNull List<MediaSession2> getSessions() {
-        List<MediaSession2> list = new ArrayList<>();
-        synchronized (mLock) {
-            list.addAll(mSessions.values());
-        }
-        return list;
-    }
-
-    /**
-     * Returns the {@link MediaSessionManager}.
-     */
-    @NonNull
-    MediaSessionManager getMediaSessionManager() {
-        synchronized (mLock) {
-            return mMediaSessionManager;
-        }
-    }
-
-    /**
-     * Called by registered {@link MediaSession2.ForegroundServiceEventCallback}
-     *
-     * @param session session with change
-     * @param playbackActive {@code true} if playback is active.
-     */
-    void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {
-        MediaNotification mediaNotification = onUpdateNotification(session);
-        if (mediaNotification == null) {
-            // The service implementation doesn't want to use the automatic start/stopForeground
-            // feature.
-            return;
-        }
-        synchronized (mLock) {
-            mNotifications.put(session, mediaNotification);
-        }
-        int id = mediaNotification.getNotificationId();
-        Notification notification = mediaNotification.getNotification();
-        if (!playbackActive) {
-            mNotificationManager.notify(id, notification);
-            return;
-        }
-        // playbackActive == true
-        startForegroundService(mStartSelfIntent);
-        startForeground(id, notification);
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Returned by {@link #onUpdateNotification(MediaSession2)} for making session service
-     * foreground service to keep playback running in the background. It's highly recommended to
-     * show media style notification here.
-     */
-    public static class MediaNotification {
-        private final int mNotificationId;
-        private final Notification mNotification;
-
-        /**
-         * Default constructor
-         *
-         * @param notificationId notification id to be used for
-         *        {@link NotificationManager#notify(int, Notification)}.
-         * @param notification a notification to make session service run in the foreground. Media
-         *        style notification is recommended here.
-         */
-        public MediaNotification(int notificationId, @NonNull Notification notification) {
-            if (notification == null) {
-                throw new IllegalArgumentException("notification shouldn't be null");
-            }
-            mNotificationId = notificationId;
-            mNotification = notification;
-        }
-
-        /**
-         * Gets the id of the notification.
-         *
-         * @return the notification id
-         */
-        public int getNotificationId() {
-            return mNotificationId;
-        }
-
-        /**
-         * Gets the notification.
-         *
-         * @return the notification
-         */
-        @NonNull
-        public Notification getNotification() {
-            return mNotification;
-        }
-    }
-
-    private static final class MediaSession2ServiceStub extends IMediaSession2Service.Stub
-            implements AutoCloseable {
-        final WeakReference<MediaSession2Service> mService;
-        final Handler mHandler;
-
-        MediaSession2ServiceStub(MediaSession2Service service) {
-            mService = new WeakReference<>(service);
-            mHandler = new Handler(service.getMainLooper());
-        }
-
-        @Override
-        public void connect(Controller2Link caller, int seq, Bundle connectionRequest) {
-            if (mService.get() == null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Service is already destroyed");
-                }
-                return;
-            }
-            if (caller == null || connectionRequest == null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Ignoring calls with illegal arguments, caller=" + caller
-                            + ", connectionRequest=" + connectionRequest);
-                }
-                return;
-            }
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mHandler.post(() -> {
-                    boolean shouldNotifyDisconnected = true;
-                    try {
-                        final MediaSession2Service service = mService.get();
-                        if (service == null) {
-                            if (DEBUG) {
-                                Log.d(TAG, "Service isn't available");
-                            }
-                            return;
-                        }
-
-                        String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME);
-                        // The Binder.getCallingPid() can be 0 for an oneway call from the
-                        // remote process. If it's the case, use PID from the connectionRequest.
-                        RemoteUserInfo remoteUserInfo = new RemoteUserInfo(
-                                callingPkg,
-                                pid == 0 ? connectionRequest.getInt(KEY_PID) : pid,
-                                uid);
-
-                        Bundle connectionHints = connectionRequest.getBundle(KEY_CONNECTION_HINTS);
-                        if (connectionHints == null) {
-                            Log.w(TAG, "connectionHints shouldn't be null.");
-                            connectionHints = Bundle.EMPTY;
-                        } else if (MediaSession2.hasCustomParcelable(connectionHints)) {
-                            Log.w(TAG, "connectionHints contain custom parcelable. Ignoring.");
-                            connectionHints = Bundle.EMPTY;
-                        }
-
-                        final ControllerInfo controllerInfo = new ControllerInfo(
-                                remoteUserInfo,
-                                service.getMediaSessionManager()
-                                        .isTrustedForMediaControl(remoteUserInfo),
-                                caller,
-                                connectionHints);
-
-                        if (DEBUG) {
-                            Log.d(TAG, "Handling incoming connection request from the"
-                                    + " controller=" + controllerInfo);
-                        }
-
-                        final MediaSession2 session;
-                        session = service.onGetSession(controllerInfo);
-
-                        if (session == null) {
-                            if (DEBUG) {
-                                Log.d(TAG, "Rejecting incoming connection request from the"
-                                        + " controller=" + controllerInfo);
-                            }
-                            // Note: Trusted controllers also can be rejected according to the
-                            // service implementation.
-                            return;
-                        }
-                        service.addSession(session);
-                        shouldNotifyDisconnected = false;
-                        session.onConnect(caller, pid, uid, seq, connectionRequest);
-                    } catch (Exception e) {
-                        // Don't propagate exception in service to the controller.
-                        Log.w(TAG, "Failed to add a session to session service", e);
-                    } finally {
-                        // Trick to call onDisconnected() in one place.
-                        if (shouldNotifyDisconnected) {
-                            if (DEBUG) {
-                                Log.d(TAG, "Notifying the controller of its disconnection");
-                            }
-                            try {
-                                caller.notifyDisconnected(0);
-                            } catch (RuntimeException e) {
-                                // Controller may be died prematurely.
-                                // Not an issue because we'll ignore it anyway.
-                            }
-                        }
-                    }
-                });
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void close() {
-            mHandler.removeCallbacksAndMessages(null);
-            mService.clear();
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/MediaTranscodingManager.java b/apex/media/framework/java/android/media/MediaTranscodingManager.java
deleted file mode 100644
index 1a84929..0000000
--- a/apex/media/framework/java/android/media/MediaTranscodingManager.java
+++ /dev/null
@@ -1,1752 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.net.Uri;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.Os;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.modules.annotation.MinSdk;
-import com.android.modules.utils.build.SdkLevel;
-
-import java.io.FileNotFoundException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- Android 12 introduces Compatible media transcoding feature.  See
- <a href="https://developer.android.com/about/versions/12/features#compatible_media_transcoding">
- Compatible media transcoding</a>. MediaTranscodingManager provides an interface to the system's media
- transcoding service and can be used to transcode media files, e.g. transcoding a video from HEVC to
- AVC.
-
- <h3>Transcoding Types</h3>
- <h4>Video Transcoding</h4>
- When transcoding a video file, the video track will be transcoded based on the desired track format
- and the audio track will be pass through without any modification.
- <p class=note>
- Note that currently only support transcoding video file in mp4 format and with single video track.
-
- <h3>Transcoding Request</h3>
- <p>
- To transcode a media file, first create a {@link TranscodingRequest} through its builder class
- {@link VideoTranscodingRequest.Builder}. Transcode requests are then enqueue to the manager through
- {@link MediaTranscodingManager#enqueueRequest(
-         TranscodingRequest, Executor, OnTranscodingFinishedListener)}
- TranscodeRequest are processed based on client process's priority and request priority. When a
- transcode operation is completed the caller is notified via its
- {@link OnTranscodingFinishedListener}.
- In the meantime the caller may use the returned TranscodingSession object to cancel or check the
- status of a specific transcode operation.
- <p>
- Here is an example where <code>Builder</code> is used to specify all parameters
-
- <pre class=prettyprint>
- VideoTranscodingRequest request =
-    new VideoTranscodingRequest.Builder(srcUri, dstUri, videoFormat).build();
- }</pre>
- @hide
- */
-@MinSdk(Build.VERSION_CODES.S)
-@SystemApi
-public final class MediaTranscodingManager {
-    private static final String TAG = "MediaTranscodingManager";
-
-    /** Maximum number of retry to connect to the service. */
-    private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
-
-    /** Interval between trying to reconnect to the service. */
-    private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
-
-    /** Default bpp(bits-per-pixel) to use for calculating default bitrate. */
-    private static final float BPP = 0.25f;
-
-    /**
-     * Listener that gets notified when a transcoding operation has finished.
-     * This listener gets notified regardless of how the operation finished. It is up to the
-     * listener implementation to check the result and take appropriate action.
-     */
-    @FunctionalInterface
-    public interface OnTranscodingFinishedListener {
-        /**
-         * Called when the transcoding operation has finished. The receiver may use the
-         * TranscodingSession to check the result, i.e. whether the operation succeeded, was
-         * canceled or if an error occurred.
-         *
-         * @param session The TranscodingSession instance for the finished transcoding operation.
-         */
-        void onTranscodingFinished(@NonNull TranscodingSession session);
-    }
-
-    private final Context mContext;
-    private ContentResolver mContentResolver;
-    private final String mPackageName;
-    private final int mPid;
-    private final int mUid;
-    private final boolean mIsLowRamDevice;
-    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
-    private final HashMap<Integer, TranscodingSession> mPendingTranscodingSessions = new HashMap();
-    private final Object mLock = new Object();
-    @GuardedBy("mLock")
-    @NonNull private ITranscodingClient mTranscodingClient = null;
-    private static MediaTranscodingManager sMediaTranscodingManager;
-
-    private void handleTranscodingFinished(int sessionId, TranscodingResultParcel result) {
-        synchronized (mPendingTranscodingSessions) {
-            // Gets the session associated with the sessionId and removes it from
-            // mPendingTranscodingSessions.
-            final TranscodingSession session = mPendingTranscodingSessions.remove(sessionId);
-
-            if (session == null) {
-                // This should not happen in reality.
-                Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
-                return;
-            }
-
-            // Updates the session status and result.
-            session.updateStatusAndResult(TranscodingSession.STATUS_FINISHED,
-                    TranscodingSession.RESULT_SUCCESS,
-                    TranscodingSession.ERROR_NONE);
-
-            // Notifies client the session is done.
-            if (session.mListener != null && session.mListenerExecutor != null) {
-                session.mListenerExecutor.execute(
-                        () -> session.mListener.onTranscodingFinished(session));
-            }
-        }
-    }
-
-    private void handleTranscodingFailed(int sessionId, int errorCode) {
-        synchronized (mPendingTranscodingSessions) {
-            // Gets the session associated with the sessionId and removes it from
-            // mPendingTranscodingSessions.
-            final TranscodingSession session = mPendingTranscodingSessions.remove(sessionId);
-
-            if (session == null) {
-                // This should not happen in reality.
-                Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
-                return;
-            }
-
-            // Updates the session status and result.
-            session.updateStatusAndResult(TranscodingSession.STATUS_FINISHED,
-                    TranscodingSession.RESULT_ERROR, errorCode);
-
-            // Notifies client the session failed.
-            if (session.mListener != null && session.mListenerExecutor != null) {
-                session.mListenerExecutor.execute(
-                        () -> session.mListener.onTranscodingFinished(session));
-            }
-        }
-    }
-
-    private void handleTranscodingProgressUpdate(int sessionId, int newProgress) {
-        synchronized (mPendingTranscodingSessions) {
-            // Gets the session associated with the sessionId.
-            final TranscodingSession session = mPendingTranscodingSessions.get(sessionId);
-
-            if (session == null) {
-                // This should not happen in reality.
-                Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
-                return;
-            }
-
-            // Updates the session progress.
-            session.updateProgress(newProgress);
-
-            // Notifies client the progress update.
-            if (session.mProgressUpdateExecutor != null
-                    && session.mProgressUpdateListener != null) {
-                session.mProgressUpdateExecutor.execute(
-                        () -> session.mProgressUpdateListener.onProgressUpdate(session,
-                                newProgress));
-            }
-        }
-    }
-
-    private IMediaTranscodingService getService(boolean retry) {
-        // Do not try to get the service on pre-S. The service is lazy-start and getting the
-        // service could block.
-        if (!SdkLevel.isAtLeastS()) {
-            return null;
-        }
-        // Do not try to get the service on AndroidGo (low-ram) devices.
-        if (mIsLowRamDevice) {
-            return null;
-        }
-        int retryCount = !retry ? 1 :  CONNECT_SERVICE_RETRY_COUNT;
-        Log.i(TAG, "get service with retry " + retryCount);
-        for (int count = 1;  count <= retryCount; count++) {
-            Log.d(TAG, "Trying to connect to service. Try count: " + count);
-            IMediaTranscodingService service = IMediaTranscodingService.Stub.asInterface(
-                    MediaFrameworkInitializer
-                    .getMediaServiceManager()
-                    .getMediaTranscodingServiceRegisterer()
-                    .get());
-            if (service != null) {
-                return service;
-            }
-            try {
-                // Sleep a bit before retry.
-                Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
-            } catch (InterruptedException ie) {
-                /* ignore */
-            }
-        }
-        Log.w(TAG, "Failed to get service");
-        return null;
-    }
-
-    /*
-     * Handle client binder died event.
-     * Upon receiving a binder died event of the client, we will do the following:
-     * 1) For the session that is running, notify the client that the session is failed with
-     *    error code,  so client could choose to retry the session or not.
-     *    TODO(hkuang): Add a new error code to signal service died error.
-     * 2) For the sessions that is still pending or paused, we will resubmit the session
-     *    once we successfully reconnect to the service and register a new client.
-     * 3) When trying to connect to the service and register a new client. The service may need time
-     *    to reboot or never boot up again. So we will retry for a number of times. If we still
-     *    could not connect, we will notify client session failure for the pending and paused
-     *    sessions.
-     */
-    private void onClientDied() {
-        synchronized (mLock) {
-            mTranscodingClient = null;
-        }
-
-        // Delegates the session notification and retry to the executor as it may take some time.
-        mExecutor.execute(() -> {
-            // List to track the sessions that we want to retry.
-            List<TranscodingSession> retrySessions = new ArrayList<TranscodingSession>();
-
-            // First notify the client of session failure for all the running sessions.
-            synchronized (mPendingTranscodingSessions) {
-                for (Map.Entry<Integer, TranscodingSession> entry :
-                        mPendingTranscodingSessions.entrySet()) {
-                    TranscodingSession session = entry.getValue();
-
-                    if (session.getStatus() == TranscodingSession.STATUS_RUNNING) {
-                        session.updateStatusAndResult(TranscodingSession.STATUS_FINISHED,
-                                TranscodingSession.RESULT_ERROR,
-                                TranscodingSession.ERROR_SERVICE_DIED);
-
-                        // Remove the session from pending sessions.
-                        mPendingTranscodingSessions.remove(entry.getKey());
-
-                        if (session.mListener != null && session.mListenerExecutor != null) {
-                            Log.i(TAG, "Notify client session failed");
-                            session.mListenerExecutor.execute(
-                                    () -> session.mListener.onTranscodingFinished(session));
-                        }
-                    } else if (session.getStatus() == TranscodingSession.STATUS_PENDING
-                            || session.getStatus() == TranscodingSession.STATUS_PAUSED) {
-                        // Add the session to retrySessions to handle them later.
-                        retrySessions.add(session);
-                    }
-                }
-            }
-
-            // Try to register with the service once it boots up.
-            IMediaTranscodingService service = getService(true /*retry*/);
-            boolean haveTranscodingClient = false;
-            if (service != null) {
-                synchronized (mLock) {
-                    mTranscodingClient = registerClient(service);
-                    if (mTranscodingClient != null) {
-                        haveTranscodingClient = true;
-                    }
-                }
-            }
-
-            for (TranscodingSession session : retrySessions) {
-                // Notify the session failure if we fails to connect to the service or fail
-                // to retry the session.
-                if (!haveTranscodingClient) {
-                    // TODO(hkuang): Return correct error code to the client.
-                    handleTranscodingFailed(session.getSessionId(), 0 /*unused */);
-                }
-
-                try {
-                    // Do not set hasRetried for retry initiated by MediaTranscodingManager.
-                    session.retryInternal(false /*setHasRetried*/);
-                } catch (Exception re) {
-                    // TODO(hkuang): Return correct error code to the client.
-                    handleTranscodingFailed(session.getSessionId(), 0 /*unused */);
-                }
-            }
-        });
-    }
-
-    private void updateStatus(int sessionId, int status) {
-        synchronized (mPendingTranscodingSessions) {
-            final TranscodingSession session = mPendingTranscodingSessions.get(sessionId);
-
-            if (session == null) {
-                // This should not happen in reality.
-                Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
-                return;
-            }
-
-            // Updates the session status.
-            session.updateStatus(status);
-        }
-    }
-
-    // Just forwards all the events to the event handler.
-    private ITranscodingClientCallback mTranscodingClientCallback =
-            new ITranscodingClientCallback.Stub() {
-                // TODO(hkuang): Add more unit test to test difference file open mode.
-                @Override
-                public ParcelFileDescriptor openFileDescriptor(String fileUri, String mode)
-                        throws RemoteException {
-                    if (!mode.equals("r") && !mode.equals("w") && !mode.equals("rw")) {
-                        Log.e(TAG, "Unsupport mode: " + mode);
-                        return null;
-                    }
-
-                    Uri uri = Uri.parse(fileUri);
-                    try {
-                        AssetFileDescriptor afd = mContentResolver.openAssetFileDescriptor(uri,
-                                mode);
-                        if (afd != null) {
-                            return afd.getParcelFileDescriptor();
-                        }
-                    } catch (FileNotFoundException e) {
-                        Log.w(TAG, "Cannot find content uri: " + uri, e);
-                    } catch (SecurityException e) {
-                        Log.w(TAG, "Cannot open content uri: " + uri, e);
-                    } catch (Exception e) {
-                        Log.w(TAG, "Unknown content uri: " + uri, e);
-                    }
-                    return null;
-                }
-
-                @Override
-                public void onTranscodingStarted(int sessionId) throws RemoteException {
-                    updateStatus(sessionId, TranscodingSession.STATUS_RUNNING);
-                }
-
-                @Override
-                public void onTranscodingPaused(int sessionId) throws RemoteException {
-                    updateStatus(sessionId, TranscodingSession.STATUS_PAUSED);
-                }
-
-                @Override
-                public void onTranscodingResumed(int sessionId) throws RemoteException {
-                    updateStatus(sessionId, TranscodingSession.STATUS_RUNNING);
-                }
-
-                @Override
-                public void onTranscodingFinished(int sessionId, TranscodingResultParcel result)
-                        throws RemoteException {
-                    handleTranscodingFinished(sessionId, result);
-                }
-
-                @Override
-                public void onTranscodingFailed(int sessionId, int errorCode)
-                        throws RemoteException {
-                    handleTranscodingFailed(sessionId, errorCode);
-                }
-
-                @Override
-                public void onAwaitNumberOfSessionsChanged(int sessionId, int oldAwaitNumber,
-                        int newAwaitNumber) throws RemoteException {
-                    //TODO(hkuang): Implement this.
-                }
-
-                @Override
-                public void onProgressUpdate(int sessionId, int newProgress)
-                        throws RemoteException {
-                    handleTranscodingProgressUpdate(sessionId, newProgress);
-                }
-            };
-
-    private ITranscodingClient registerClient(IMediaTranscodingService service) {
-        synchronized (mLock) {
-            try {
-                // Registers the client with MediaTranscoding service.
-                mTranscodingClient = service.registerClient(
-                        mTranscodingClientCallback,
-                        mPackageName,
-                        mPackageName);
-
-                if (mTranscodingClient != null) {
-                    mTranscodingClient.asBinder().linkToDeath(() -> onClientDied(), /* flags */ 0);
-                }
-            } catch (Exception ex) {
-                Log.e(TAG, "Failed to register new client due to exception " + ex);
-                mTranscodingClient = null;
-            }
-        }
-        return mTranscodingClient;
-    }
-
-    /**
-     * @hide
-     */
-    public MediaTranscodingManager(@NonNull Context context) {
-        mContext = context;
-        mContentResolver = mContext.getContentResolver();
-        mPackageName = mContext.getPackageName();
-        mUid = Os.getuid();
-        mPid = Os.getpid();
-        mIsLowRamDevice = mContext.getSystemService(ActivityManager.class).isLowRamDevice();
-    }
-
-    /**
-     * Abstract base class for all the TranscodingRequest.
-     * <p> TranscodingRequest encapsulates the desired configuration for the transcoding.
-     */
-    public abstract static class TranscodingRequest {
-        /**
-         *
-         * Default transcoding type.
-         * @hide
-         */
-        public static final int TRANSCODING_TYPE_UNKNOWN = 0;
-
-        /**
-         * TRANSCODING_TYPE_VIDEO indicates that client wants to perform transcoding on a video.
-         * <p>Note that currently only support transcoding video file in mp4 format.
-         * @hide
-         */
-        public static final int TRANSCODING_TYPE_VIDEO = 1;
-
-        /**
-         * TRANSCODING_TYPE_IMAGE indicates that client wants to perform transcoding on an image.
-         * @hide
-         */
-        public static final int TRANSCODING_TYPE_IMAGE = 2;
-
-        /** @hide */
-        @IntDef(prefix = {"TRANSCODING_TYPE_"}, value = {
-                TRANSCODING_TYPE_UNKNOWN,
-                TRANSCODING_TYPE_VIDEO,
-                TRANSCODING_TYPE_IMAGE,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface TranscodingType {}
-
-        /**
-         * Default value.
-         *
-         * @hide
-         */
-        public static final int PRIORITY_UNKNOWN = 0;
-        /**
-         * PRIORITY_REALTIME indicates that the transcoding request is time-critical and that the
-         * client wants the transcoding result as soon as possible.
-         * <p> Set PRIORITY_REALTIME only if the transcoding is time-critical as it will involve
-         * performance penalty due to resource reallocation to prioritize the sessions with higher
-         * priority.
-         *
-         * @hide
-         */
-        public static final int PRIORITY_REALTIME = 1;
-
-        /**
-         * PRIORITY_OFFLINE indicates the transcoding is not time-critical and the client does not
-         * need the transcoding result as soon as possible.
-         * <p>Sessions with PRIORITY_OFFLINE will be scheduled behind PRIORITY_REALTIME. Always set
-         * to
-         * PRIORITY_OFFLINE if client does not need the result as soon as possible and could accept
-         * delay of the transcoding result.
-         *
-         * @hide
-         *
-         */
-        public static final int PRIORITY_OFFLINE = 2;
-
-        /** @hide */
-        @IntDef(prefix = {"PRIORITY_"}, value = {
-                PRIORITY_UNKNOWN,
-                PRIORITY_REALTIME,
-                PRIORITY_OFFLINE,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface TranscodingPriority {}
-
-        /** Uri of the source media file. */
-        private @NonNull Uri mSourceUri;
-
-        /** Uri of the destination media file. */
-        private @NonNull Uri mDestinationUri;
-
-        /** FileDescriptor of the source media file. */
-        private @Nullable ParcelFileDescriptor mSourceFileDescriptor;
-
-        /** FileDescriptor of the destination media file. */
-        private @Nullable ParcelFileDescriptor mDestinationFileDescriptor;
-
-        /**
-         *  The UID of the client that the TranscodingRequest is for. Only privileged caller could
-         *  set this Uid as only they could do the transcoding on behalf of the client.
-         *  -1 means not available.
-         */
-        private int mClientUid = -1;
-
-        /**
-         *  The Pid of the client that the TranscodingRequest is for. Only privileged caller could
-         *  set this Uid as only they could do the transcoding on behalf of the client.
-         *  -1 means not available.
-         */
-        private int mClientPid = -1;
-
-        /** Type of the transcoding. */
-        private @TranscodingType int mType = TRANSCODING_TYPE_UNKNOWN;
-
-        /** Priority of the transcoding. */
-        private @TranscodingPriority int mPriority = PRIORITY_UNKNOWN;
-
-        /**
-         * Desired image format for the destination file.
-         * <p> If this is null, source file's image track will be passed through and copied to the
-         * destination file.
-         * @hide
-         */
-        private @Nullable MediaFormat mImageFormat = null;
-
-        @VisibleForTesting
-        private TranscodingTestConfig mTestConfig = null;
-
-        /**
-         * Prevent public constructor access.
-         */
-        /* package private */ TranscodingRequest() {
-        }
-
-        private TranscodingRequest(Builder b) {
-            mSourceUri = b.mSourceUri;
-            mSourceFileDescriptor = b.mSourceFileDescriptor;
-            mDestinationUri = b.mDestinationUri;
-            mDestinationFileDescriptor = b.mDestinationFileDescriptor;
-            mClientUid = b.mClientUid;
-            mClientPid = b.mClientPid;
-            mPriority = b.mPriority;
-            mType = b.mType;
-            mTestConfig = b.mTestConfig;
-        }
-
-        /**
-         * Return the type of the transcoding.
-         * @hide
-         */
-        @TranscodingType
-        public int getType() {
-            return mType;
-        }
-
-        /** Return source uri of the transcoding. */
-        @NonNull
-        public Uri getSourceUri() {
-            return mSourceUri;
-        }
-
-        /**
-         * Return source file descriptor of the transcoding.
-         * This will be null if client has not provided it.
-         */
-        @Nullable
-        public ParcelFileDescriptor getSourceFileDescriptor() {
-            return mSourceFileDescriptor;
-        }
-
-        /** Return the UID of the client that this request is for. -1 means not available. */
-        public int getClientUid() {
-            return mClientUid;
-        }
-
-        /** Return the PID of the client that this request is for. -1 means not available. */
-        public int getClientPid() {
-            return mClientPid;
-        }
-
-        /** Return destination uri of the transcoding. */
-        @NonNull
-        public Uri getDestinationUri() {
-            return mDestinationUri;
-        }
-
-        /**
-         * Return destination file descriptor of the transcoding.
-         * This will be null if client has not provided it.
-         */
-        @Nullable
-        public ParcelFileDescriptor getDestinationFileDescriptor() {
-            return mDestinationFileDescriptor;
-        }
-
-        /**
-         * Return priority of the transcoding.
-         * @hide
-         */
-        @TranscodingPriority
-        public int getPriority() {
-            return mPriority;
-        }
-
-        /**
-         * Return TestConfig of the transcoding.
-         * @hide
-         */
-        @Nullable
-        public TranscodingTestConfig getTestConfig() {
-            return mTestConfig;
-        }
-
-        abstract void writeFormatToParcel(TranscodingRequestParcel parcel);
-
-        /* Writes the TranscodingRequest to a parcel. */
-        private TranscodingRequestParcel writeToParcel(@NonNull Context context) {
-            TranscodingRequestParcel parcel = new TranscodingRequestParcel();
-            switch (mPriority) {
-            case PRIORITY_OFFLINE:
-                parcel.priority = TranscodingSessionPriority.kUnspecified;
-                break;
-            case PRIORITY_REALTIME:
-            case PRIORITY_UNKNOWN:
-            default:
-                parcel.priority = TranscodingSessionPriority.kNormal;
-                break;
-            }
-            parcel.transcodingType = mType;
-            parcel.sourceFilePath = mSourceUri.toString();
-            parcel.sourceFd = mSourceFileDescriptor;
-            parcel.destinationFilePath = mDestinationUri.toString();
-            parcel.destinationFd = mDestinationFileDescriptor;
-            parcel.clientUid = mClientUid;
-            parcel.clientPid = mClientPid;
-            if (mClientUid < 0) {
-                parcel.clientPackageName = context.getPackageName();
-            } else {
-                String packageName = context.getPackageManager().getNameForUid(mClientUid);
-                // PackageName is optional as some uid does not have package name. Set to
-                // "Unavailable" string in this case.
-                if (packageName == null) {
-                    Log.w(TAG, "Failed to find package for uid: " + mClientUid);
-                    packageName = "Unavailable";
-                }
-                parcel.clientPackageName = packageName;
-            }
-            writeFormatToParcel(parcel);
-            if (mTestConfig != null) {
-                parcel.isForTesting = true;
-                parcel.testConfig = mTestConfig;
-            }
-            return parcel;
-        }
-
-        /**
-         * Builder to build a {@link TranscodingRequest} object.
-         *
-         * @param <T> The subclass to be built.
-         */
-        abstract static class Builder<T extends Builder<T>> {
-            private @NonNull Uri mSourceUri;
-            private @NonNull Uri mDestinationUri;
-            private @Nullable ParcelFileDescriptor mSourceFileDescriptor = null;
-            private @Nullable ParcelFileDescriptor mDestinationFileDescriptor = null;
-            private int mClientUid = -1;
-            private int mClientPid = -1;
-            private @TranscodingType int mType = TRANSCODING_TYPE_UNKNOWN;
-            private @TranscodingPriority int mPriority = PRIORITY_UNKNOWN;
-            private TranscodingTestConfig mTestConfig;
-
-            abstract T self();
-
-            /**
-             * Creates a builder for building {@link TranscodingRequest}s.
-             *
-             * Client must set the source Uri. If client also provides the source fileDescriptor
-             * through is provided by {@link #setSourceFileDescriptor(ParcelFileDescriptor)},
-             * TranscodingSession will use the fd instead of calling back to the client to open the
-             * sourceUri.
-             *
-             *
-             * @param type The transcoding type.
-             * @param sourceUri Content uri for the source media file.
-             * @param destinationUri Content uri for the destination media file.
-             *
-             */
-            private Builder(@TranscodingType int type, @NonNull Uri sourceUri,
-                    @NonNull Uri destinationUri) {
-                mType = type;
-
-                if (sourceUri == null || Uri.EMPTY.equals(sourceUri)) {
-                    throw new IllegalArgumentException(
-                            "You must specify a non-empty source Uri.");
-                }
-                mSourceUri = sourceUri;
-
-                if (destinationUri == null || Uri.EMPTY.equals(destinationUri)) {
-                    throw new IllegalArgumentException(
-                            "You must specify a non-empty destination Uri.");
-                }
-                mDestinationUri = destinationUri;
-            }
-
-            /**
-             * Specifies the fileDescriptor opened from the source media file.
-             *
-             * This call is optional. If the source fileDescriptor is provided, TranscodingSession
-             * will use it directly instead of opening the uri from {@link #Builder(int, Uri, Uri)}.
-             * It is client's responsibility to make sure the fileDescriptor is opened from the
-             * source uri.
-             * @param fileDescriptor a {@link ParcelFileDescriptor} opened from source media file.
-             * @return The same builder instance.
-             * @throws IllegalArgumentException if fileDescriptor is invalid.
-             */
-            @NonNull
-            public T setSourceFileDescriptor(@NonNull ParcelFileDescriptor fileDescriptor) {
-                if (fileDescriptor == null || fileDescriptor.getFd() < 0) {
-                    throw new IllegalArgumentException(
-                            "Invalid source descriptor.");
-                }
-                mSourceFileDescriptor = fileDescriptor;
-                return self();
-            }
-
-            /**
-             * Specifies the fileDescriptor opened from the destination media file.
-             *
-             * This call is optional. If the destination fileDescriptor is provided,
-             * TranscodingSession will use it directly instead of opening the source uri from
-             * {@link #Builder(int, Uri, Uri)} upon transcoding starts. It is client's
-             * responsibility to make sure the fileDescriptor is opened from the destination uri.
-             * @param fileDescriptor a {@link ParcelFileDescriptor} opened from destination media
-             *                       file.
-             * @return The same builder instance.
-             * @throws IllegalArgumentException if fileDescriptor is invalid.
-             */
-            @NonNull
-            public T setDestinationFileDescriptor(
-                    @NonNull ParcelFileDescriptor fileDescriptor) {
-                if (fileDescriptor == null || fileDescriptor.getFd() < 0) {
-                    throw new IllegalArgumentException(
-                            "Invalid destination descriptor.");
-                }
-                mDestinationFileDescriptor = fileDescriptor;
-                return self();
-            }
-
-            /**
-             * Specify the UID of the client that this request is for.
-             * <p>
-             * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could forward the
-             * pid. Note that the permission check happens on the service side upon starting the
-             * transcoding. If the client does not have the permission, the transcoding will fail.
-             *
-             * @param uid client Uid.
-             * @return The same builder instance.
-             * @throws IllegalArgumentException if uid is invalid.
-             */
-            @NonNull
-            public T setClientUid(int uid) {
-                if (uid < 0) {
-                    throw new IllegalArgumentException("Invalid Uid");
-                }
-                mClientUid = uid;
-                return self();
-            }
-
-            /**
-             * Specify the pid of the client that this request is for.
-             * <p>
-             * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could forward the
-             * pid. Note that the permission check happens on the service side upon starting the
-             * transcoding. If the client does not have the permission, the transcoding will fail.
-             *
-             * @param pid client Pid.
-             * @return The same builder instance.
-             * @throws IllegalArgumentException if pid is invalid.
-             */
-            @NonNull
-            public T setClientPid(int pid) {
-                if (pid < 0) {
-                    throw new IllegalArgumentException("Invalid pid");
-                }
-                mClientPid = pid;
-                return self();
-            }
-
-            /**
-             * Specifies the priority of the transcoding.
-             *
-             * @param priority Must be one of the {@code PRIORITY_*}
-             * @return The same builder instance.
-             * @throws IllegalArgumentException if flags is invalid.
-             * @hide
-             */
-            @NonNull
-            public T setPriority(@TranscodingPriority int priority) {
-                if (priority != PRIORITY_OFFLINE && priority != PRIORITY_REALTIME) {
-                    throw new IllegalArgumentException("Invalid priority: " + priority);
-                }
-                mPriority = priority;
-                return self();
-            }
-
-            /**
-             * Sets the delay in processing this request.
-             * @param config test config.
-             * @return The same builder instance.
-             * @hide
-             */
-            @VisibleForTesting
-            @NonNull
-            public T setTestConfig(@NonNull TranscodingTestConfig config) {
-                mTestConfig = config;
-                return self();
-            }
-        }
-
-        /**
-         * Abstract base class for all the format resolvers.
-         */
-        abstract static class MediaFormatResolver {
-            private @NonNull ApplicationMediaCapabilities mClientCaps;
-
-            /**
-             * Prevents public constructor access.
-             */
-            /* package private */ MediaFormatResolver() {
-            }
-
-            /**
-             * Constructs MediaFormatResolver object.
-             *
-             * @param clientCaps An ApplicationMediaCapabilities object containing the client's
-             *                   capabilities.
-             */
-            MediaFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps) {
-                if (clientCaps == null) {
-                    throw new IllegalArgumentException("Client capabilities must not be null");
-                }
-                mClientCaps = clientCaps;
-            }
-
-            /**
-             * Returns the client capabilities.
-             */
-            @NonNull
-            /* package */ ApplicationMediaCapabilities getClientCapabilities() {
-                return mClientCaps;
-            }
-
-            abstract boolean shouldTranscode();
-        }
-
-        /**
-         * VideoFormatResolver for deciding if video transcoding is needed, and if so, the track
-         * formats to use.
-         */
-        public static class VideoFormatResolver extends MediaFormatResolver {
-            private static final int BIT_RATE = 20000000;            // 20Mbps
-
-            private MediaFormat mSrcVideoFormatHint;
-            private MediaFormat mSrcAudioFormatHint;
-
-            /**
-             * Constructs a new VideoFormatResolver object.
-             *
-             * @param clientCaps An ApplicationMediaCapabilities object containing the client's
-             *                   capabilities.
-             * @param srcVideoFormatHint A MediaFormat object containing information about the
-             *                           source's video track format that could affect the
-             *                           transcoding decision. Such information could include video
-             *                           codec types, color spaces, whether special format info (eg.
-             *                           slow-motion markers) are present, etc.. If a particular
-             *                           information is not present, it will not be used to make the
-             *                           decision.
-             */
-            public VideoFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps,
-                    @NonNull MediaFormat srcVideoFormatHint) {
-                super(clientCaps);
-                mSrcVideoFormatHint = srcVideoFormatHint;
-            }
-
-            /**
-             * Constructs a new VideoFormatResolver object.
-             *
-             * @param clientCaps An ApplicationMediaCapabilities object containing the client's
-             *                   capabilities.
-             * @param srcVideoFormatHint A MediaFormat object containing information about the
-             *                           source's video track format that could affect the
-             *                           transcoding decision. Such information could include video
-             *                           codec types, color spaces, whether special format info (eg.
-             *                           slow-motion markers) are present, etc.. If a particular
-             *                           information is not present, it will not be used to make the
-             *                           decision.
-             * @param srcAudioFormatHint A MediaFormat object containing information about the
-             *                           source's audio track format that could affect the
-             *                           transcoding decision.
-             * @hide
-             */
-            VideoFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps,
-                    @NonNull MediaFormat srcVideoFormatHint,
-                    @NonNull MediaFormat srcAudioFormatHint) {
-                super(clientCaps);
-                mSrcVideoFormatHint = srcVideoFormatHint;
-                mSrcAudioFormatHint = srcAudioFormatHint;
-            }
-
-            /**
-             * Returns whether the source content should be transcoded.
-             *
-             * @return true if the source should be transcoded.
-             */
-            public boolean shouldTranscode() {
-                boolean supportHevc = getClientCapabilities().isVideoMimeTypeSupported(
-                        MediaFormat.MIMETYPE_VIDEO_HEVC);
-                if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals(
-                        mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) {
-                    return true;
-                }
-                // TODO: add more checks as needed below.
-                return false;
-            }
-
-            /**
-             * Retrieves the video track format to be used on
-             * {@link VideoTranscodingRequest.Builder#setVideoTrackFormat(MediaFormat)} for this
-             * configuration.
-             *
-             * @return the video track format to be used if transcoding should be performed,
-             *         and null otherwise.
-             * @throws IllegalArgumentException if the hinted source video format contains invalid
-             *         parameters.
-             */
-            @Nullable
-            public MediaFormat resolveVideoFormat() {
-                if (!shouldTranscode()) {
-                    return null;
-                }
-
-                MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint);
-                videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
-
-                int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH, -1);
-                int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT, -1);
-                if (width <= 0 || height <= 0) {
-                    throw new IllegalArgumentException(
-                            "Source Width and height must be larger than 0");
-                }
-
-                float frameRate =
-                        mSrcVideoFormatHint.getNumber(MediaFormat.KEY_FRAME_RATE, 30.0)
-                        .floatValue();
-                if (frameRate <= 0) {
-                    throw new IllegalArgumentException(
-                            "frameRate must be larger than 0");
-                }
-
-                int bitrate = getAVCBitrate(width, height, frameRate);
-                videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-                return videoTrackFormat;
-            }
-
-            /**
-             * Generate a default bitrate with the fixed bpp(bits-per-pixel) 0.25.
-             * This maps to:
-             * 1080P@30fps -> 16Mbps
-             * 1080P@60fps-> 32Mbps
-             * 4K@30fps -> 62Mbps
-             */
-            private static int getDefaultBitrate(int width, int height, float frameRate) {
-                return (int) (width * height * frameRate * BPP);
-            }
-
-            /**
-             * Query the bitrate from CamcorderProfile. If there are two profiles that match the
-             * width/height/framerate, we will use the higher one to get better quality.
-             * Return default bitrate if could not find any match profile.
-             */
-            private static int getAVCBitrate(int width, int height, float frameRate) {
-                int bitrate = -1;
-                int[] cameraIds = {0, 1};
-
-                // Profiles ordered in decreasing order of preference.
-                int[] preferQualities = {
-                        CamcorderProfile.QUALITY_2160P,
-                        CamcorderProfile.QUALITY_1080P,
-                        CamcorderProfile.QUALITY_720P,
-                        CamcorderProfile.QUALITY_480P,
-                        CamcorderProfile.QUALITY_LOW,
-                };
-
-                for (int cameraId : cameraIds) {
-                    for (int quality : preferQualities) {
-                        // Check if camera id has profile for the quality level.
-                        if (!CamcorderProfile.hasProfile(cameraId, quality)) {
-                            continue;
-                        }
-                        CamcorderProfile profile = CamcorderProfile.get(cameraId, quality);
-                        // Check the width/height/framerate/codec, also consider portrait case.
-                        if (((width == profile.videoFrameWidth
-                                && height == profile.videoFrameHeight)
-                                || (height == profile.videoFrameWidth
-                                && width == profile.videoFrameHeight))
-                                && (int) frameRate == profile.videoFrameRate
-                                && profile.videoCodec == MediaRecorder.VideoEncoder.H264) {
-                            if (bitrate < profile.videoBitRate) {
-                                bitrate = profile.videoBitRate;
-                            }
-                            break;
-                        }
-                    }
-                }
-
-                if (bitrate == -1) {
-                    Log.w(TAG, "Failed to find CamcorderProfile for w: " + width + "h: " + height
-                            + " fps: "
-                            + frameRate);
-                    bitrate = getDefaultBitrate(width, height, frameRate);
-                }
-                Log.d(TAG, "Using bitrate " + bitrate + " for " + width + " " + height + " "
-                        + frameRate);
-                return bitrate;
-            }
-
-            /**
-             * Retrieves the audio track format to be used for transcoding.
-             *
-             * @return the audio track format to be used if transcoding should be performed, and
-             *         null otherwise.
-             * @hide
-             */
-            @Nullable
-            public MediaFormat resolveAudioFormat() {
-                if (!shouldTranscode()) {
-                    return null;
-                }
-                // Audio transcoding is not supported yet, always return null.
-                return null;
-            }
-        }
-    }
-
-    /**
-     * VideoTranscodingRequest encapsulates the configuration for transcoding a video.
-     */
-    public static final class VideoTranscodingRequest extends TranscodingRequest {
-        /**
-         * Desired output video format of the destination file.
-         * <p> If this is null, source file's video track will be passed through and copied to the
-         * destination file.
-         */
-        private @Nullable MediaFormat mVideoTrackFormat = null;
-
-        /**
-         * Desired output audio format of the destination file.
-         * <p> If this is null, source file's audio track will be passed through and copied to the
-         * destination file.
-         */
-        private @Nullable MediaFormat mAudioTrackFormat = null;
-
-        private VideoTranscodingRequest(VideoTranscodingRequest.Builder builder) {
-            super(builder);
-            mVideoTrackFormat = builder.mVideoTrackFormat;
-            mAudioTrackFormat = builder.mAudioTrackFormat;
-        }
-
-        /**
-         * Return the video track format of the transcoding.
-         * This will be null if client has not specified the video track format.
-         */
-        @NonNull
-        public MediaFormat getVideoTrackFormat() {
-            return mVideoTrackFormat;
-        }
-
-        @Override
-        void writeFormatToParcel(TranscodingRequestParcel parcel) {
-            parcel.requestedVideoTrackFormat = convertToVideoTrackFormat(mVideoTrackFormat);
-        }
-
-        /* Converts the MediaFormat to TranscodingVideoTrackFormat. */
-        private static TranscodingVideoTrackFormat convertToVideoTrackFormat(MediaFormat format) {
-            if (format == null) {
-                throw new IllegalArgumentException("Invalid MediaFormat");
-            }
-
-            TranscodingVideoTrackFormat trackFormat = new TranscodingVideoTrackFormat();
-
-            if (format.containsKey(MediaFormat.KEY_MIME)) {
-                String mime = format.getString(MediaFormat.KEY_MIME);
-                if (MediaFormat.MIMETYPE_VIDEO_AVC.equals(mime)) {
-                    trackFormat.codecType = TranscodingVideoCodecType.kAvc;
-                } else if (MediaFormat.MIMETYPE_VIDEO_HEVC.equals(mime)) {
-                    trackFormat.codecType = TranscodingVideoCodecType.kHevc;
-                } else {
-                    throw new UnsupportedOperationException("Only support transcode to avc/hevc");
-                }
-            }
-
-            if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
-                int bitrateBps = format.getInteger(MediaFormat.KEY_BIT_RATE);
-                if (bitrateBps <= 0) {
-                    throw new IllegalArgumentException("Bitrate must be larger than 0");
-                }
-                trackFormat.bitrateBps = bitrateBps;
-            }
-
-            if (format.containsKey(MediaFormat.KEY_WIDTH) && format.containsKey(
-                    MediaFormat.KEY_HEIGHT)) {
-                int width = format.getInteger(MediaFormat.KEY_WIDTH);
-                int height = format.getInteger(MediaFormat.KEY_HEIGHT);
-                if (width <= 0 || height <= 0) {
-                    throw new IllegalArgumentException("Width and height must be larger than 0");
-                }
-                // TODO: Validate the aspect ratio after adding scaling.
-                trackFormat.width = width;
-                trackFormat.height = height;
-            }
-
-            if (format.containsKey(MediaFormat.KEY_PROFILE)) {
-                int profile = format.getInteger(MediaFormat.KEY_PROFILE);
-                if (profile <= 0) {
-                    throw new IllegalArgumentException("Invalid codec profile");
-                }
-                // TODO: Validate the profile according to codec type.
-                trackFormat.profile = profile;
-            }
-
-            if (format.containsKey(MediaFormat.KEY_LEVEL)) {
-                int level = format.getInteger(MediaFormat.KEY_LEVEL);
-                if (level <= 0) {
-                    throw new IllegalArgumentException("Invalid codec level");
-                }
-                // TODO: Validate the level according to codec type.
-                trackFormat.level = level;
-            }
-
-            return trackFormat;
-        }
-
-        /**
-         * Builder class for {@link VideoTranscodingRequest}.
-         */
-        public static final class Builder extends
-                TranscodingRequest.Builder<VideoTranscodingRequest.Builder> {
-            /**
-             * Desired output video format of the destination file.
-             * <p> If this is null, source file's video track will be passed through and
-             * copied to the destination file.
-             */
-            private @Nullable MediaFormat mVideoTrackFormat = null;
-
-            /**
-             * Desired output audio format of the destination file.
-             * <p> If this is null, source file's audio track will be passed through and copied
-             * to the destination file.
-             */
-            private @Nullable MediaFormat mAudioTrackFormat = null;
-
-            /**
-             * Creates a builder for building {@link VideoTranscodingRequest}s.
-             *
-             * <p> Client could only specify the settings that matters to them, e.g. codec format or
-             * bitrate. And by default, transcoding will preserve the original video's settings
-             * (bitrate, framerate, resolution) if not provided.
-             * <p>Note that some settings may silently fail to apply if the device does not support
-             * them.
-             * @param sourceUri Content uri for the source media file.
-             * @param destinationUri Content uri for the destination media file.
-             * @param videoFormat MediaFormat containing the settings that client wants override in
-             *                    the original video's video track.
-             * @throws IllegalArgumentException if videoFormat is invalid.
-             */
-            public Builder(@NonNull Uri sourceUri, @NonNull Uri destinationUri,
-                    @NonNull MediaFormat videoFormat) {
-                super(TRANSCODING_TYPE_VIDEO, sourceUri, destinationUri);
-                setVideoTrackFormat(videoFormat);
-            }
-
-            @Override
-            @NonNull
-            public Builder setClientUid(int uid) {
-                super.setClientUid(uid);
-                return self();
-            }
-
-            @Override
-            @NonNull
-            public Builder setClientPid(int pid) {
-                super.setClientPid(pid);
-                return self();
-            }
-
-            @Override
-            @NonNull
-            public Builder setSourceFileDescriptor(@NonNull ParcelFileDescriptor fd) {
-                super.setSourceFileDescriptor(fd);
-                return self();
-            }
-
-            @Override
-            @NonNull
-            public Builder setDestinationFileDescriptor(@NonNull ParcelFileDescriptor fd) {
-                super.setDestinationFileDescriptor(fd);
-                return self();
-            }
-
-            private void setVideoTrackFormat(@NonNull MediaFormat videoFormat) {
-                if (videoFormat == null) {
-                    throw new IllegalArgumentException("videoFormat must not be null");
-                }
-
-                // Check if the MediaFormat is for video by looking at the MIME type.
-                String mime = videoFormat.containsKey(MediaFormat.KEY_MIME)
-                        ? videoFormat.getString(MediaFormat.KEY_MIME) : null;
-                if (mime == null || !mime.startsWith("video/")) {
-                    throw new IllegalArgumentException("Invalid video format: wrong mime type");
-                }
-
-                mVideoTrackFormat = videoFormat;
-            }
-
-            /**
-             * @return a new {@link TranscodingRequest} instance successfully initialized
-             * with all the parameters set on this <code>Builder</code>.
-             * @throws UnsupportedOperationException if the parameters set on the
-             *                                       <code>Builder</code> were incompatible, or
-             *                                       if they are not supported by the
-             *                                       device.
-             */
-            @NonNull
-            public VideoTranscodingRequest build() {
-                return new VideoTranscodingRequest(this);
-            }
-
-            @Override
-            VideoTranscodingRequest.Builder self() {
-                return this;
-            }
-        }
-    }
-
-    /**
-     * Handle to an enqueued transcoding operation. An instance of this class represents a single
-     * enqueued transcoding operation. The caller can use that instance to query the status or
-     * progress, and to get the result once the operation has completed.
-     */
-    public static final class TranscodingSession {
-        /** The session is enqueued but not yet running. */
-        public static final int STATUS_PENDING = 1;
-        /** The session is currently running. */
-        public static final int STATUS_RUNNING = 2;
-        /** The session is finished. */
-        public static final int STATUS_FINISHED = 3;
-        /** The session is paused. */
-        public static final int STATUS_PAUSED = 4;
-
-        /** @hide */
-        @IntDef(prefix = { "STATUS_" }, value = {
-                STATUS_PENDING,
-                STATUS_RUNNING,
-                STATUS_FINISHED,
-                STATUS_PAUSED,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Status {}
-
-        /** The session does not have a result yet. */
-        public static final int RESULT_NONE = 1;
-        /** The session completed successfully. */
-        public static final int RESULT_SUCCESS = 2;
-        /** The session encountered an error while running. */
-        public static final int RESULT_ERROR = 3;
-        /** The session was canceled by the caller. */
-        public static final int RESULT_CANCELED = 4;
-
-        /** @hide */
-        @IntDef(prefix = { "RESULT_" }, value = {
-                RESULT_NONE,
-                RESULT_SUCCESS,
-                RESULT_ERROR,
-                RESULT_CANCELED,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Result {}
-
-
-        // The error code exposed here should be in sync with:
-        // frameworks/av/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
-        /** @hide */
-        @IntDef(prefix = { "TRANSCODING_SESSION_ERROR_" }, value = {
-                ERROR_NONE,
-                ERROR_DROPPED_BY_SERVICE,
-                ERROR_SERVICE_DIED})
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface TranscodingSessionErrorCode{}
-        /**
-         * Constant indicating that no error occurred.
-         */
-        public static final int ERROR_NONE = 0;
-
-        /**
-         * Constant indicating that the session is dropped by Transcoding service due to hitting
-         * the limit, e.g. too many back to back transcoding happen in a short time frame.
-         */
-        public static final int ERROR_DROPPED_BY_SERVICE = 1;
-
-        /**
-         * Constant indicating the backing transcoding service is died. Client should enqueue the
-         * the request again.
-         */
-        public static final int ERROR_SERVICE_DIED = 2;
-
-        /** Listener that gets notified when the progress changes. */
-        @FunctionalInterface
-        public interface OnProgressUpdateListener {
-            /**
-             * Called when the progress changes. The progress is in percentage between 0 and 1,
-             * where 0 means the session has not yet started and 100 means that it has finished.
-             *
-             * @param session      The session associated with the progress.
-             * @param progress The new progress ranging from 0 ~ 100 inclusive.
-             */
-            void onProgressUpdate(@NonNull TranscodingSession session,
-                    @IntRange(from = 0, to = 100) int progress);
-        }
-
-        private final MediaTranscodingManager mManager;
-        private Executor mListenerExecutor;
-        private OnTranscodingFinishedListener mListener;
-        private int mSessionId = -1;
-        // Lock for internal state.
-        private final Object mLock = new Object();
-        @GuardedBy("mLock")
-        private Executor mProgressUpdateExecutor = null;
-        @GuardedBy("mLock")
-        private OnProgressUpdateListener mProgressUpdateListener = null;
-        @GuardedBy("mLock")
-        private int mProgress = 0;
-        @GuardedBy("mLock")
-        private int mProgressUpdateInterval = 0;
-        @GuardedBy("mLock")
-        private @Status int mStatus = STATUS_PENDING;
-        @GuardedBy("mLock")
-        private @Result int mResult = RESULT_NONE;
-        @GuardedBy("mLock")
-        private @TranscodingSessionErrorCode int mErrorCode = ERROR_NONE;
-        @GuardedBy("mLock")
-        private boolean mHasRetried = false;
-        // The original request that associated with this session.
-        private final TranscodingRequest mRequest;
-
-        private TranscodingSession(
-                @NonNull MediaTranscodingManager manager,
-                @NonNull TranscodingRequest request,
-                @NonNull TranscodingSessionParcel parcel,
-                @NonNull @CallbackExecutor Executor executor,
-                @NonNull OnTranscodingFinishedListener listener) {
-            Objects.requireNonNull(manager, "manager must not be null");
-            Objects.requireNonNull(parcel, "parcel must not be null");
-            Objects.requireNonNull(executor, "listenerExecutor must not be null");
-            Objects.requireNonNull(listener, "listener must not be null");
-            mManager = manager;
-            mSessionId = parcel.sessionId;
-            mListenerExecutor = executor;
-            mListener = listener;
-            mRequest = request;
-        }
-
-        /**
-         * Set a progress listener.
-         * @param executor The executor on which listener will be invoked.
-         * @param listener The progress listener.
-         */
-        public void setOnProgressUpdateListener(
-                @NonNull @CallbackExecutor Executor executor,
-                @Nullable OnProgressUpdateListener listener) {
-            synchronized (mLock) {
-                Objects.requireNonNull(executor, "listenerExecutor must not be null");
-                Objects.requireNonNull(listener, "listener must not be null");
-                mProgressUpdateExecutor = executor;
-                mProgressUpdateListener = listener;
-            }
-        }
-
-        private void updateStatusAndResult(@Status int sessionStatus,
-                @Result int sessionResult, @TranscodingSessionErrorCode int errorCode) {
-            synchronized (mLock) {
-                mStatus = sessionStatus;
-                mResult = sessionResult;
-                mErrorCode = errorCode;
-            }
-        }
-
-        /**
-         * Retrieve the error code associated with the RESULT_ERROR.
-         */
-        public @TranscodingSessionErrorCode int getErrorCode() {
-            synchronized (mLock) {
-                return mErrorCode;
-            }
-        }
-
-        /**
-         * Resubmit the transcoding session to the service.
-         * Note that only the session that fails or gets cancelled could be retried and each session
-         * could be retried only once. After that, Client need to enqueue a new request if they want
-         * to try again.
-         *
-         * @return true if successfully resubmit the job to service. False otherwise.
-         * @throws UnsupportedOperationException if the retry could not be fulfilled.
-         * @hide
-         */
-        public boolean retry() {
-            return retryInternal(true /*setHasRetried*/);
-        }
-
-        // TODO(hkuang): Add more test for it.
-        private boolean retryInternal(boolean setHasRetried) {
-            synchronized (mLock) {
-                if (mStatus == STATUS_PENDING || mStatus == STATUS_RUNNING) {
-                    throw new UnsupportedOperationException(
-                            "Failed to retry as session is in processing");
-                }
-
-                if (mHasRetried) {
-                    throw new UnsupportedOperationException("Session has been retried already");
-                }
-
-                // Get the client interface.
-                ITranscodingClient client = mManager.getTranscodingClient();
-                if (client == null) {
-                    Log.e(TAG, "Service rebooting. Try again later");
-                    return false;
-                }
-
-                synchronized (mManager.mPendingTranscodingSessions) {
-                    try {
-                        // Submits the request to MediaTranscoding service.
-                        TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel();
-                        if (!client.submitRequest(mRequest.writeToParcel(mManager.mContext),
-                                                  sessionParcel)) {
-                            mHasRetried = true;
-                            throw new UnsupportedOperationException("Failed to enqueue request");
-                        }
-
-                        // Replace the old session id wit the new one.
-                        mSessionId = sessionParcel.sessionId;
-                        // Adds the new session back into pending sessions.
-                        mManager.mPendingTranscodingSessions.put(mSessionId, this);
-                    } catch (RemoteException re) {
-                        return false;
-                    }
-                    mStatus = STATUS_PENDING;
-                    mHasRetried = setHasRetried ? true : false;
-                }
-            }
-            return true;
-        }
-
-        /**
-         * Cancels the transcoding session and notify the listener.
-         * If the session happened to finish before being canceled this call is effectively a no-op
-         * and will not update the result in that case.
-         */
-        public void cancel() {
-            synchronized (mLock) {
-                // Check if the session is finished already.
-                if (mStatus != STATUS_FINISHED) {
-                    try {
-                        ITranscodingClient client = mManager.getTranscodingClient();
-                        // The client may be gone.
-                        if (client != null) {
-                            client.cancelSession(mSessionId);
-                        }
-                    } catch (RemoteException re) {
-                        //TODO(hkuang): Find out what to do if failing to cancel the session.
-                        Log.e(TAG, "Failed to cancel the session due to exception:  " + re);
-                    }
-                    mStatus = STATUS_FINISHED;
-                    mResult = RESULT_CANCELED;
-
-                    // Notifies client the session is canceled.
-                    mListenerExecutor.execute(() -> mListener.onTranscodingFinished(this));
-                }
-            }
-        }
-
-        /**
-         * Gets the progress of the transcoding session. The progress is between 0 and 100, where 0
-         * means that the session has not yet started and 100 means that it is finished. For the
-         * cancelled session, the progress will be the last updated progress before it is cancelled.
-         * @return The progress.
-         */
-        @IntRange(from = 0, to = 100)
-        public int getProgress() {
-            synchronized (mLock) {
-                return mProgress;
-            }
-        }
-
-        /**
-         * Gets the status of the transcoding session.
-         * @return The status.
-         */
-        public @Status int getStatus() {
-            synchronized (mLock) {
-                return mStatus;
-            }
-        }
-
-        /**
-         * Adds a client uid that is also waiting for this transcoding session.
-         * <p>
-         * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could add the
-         * uid. Note that the permission check happens on the service side upon starting the
-         * transcoding. If the client does not have the permission, the transcoding will fail.
-         * @param uid  the additional client uid to be added.
-         * @return true if successfully added, false otherwise.
-         */
-        public boolean addClientUid(int uid) {
-            if (uid < 0) {
-                throw new IllegalArgumentException("Invalid Uid");
-            }
-
-            // Get the client interface.
-            ITranscodingClient client = mManager.getTranscodingClient();
-            if (client == null) {
-                Log.e(TAG, "Service is dead...");
-                return false;
-            }
-
-            try {
-                if (!client.addClientUid(mSessionId, uid)) {
-                    Log.e(TAG, "Failed to add client uid");
-                    return false;
-                }
-            } catch (Exception ex) {
-                Log.e(TAG, "Failed to get client uids due to " + ex);
-                return false;
-            }
-            return true;
-        }
-
-        /**
-         * Query all the client that waiting for this transcoding session
-         * @return a list containing all the client uids.
-         */
-        @NonNull
-        public List<Integer> getClientUids() {
-            List<Integer> uidList = new ArrayList<Integer>();
-
-            // Get the client interface.
-            ITranscodingClient client = mManager.getTranscodingClient();
-            if (client == null) {
-                Log.e(TAG, "Service is dead...");
-                return uidList;
-            }
-
-            try {
-                int[] clientUids  = client.getClientUids(mSessionId);
-                for (int i : clientUids) {
-                    uidList.add(i);
-                }
-            } catch (Exception ex) {
-                Log.e(TAG, "Failed to get client uids due to " + ex);
-            }
-
-            return uidList;
-        }
-
-        /**
-         * Gets sessionId of the transcoding session.
-         * @return session id.
-         */
-        public int getSessionId() {
-            return mSessionId;
-        }
-
-        /**
-         * Gets the result of the transcoding session.
-         * @return The result.
-         */
-        public @Result int getResult() {
-            synchronized (mLock) {
-                return mResult;
-            }
-        }
-
-        @Override
-        public String toString() {
-            String result;
-            String status;
-
-            switch (mResult) {
-                case RESULT_NONE:
-                    result = "RESULT_NONE";
-                    break;
-                case RESULT_SUCCESS:
-                    result = "RESULT_SUCCESS";
-                    break;
-                case RESULT_ERROR:
-                    result = "RESULT_ERROR(" + mErrorCode + ")";
-                    break;
-                case RESULT_CANCELED:
-                    result = "RESULT_CANCELED";
-                    break;
-                default:
-                    result = String.valueOf(mResult);
-                    break;
-            }
-
-            switch (mStatus) {
-                case STATUS_PENDING:
-                    status = "STATUS_PENDING";
-                    break;
-                case STATUS_PAUSED:
-                    status = "STATUS_PAUSED";
-                    break;
-                case STATUS_RUNNING:
-                    status = "STATUS_RUNNING";
-                    break;
-                case STATUS_FINISHED:
-                    status = "STATUS_FINISHED";
-                    break;
-                default:
-                    status = String.valueOf(mStatus);
-                    break;
-            }
-            return String.format(" session: {id: %d, status: %s, result: %s, progress: %d}",
-                    mSessionId, status, result, mProgress);
-        }
-
-        private void updateProgress(int newProgress) {
-            synchronized (mLock) {
-                mProgress = newProgress;
-            }
-        }
-
-        private void updateStatus(int newStatus) {
-            synchronized (mLock) {
-                mStatus = newStatus;
-            }
-        }
-    }
-
-    private ITranscodingClient getTranscodingClient() {
-        synchronized (mLock) {
-            return mTranscodingClient;
-        }
-    }
-
-    /**
-     * Enqueues a TranscodingRequest for execution.
-     * <p> Upon successfully accepting the request, MediaTranscodingManager will return a
-     * {@link TranscodingSession} to the client. Client should use {@link TranscodingSession} to
-     * track the progress and get the result.
-     * <p> MediaTranscodingManager will return null if fails to accept the request due to service
-     * rebooting. Client could retry again after receiving null.
-     *
-     * @param transcodingRequest The TranscodingRequest to enqueue.
-     * @param listenerExecutor   Executor on which the listener is notified.
-     * @param listener           Listener to get notified when the transcoding session is finished.
-     * @return A TranscodingSession for this operation.
-     * @throws UnsupportedOperationException if the request could not be fulfilled.
-     */
-    @Nullable
-    public TranscodingSession enqueueRequest(
-            @NonNull TranscodingRequest transcodingRequest,
-            @NonNull @CallbackExecutor Executor listenerExecutor,
-            @NonNull OnTranscodingFinishedListener listener) {
-        Log.i(TAG, "enqueueRequest called.");
-        Objects.requireNonNull(transcodingRequest, "transcodingRequest must not be null");
-        Objects.requireNonNull(listenerExecutor, "listenerExecutor must not be null");
-        Objects.requireNonNull(listener, "listener must not be null");
-
-        // Converts the request to TranscodingRequestParcel.
-        TranscodingRequestParcel requestParcel = transcodingRequest.writeToParcel(mContext);
-
-        Log.i(TAG, "Getting transcoding request " + transcodingRequest.getSourceUri());
-
-        // Submits the request to MediaTranscoding service.
-        try {
-            TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel();
-            // Synchronizes the access to mPendingTranscodingSessions to make sure the session Id is
-            // inserted in the mPendingTranscodingSessions in the callback handler.
-            synchronized (mPendingTranscodingSessions) {
-                synchronized (mLock) {
-                    if (mTranscodingClient == null) {
-                        // Try to register with the service again.
-                        IMediaTranscodingService service = getService(false /*retry*/);
-                        if (service == null) {
-                            Log.w(TAG, "Service rebooting. Try again later");
-                            return null;
-                        }
-                        mTranscodingClient = registerClient(service);
-                        // If still fails, throws an exception to tell client to try later.
-                        if (mTranscodingClient == null) {
-                            Log.w(TAG, "Service rebooting. Try again later");
-                            return null;
-                        }
-                    }
-
-                    if (!mTranscodingClient.submitRequest(requestParcel, sessionParcel)) {
-                        throw new UnsupportedOperationException("Failed to enqueue request");
-                    }
-                }
-
-                // Wraps the TranscodingSessionParcel into a TranscodingSession and returns it to
-                // client for tracking.
-                TranscodingSession session = new TranscodingSession(this, transcodingRequest,
-                        sessionParcel,
-                        listenerExecutor,
-                        listener);
-
-                // Adds the new session into pending sessions.
-                mPendingTranscodingSessions.put(session.getSessionId(), session);
-                return session;
-            }
-        } catch (RemoteException ex) {
-            Log.w(TAG, "Service rebooting. Try again later");
-            return null;
-        } catch (ServiceSpecificException ex) {
-            throw new UnsupportedOperationException(
-                    "Failed to submit request to Transcoding service. Error: " + ex);
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/ProxyDataSourceCallback.java b/apex/media/framework/java/android/media/ProxyDataSourceCallback.java
deleted file mode 100644
index 14d3ce8..0000000
--- a/apex/media/framework/java/android/media/ProxyDataSourceCallback.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.ParcelFileDescriptor;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * A DataSourceCallback that is backed by a ParcelFileDescriptor.
- */
-class ProxyDataSourceCallback extends DataSourceCallback {
-    private static final String TAG = "TestDataSourceCallback";
-
-    ParcelFileDescriptor mPFD;
-    FileDescriptor mFD;
-
-    ProxyDataSourceCallback(ParcelFileDescriptor pfd) throws IOException {
-        mPFD = pfd.dup();
-        mFD = mPFD.getFileDescriptor();
-    }
-
-    @Override
-    public synchronized int readAt(long position, byte[] buffer, int offset, int size)
-            throws IOException {
-        try {
-            Os.lseek(mFD, position, OsConstants.SEEK_SET);
-            int ret = Os.read(mFD, buffer, offset, size);
-            return (ret == 0) ? END_OF_STREAM : ret;
-        } catch (ErrnoException e) {
-            throw new IOException(e);
-        }
-    }
-
-    @Override
-    public synchronized long getSize() throws IOException {
-        return mPFD.getStatSize();
-    }
-
-    @Override
-    public synchronized void close() {
-        try {
-            mPFD.close();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to close the PFD.", e);
-        }
-    }
-}
-
diff --git a/apex/media/framework/java/android/media/RoutingDelegate.java b/apex/media/framework/java/android/media/RoutingDelegate.java
deleted file mode 100644
index 2359813..0000000
--- a/apex/media/framework/java/android/media/RoutingDelegate.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Handler;
-
-class RoutingDelegate implements AudioRouting.OnRoutingChangedListener {
-    private AudioRouting mAudioRouting;
-    private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
-    private Handler mHandler;
-
-    RoutingDelegate(final AudioRouting audioRouting,
-                    final AudioRouting.OnRoutingChangedListener listener,
-                    Handler handler) {
-        mAudioRouting = audioRouting;
-        mOnRoutingChangedListener = listener;
-        mHandler = handler;
-    }
-
-    public AudioRouting.OnRoutingChangedListener getListener() {
-        return mOnRoutingChangedListener;
-    }
-
-    public Handler getHandler() {
-        return mHandler;
-    }
-
-    @Override
-    public void onRoutingChanged(AudioRouting router) {
-        if (mOnRoutingChangedListener != null) {
-            mOnRoutingChangedListener.onRoutingChanged(mAudioRouting);
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/Session2Command.java b/apex/media/framework/java/android/media/Session2Command.java
deleted file mode 100644
index 26f4568..0000000
--- a/apex/media/framework/java/android/media/Session2Command.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.util.Objects;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
- * <p>
- * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
- * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
- * {@link #getCustomAction()} shouldn't be {@code null}.
- * <p>
- * Refer to the
- * <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
- * class for the list of valid commands.
- */
-public final class Session2Command implements Parcelable {
-    /**
-     * Command code for the custom command which can be defined by string action in the
-     * {@link Session2Command}.
-     */
-    public static final int COMMAND_CODE_CUSTOM = 0;
-
-    public static final @android.annotation.NonNull Parcelable.Creator<Session2Command> CREATOR =
-            new Parcelable.Creator<Session2Command>() {
-                @Override
-                public Session2Command createFromParcel(Parcel in) {
-                    return new Session2Command(in);
-                }
-
-                @Override
-                public Session2Command[] newArray(int size) {
-                    return new Session2Command[size];
-                }
-            };
-
-    private final int mCommandCode;
-    // Nonnull if it's custom command
-    private final String mCustomAction;
-    private final Bundle mCustomExtras;
-
-    /**
-     * Constructor for creating a command predefined in AndroidX media2.
-     *
-     * @param commandCode A command code for a command predefined in AndroidX media2.
-     */
-    public Session2Command(int commandCode) {
-        if (commandCode == COMMAND_CODE_CUSTOM) {
-            throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
-        }
-        mCommandCode = commandCode;
-        mCustomAction = null;
-        mCustomExtras = null;
-    }
-
-    /**
-     * Constructor for creating a custom command.
-     *
-     * @param action The action of this custom command.
-     * @param extras An extra bundle for this custom command.
-     */
-    public Session2Command(@NonNull String action, @Nullable Bundle extras) {
-        if (action == null) {
-            throw new IllegalArgumentException("action shouldn't be null");
-        }
-        mCommandCode = COMMAND_CODE_CUSTOM;
-        mCustomAction = action;
-        mCustomExtras = extras;
-    }
-
-    /**
-     * Used by parcelable creator.
-     */
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    Session2Command(Parcel in) {
-        mCommandCode = in.readInt();
-        mCustomAction = in.readString();
-        mCustomExtras = in.readBundle();
-    }
-
-    /**
-     * Gets the command code of a predefined command.
-     * This will return {@link #COMMAND_CODE_CUSTOM} for a custom command.
-     */
-    public int getCommandCode() {
-        return mCommandCode;
-    }
-
-    /**
-     * Gets the action of a custom command.
-     * This will return {@code null} for a predefined command.
-     */
-    @Nullable
-    public String getCustomAction() {
-        return mCustomAction;
-    }
-
-    /**
-     * Gets the extra bundle of a custom command.
-     * This will return {@code null} for a predefined command.
-     */
-    @Nullable
-    public Bundle getCustomExtras() {
-        return mCustomExtras;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        if (dest == null) {
-            throw new IllegalArgumentException("parcel shouldn't be null");
-        }
-        dest.writeInt(mCommandCode);
-        dest.writeString(mCustomAction);
-        dest.writeBundle(mCustomExtras);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (!(obj instanceof Session2Command)) {
-            return false;
-        }
-        Session2Command other = (Session2Command) obj;
-        return mCommandCode == other.mCommandCode
-                && TextUtils.equals(mCustomAction, other.mCustomAction);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mCustomAction, mCommandCode);
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Contains the result of {@link Session2Command}.
-     */
-    public static final class Result {
-        private final int mResultCode;
-        private final Bundle mResultData;
-
-        /**
-         * Result code representing that the command is skipped or canceled. For an example, a seek
-         * command can be skipped if it is followed by another seek command.
-         */
-        public static final int RESULT_INFO_SKIPPED = 1;
-
-        /**
-         * Result code representing that the command is successfully completed.
-         */
-        public static final int RESULT_SUCCESS = 0;
-
-        /**
-         * Result code represents that call is ended with an unknown error.
-         */
-        public static final int RESULT_ERROR_UNKNOWN_ERROR = -1;
-
-        /**
-         * Constructor of {@link Result}.
-         *
-         * @param resultCode result code
-         * @param resultData result data
-         */
-        public Result(int resultCode, @Nullable Bundle resultData) {
-            mResultCode = resultCode;
-            mResultData = resultData;
-        }
-
-        /**
-         * Returns the result code.
-         */
-        public int getResultCode() {
-            return mResultCode;
-        }
-
-        /**
-         * Returns the result data.
-         */
-        @Nullable
-        public Bundle getResultData() {
-            return mResultData;
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/Session2CommandGroup.java b/apex/media/framework/java/android/media/Session2CommandGroup.java
deleted file mode 100644
index 13aabfc..0000000
--- a/apex/media/framework/java/android/media/Session2CommandGroup.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.Session2Command.COMMAND_CODE_CUSTOM;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * A set of {@link Session2Command} which represents a command group.
- */
-public final class Session2CommandGroup implements Parcelable {
-    private static final String TAG = "Session2CommandGroup";
-
-    public static final @android.annotation.NonNull Parcelable.Creator<Session2CommandGroup>
-            CREATOR = new Parcelable.Creator<Session2CommandGroup>() {
-                @Override
-                public Session2CommandGroup createFromParcel(Parcel in) {
-                    return new Session2CommandGroup(in);
-                }
-
-                @Override
-                public Session2CommandGroup[] newArray(int size) {
-                    return new Session2CommandGroup[size];
-                }
-            };
-
-    Set<Session2Command> mCommands = new HashSet<>();
-
-    /**
-     * Creates a new Session2CommandGroup with commands copied from another object.
-     *
-     * @param commands The collection of commands to copy.
-     */
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    Session2CommandGroup(@Nullable Collection<Session2Command> commands) {
-        if (commands != null) {
-            mCommands.addAll(commands);
-        }
-    }
-
-    /**
-     * Used by parcelable creator.
-     */
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    Session2CommandGroup(Parcel in) {
-        Parcelable[] commands = in.readParcelableArray(Session2Command.class.getClassLoader());
-        if (commands != null) {
-            for (Parcelable command : commands) {
-                mCommands.add((Session2Command) command);
-            }
-        }
-    }
-
-    /**
-     * Checks whether this command group has a command that matches given {@code command}.
-     *
-     * @param command A command to find. Shouldn't be {@code null}.
-     */
-    public boolean hasCommand(@NonNull Session2Command command) {
-        if (command == null) {
-            throw new IllegalArgumentException("command shouldn't be null");
-        }
-        return mCommands.contains(command);
-    }
-
-    /**
-     * Checks whether this command group has a command that matches given {@code commandCode}.
-     *
-     * @param commandCode A command code to find.
-     *                    Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}.
-     */
-    public boolean hasCommand(int commandCode) {
-        if (commandCode == COMMAND_CODE_CUSTOM) {
-            throw new IllegalArgumentException("Use hasCommand(Command) for custom command");
-        }
-        for (Session2Command command : mCommands) {
-            if (command.getCommandCode() == commandCode) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Gets all commands of this command group.
-     */
-    @NonNull
-    public Set<Session2Command> getCommands() {
-        return new HashSet<>(mCommands);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        if (dest == null) {
-            throw new IllegalArgumentException("parcel shouldn't be null");
-        }
-        dest.writeParcelableArray(mCommands.toArray(new Session2Command[0]), 0);
-    }
-
-    /**
-     * This API is not generally intended for third party application developers.
-     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
-     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
-     * Library</a> for consistent behavior across all devices.
-     * <p>
-     * Builds a {@link Session2CommandGroup} object.
-     */
-    public static final class Builder {
-        private Set<Session2Command> mCommands;
-
-        public Builder() {
-            mCommands = new HashSet<>();
-        }
-
-        /**
-         * Creates a new builder for {@link Session2CommandGroup} with commands copied from another
-         * {@link Session2CommandGroup} object.
-         * @param commandGroup
-         */
-        public Builder(@NonNull Session2CommandGroup commandGroup) {
-            if (commandGroup == null) {
-                throw new IllegalArgumentException("command group shouldn't be null");
-            }
-            mCommands = commandGroup.getCommands();
-        }
-
-        /**
-         * Adds a command to this command group.
-         *
-         * @param command A command to add. Shouldn't be {@code null}.
-         */
-        @NonNull
-        public Builder addCommand(@NonNull Session2Command command) {
-            if (command == null) {
-                throw new IllegalArgumentException("command shouldn't be null");
-            }
-            mCommands.add(command);
-            return this;
-        }
-
-        /**
-         * Removes a command from this group which matches given {@code command}.
-         *
-         * @param command A command to find. Shouldn't be {@code null}.
-         */
-        @NonNull
-        public Builder removeCommand(@NonNull Session2Command command) {
-            if (command == null) {
-                throw new IllegalArgumentException("command shouldn't be null");
-            }
-            mCommands.remove(command);
-            return this;
-        }
-
-        /**
-         * Builds {@link Session2CommandGroup}.
-         *
-         * @return a new {@link Session2CommandGroup}.
-         */
-        @NonNull
-        public Session2CommandGroup build() {
-            return new Session2CommandGroup(mCommands);
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/Session2Link.java b/apex/media/framework/java/android/media/Session2Link.java
deleted file mode 100644
index 6e550e8..0000000
--- a/apex/media/framework/java/android/media/Session2Link.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import java.util.Objects;
-
-/**
- * Handles incoming commands from {@link MediaController2} to {@link MediaSession2}.
- * @hide
- */
-// @SystemApi
-public final class Session2Link implements Parcelable {
-    private static final String TAG = "Session2Link";
-    private static final boolean DEBUG = MediaSession2.DEBUG;
-
-    public static final @android.annotation.NonNull Parcelable.Creator<Session2Link> CREATOR =
-            new Parcelable.Creator<Session2Link>() {
-                @Override
-                public Session2Link createFromParcel(Parcel in) {
-                    return new Session2Link(in);
-                }
-
-                @Override
-                public Session2Link[] newArray(int size) {
-                    return new Session2Link[size];
-                }
-            };
-
-    private final MediaSession2 mSession;
-    private final IMediaSession2 mISession;
-
-    public Session2Link(MediaSession2 session) {
-        mSession = session;
-        mISession = new Session2Stub();
-    }
-
-    Session2Link(Parcel in) {
-        mSession = null;
-        mISession = IMediaSession2.Stub.asInterface(in.readStrongBinder());
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(mISession.asBinder());
-    }
-
-    @Override
-    public int hashCode() {
-        return mISession.asBinder().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof Session2Link)) {
-            return false;
-        }
-        Session2Link other = (Session2Link) obj;
-        return Objects.equals(mISession.asBinder(), other.mISession.asBinder());
-    }
-
-    /** Link to death with mISession */
-    public void linkToDeath(@NonNull IBinder.DeathRecipient recipient, int flags) {
-        if (mISession != null) {
-            try {
-                mISession.asBinder().linkToDeath(recipient, flags);
-            } catch (RemoteException e) {
-                if (DEBUG) {
-                    Log.d(TAG, "Session died too early.", e);
-                }
-            }
-        }
-    }
-
-    /** Unlink to death with mISession */
-    public boolean unlinkToDeath(@NonNull IBinder.DeathRecipient recipient, int flags) {
-        if (mISession != null) {
-            return mISession.asBinder().unlinkToDeath(recipient, flags);
-        }
-        return true;
-    }
-
-    /** Interface method for IMediaSession2.connect */
-    public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) {
-        try {
-            mISession.connect(caller, seq, connectionRequest);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaSession2.disconnect */
-    public void disconnect(final Controller2Link caller, int seq) {
-        try {
-            mISession.disconnect(caller, seq);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaSession2.sendSessionCommand */
-    public void sendSessionCommand(final Controller2Link caller, final int seq,
-            final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
-        try {
-            mISession.sendSessionCommand(caller, seq, command, args, resultReceiver);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Interface method for IMediaSession2.sendSessionCommand */
-    public void cancelSessionCommand(final Controller2Link caller, final int seq) {
-        try {
-            mISession.cancelSessionCommand(caller, seq);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /** Stub implementation for IMediaSession2.connect */
-    public void onConnect(final Controller2Link caller, int pid, int uid, int seq,
-            Bundle connectionRequest) {
-        mSession.onConnect(caller, pid, uid, seq, connectionRequest);
-    }
-
-    /** Stub implementation for IMediaSession2.disconnect */
-    public void onDisconnect(final Controller2Link caller, int seq) {
-        mSession.onDisconnect(caller, seq);
-    }
-
-    /** Stub implementation for IMediaSession2.sendSessionCommand */
-    public void onSessionCommand(final Controller2Link caller, final int seq,
-            final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
-        mSession.onSessionCommand(caller, seq, command, args, resultReceiver);
-    }
-
-    /** Stub implementation for IMediaSession2.cancelSessionCommand */
-    public void onCancelCommand(final Controller2Link caller, final int seq) {
-        mSession.onCancelCommand(caller, seq);
-    }
-
-    private class Session2Stub extends IMediaSession2.Stub {
-        @Override
-        public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) {
-            if (caller == null || connectionRequest == null) {
-                return;
-            }
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Session2Link.this.onConnect(caller, pid, uid, seq, connectionRequest);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void disconnect(final Controller2Link caller, int seq) {
-            if (caller == null) {
-                return;
-            }
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Session2Link.this.onDisconnect(caller, seq);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void sendSessionCommand(final Controller2Link caller, final int seq,
-                final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
-            if (caller == null) {
-                return;
-            }
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void cancelSessionCommand(final Controller2Link caller, final int seq) {
-            if (caller == null) {
-                return;
-            }
-            final long token = Binder.clearCallingIdentity();
-            try {
-                Session2Link.this.onCancelCommand(caller, seq);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-    }
-}
diff --git a/apex/media/framework/java/android/media/Session2Token.java b/apex/media/framework/java/android/media/Session2Token.java
deleted file mode 100644
index aae2e1b..0000000
--- a/apex/media/framework/java/android/media/Session2Token.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Represents an ongoing {@link MediaSession2} or a {@link MediaSession2Service}.
- * If it's representing a session service, it may not be ongoing.
- * <p>
- * This may be passed to apps by the session owner to allow them to create a
- * {@link MediaController2} to communicate with the session.
- * <p>
- * It can be also obtained by {@link android.media.session.MediaSessionManager}.
- */
-public final class Session2Token implements Parcelable {
-    private static final String TAG = "Session2Token";
-
-    public static final @android.annotation.NonNull Creator<Session2Token> CREATOR =
-            new Creator<Session2Token>() {
-                @Override
-                public Session2Token createFromParcel(Parcel p) {
-                    return new Session2Token(p);
-                }
-
-                @Override
-                public Session2Token[] newArray(int size) {
-                    return new Session2Token[size];
-                }
-            };
-
-    /**
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE})
-    public @interface TokenType {
-    }
-
-    /**
-     * Type for {@link MediaSession2}.
-     */
-    public static final int TYPE_SESSION = 0;
-
-    /**
-     * Type for {@link MediaSession2Service}.
-     */
-    public static final int TYPE_SESSION_SERVICE = 1;
-
-    private final int mUid;
-    @TokenType
-    private final int mType;
-    private final String mPackageName;
-    private final String mServiceName;
-    private final Session2Link mSessionLink;
-    private final ComponentName mComponentName;
-    private final Bundle mExtras;
-
-    /**
-     * Constructor for the token with type {@link #TYPE_SESSION_SERVICE}.
-     *
-     * @param context The context.
-     * @param serviceComponent The component name of the service.
-     */
-    public Session2Token(@NonNull Context context, @NonNull ComponentName serviceComponent) {
-        if (context == null) {
-            throw new IllegalArgumentException("context shouldn't be null");
-        }
-        if (serviceComponent == null) {
-            throw new IllegalArgumentException("serviceComponent shouldn't be null");
-        }
-
-        final PackageManager manager = context.getPackageManager();
-        final int uid = getUid(manager, serviceComponent.getPackageName());
-
-        if (!isInterfaceDeclared(manager, MediaSession2Service.SERVICE_INTERFACE,
-                serviceComponent)) {
-            Log.w(TAG, serviceComponent + " doesn't implement MediaSession2Service.");
-        }
-        mComponentName = serviceComponent;
-        mPackageName = serviceComponent.getPackageName();
-        mServiceName = serviceComponent.getClassName();
-        mUid = uid;
-        mType = TYPE_SESSION_SERVICE;
-        mSessionLink = null;
-        mExtras = Bundle.EMPTY;
-    }
-
-    Session2Token(int uid, int type, String packageName, Session2Link sessionLink,
-            @NonNull Bundle tokenExtras) {
-        mUid = uid;
-        mType = type;
-        mPackageName = packageName;
-        mServiceName = null;
-        mComponentName = null;
-        mSessionLink = sessionLink;
-        mExtras = tokenExtras;
-    }
-
-    Session2Token(Parcel in) {
-        mUid = in.readInt();
-        mType = in.readInt();
-        mPackageName = in.readString();
-        mServiceName = in.readString();
-        mSessionLink = in.readParcelable(null);
-        mComponentName = ComponentName.unflattenFromString(in.readString());
-
-        Bundle extras = in.readBundle();
-        if (extras == null) {
-            Log.w(TAG, "extras shouldn't be null.");
-            extras = Bundle.EMPTY;
-        } else if (MediaSession2.hasCustomParcelable(extras)) {
-            Log.w(TAG, "extras contain custom parcelable. Ignoring.");
-            extras = Bundle.EMPTY;
-        }
-        mExtras = extras;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mUid);
-        dest.writeInt(mType);
-        dest.writeString(mPackageName);
-        dest.writeString(mServiceName);
-        dest.writeParcelable(mSessionLink, flags);
-        dest.writeString(mComponentName == null ? "" : mComponentName.flattenToString());
-        dest.writeBundle(mExtras);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mType, mUid, mPackageName, mServiceName, mSessionLink);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof Session2Token)) {
-            return false;
-        }
-        Session2Token other = (Session2Token) obj;
-        return mUid == other.mUid
-                && TextUtils.equals(mPackageName, other.mPackageName)
-                && TextUtils.equals(mServiceName, other.mServiceName)
-                && mType == other.mType
-                && Objects.equals(mSessionLink, other.mSessionLink);
-    }
-
-    @Override
-    public String toString() {
-        return "Session2Token {pkg=" + mPackageName + " type=" + mType
-                + " service=" + mServiceName + " Session2Link=" + mSessionLink + "}";
-    }
-
-    /**
-     * @return uid of the session
-     */
-    public int getUid() {
-        return mUid;
-    }
-
-    /**
-     * @return package name of the session
-     */
-    @NonNull
-    public String getPackageName() {
-        return mPackageName;
-    }
-
-    /**
-     * @return service name of the session. Can be {@code null} for {@link #TYPE_SESSION}.
-     */
-    @Nullable
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    /**
-     * @return type of the token
-     * @see #TYPE_SESSION
-     * @see #TYPE_SESSION_SERVICE
-     */
-    public @TokenType int getType() {
-        return mType;
-    }
-
-    /**
-     * @return extras of the token
-     * @see MediaSession2.Builder#setExtras(Bundle)
-     */
-    @NonNull
-    public Bundle getExtras() {
-        return new Bundle(mExtras);
-    }
-
-    Session2Link getSessionLink() {
-        return mSessionLink;
-    }
-
-    private static boolean isInterfaceDeclared(PackageManager manager, String serviceInterface,
-            ComponentName serviceComponent) {
-        Intent serviceIntent = new Intent(serviceInterface);
-        // Use queryIntentServices to find services with MediaSession2Service.SERVICE_INTERFACE.
-        // We cannot use resolveService with intent specified class name, because resolveService
-        // ignores actions if Intent.setClassName() is specified.
-        serviceIntent.setPackage(serviceComponent.getPackageName());
-
-        List<ResolveInfo> list = manager.queryIntentServices(
-                serviceIntent, PackageManager.GET_META_DATA);
-        if (list != null) {
-            for (int i = 0; i < list.size(); i++) {
-                ResolveInfo resolveInfo = list.get(i);
-                if (resolveInfo == null || resolveInfo.serviceInfo == null) {
-                    continue;
-                }
-                if (TextUtils.equals(
-                        resolveInfo.serviceInfo.name, serviceComponent.getClassName())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private static int getUid(PackageManager manager, String packageName) {
-        try {
-            return manager.getApplicationInfo(packageName, 0).uid;
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new IllegalArgumentException("Cannot find package " + packageName);
-        }
-    }
-}
diff --git a/apex/media/framework/jni/android_media_MediaParserJNI.cpp b/apex/media/framework/jni/android_media_MediaParserJNI.cpp
deleted file mode 100644
index c81152c..0000000
--- a/apex/media/framework/jni/android_media_MediaParserJNI.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-#include <media/MediaMetrics.h>
-
-#define JNI_FUNCTION(RETURN_TYPE, NAME, ...)                                               \
-    extern "C" {                                                                           \
-    JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
-                                                                ##__VA_ARGS__);            \
-    }                                                                                      \
-    JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
-                                                                ##__VA_ARGS__)
-
-namespace {
-
-constexpr char kMediaMetricsKey[] = "mediaparser";
-
-constexpr char kAttributeLogSessionId[] = "android.media.mediaparser.logSessionId";
-constexpr char kAttributeParserName[] = "android.media.mediaparser.parserName";
-constexpr char kAttributeCreatedByName[] = "android.media.mediaparser.createdByName";
-constexpr char kAttributeParserPool[] = "android.media.mediaparser.parserPool";
-constexpr char kAttributeLastException[] = "android.media.mediaparser.lastException";
-constexpr char kAttributeResourceByteCount[] = "android.media.mediaparser.resourceByteCount";
-constexpr char kAttributeDurationMillis[] = "android.media.mediaparser.durationMillis";
-constexpr char kAttributeTrackMimeTypes[] = "android.media.mediaparser.trackMimeTypes";
-constexpr char kAttributeTrackCodecs[] = "android.media.mediaparser.trackCodecs";
-constexpr char kAttributeAlteredParameters[] = "android.media.mediaparser.alteredParameters";
-constexpr char kAttributeVideoWidth[] = "android.media.mediaparser.videoWidth";
-constexpr char kAttributeVideoHeight[] = "android.media.mediaparser.videoHeight";
-
-// Util class to handle string resource management.
-class JstringHandle {
-public:
-    JstringHandle(JNIEnv* env, jstring value) : mEnv(env), mJstringValue(value) {
-        mCstringValue = env->GetStringUTFChars(value, /* isCopy= */ nullptr);
-    }
-
-    ~JstringHandle() {
-        if (mCstringValue != nullptr) {
-            mEnv->ReleaseStringUTFChars(mJstringValue, mCstringValue);
-        }
-    }
-
-    [[nodiscard]] const char* value() const {
-        return mCstringValue != nullptr ? mCstringValue : "";
-    }
-
-    JNIEnv* mEnv;
-    jstring mJstringValue;
-    const char* mCstringValue;
-};
-
-} // namespace
-
-JNI_FUNCTION(void, nativeSubmitMetrics, jstring logSessionIdJstring, jstring parserNameJstring,
-             jboolean createdByName, jstring parserPoolJstring, jstring lastExceptionJstring,
-             jlong resourceByteCount, jlong durationMillis, jstring trackMimeTypesJstring,
-             jstring trackCodecsJstring, jstring alteredParameters, jint videoWidth,
-             jint videoHeight) {
-    mediametrics_handle_t item(mediametrics_create(kMediaMetricsKey));
-    mediametrics_setCString(item, kAttributeLogSessionId,
-                            JstringHandle(env, logSessionIdJstring).value());
-    mediametrics_setCString(item, kAttributeParserName,
-                            JstringHandle(env, parserNameJstring).value());
-    mediametrics_setInt32(item, kAttributeCreatedByName, createdByName ? 1 : 0);
-    mediametrics_setCString(item, kAttributeParserPool,
-                            JstringHandle(env, parserPoolJstring).value());
-    mediametrics_setCString(item, kAttributeLastException,
-                            JstringHandle(env, lastExceptionJstring).value());
-    mediametrics_setInt64(item, kAttributeResourceByteCount, resourceByteCount);
-    mediametrics_setInt64(item, kAttributeDurationMillis, durationMillis);
-    mediametrics_setCString(item, kAttributeTrackMimeTypes,
-                            JstringHandle(env, trackMimeTypesJstring).value());
-    mediametrics_setCString(item, kAttributeTrackCodecs,
-                            JstringHandle(env, trackCodecsJstring).value());
-    mediametrics_setCString(item, kAttributeAlteredParameters,
-                            JstringHandle(env, alteredParameters).value());
-    mediametrics_setInt32(item, kAttributeVideoWidth, videoWidth);
-    mediametrics_setInt32(item, kAttributeVideoHeight, videoHeight);
-    mediametrics_selfRecord(item);
-    mediametrics_delete(item);
-}
diff --git a/apex/media/framework/lint-baseline.xml b/apex/media/framework/lint-baseline.xml
deleted file mode 100644
index e1b1450..0000000
--- a/apex/media/framework/lint-baseline.xml
+++ /dev/null
@@ -1,312 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `new android.media.ApplicationMediaCapabilities.Builder`"
-        errorLine1="                            new ApplicationMediaCapabilities.Builder();"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java"
-            line="208"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `new android.media.ApplicationMediaCapabilities.Builder`"
-        errorLine1="        ApplicationMediaCapabilities.Builder builder = new ApplicationMediaCapabilities.Builder();"
-        errorLine2="                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java"
-            line="314"
-            column="56"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.os.RemoteException#rethrowFromSystemServer`"
-        errorLine1="            e.rethrowFromSystemServer();"
-        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaCommunicationManager.java"
-            line="110"
-            column="15"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.os.Parcel#writeParcelableCreator`"
-        errorLine1="        dest.writeParcelableCreator((Parcelable) parcelable);"
-        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParceledListSlice.java"
-            line="77"
-            column="14"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.os.Parcel#readParcelableCreator`"
-        errorLine1="        return from.readParcelableCreator(loader);"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParceledListSlice.java"
-            line="82"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.TrackData#mediaFormat`"
-        errorLine1="            this.mediaFormat = mediaFormat;"
-        errorLine2="            ~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="273"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.TrackData#drmInitData`"
-        errorLine1="            this.drmInitData = drmInitData;"
-        errorLine2="            ~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="274"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            this.timeMicros = timeMicros;"
-        errorLine2="            ~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="295"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            this.position = position;"
-        errorLine2="            ~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="296"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            return &quot;[timeMicros=&quot; + timeMicros + &quot;, position=&quot; + position + &quot;]&quot;;"
-        errorLine2="                                                                 ~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="302"
-            column="66"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            return &quot;[timeMicros=&quot; + timeMicros + &quot;, position=&quot; + position + &quot;]&quot;;"
-        errorLine2="                                    ~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="302"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level R (current min is 29): `android.media.MediaParser.SeekPoint`"
-        errorLine1="            SeekPoint other = (SeekPoint) obj;"
-        errorLine2="                               ~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="313"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
-        errorLine2="                                                     ~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="314"
-            column="54"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
-        errorLine2="                                                                 ~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="314"
-            column="66"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
-        errorLine2="                   ~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="314"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="314"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            int result = (int) timeMicros;"
-        errorLine2="                               ~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="319"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            result = 31 * result + (int) position;"
-        errorLine2="                                         ~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="320"
-            column="42"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
-        errorLine1="    public interface SeekableInputReader extends InputReader {"
-        errorLine2="                                                 ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="352"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level 31 (current min is 29): `android.media.metrics.LogSessionId#LOG_SESSION_ID_NONE`"
-        errorLine1="    @NonNull private LogSessionId mLogSessionId = LogSessionId.LOG_SESSION_ID_NONE;"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1071"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Cast from `SeekableInputReader` to `InputReader` requires API level 30 (current min is 29)"
-        errorLine1="        mExoDataReader.mInputReader = seekableInputReader;"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1201"
-            column="39"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            mPendingSeekPosition = seekPoint.position;"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1287"
-            column="36"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            mPendingSeekTimeMicros = seekPoint.timeMicros;"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1288"
-            column="38"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
-        errorLine1="            mExtractor.seek(seekPoint.position, seekPoint.timeMicros);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1290"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
-        errorLine1="            mExtractor.seek(seekPoint.position, seekPoint.timeMicros);"
-        errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1290"
-            column="49"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level R (current min is 29): `android.media.DrmInitData.SchemeInitData#uuid`"
-        errorLine1="                if (schemeInitData.uuid.equals(schemeUuid)) {"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1579"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
-        errorLine1="    private static final class DataReaderAdapter implements InputReader {"
-        errorLine2="                                                            ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1872"
-            column="61"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
-        errorLine1="    private static final class ParsableByteArrayAdapter implements InputReader {"
-        errorLine2="                                                                   ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
-            line="1905"
-            column="68"/>
-    </issue>
-
-</issues>
diff --git a/apex/media/framework/updatable-media-proguard.flags b/apex/media/framework/updatable-media-proguard.flags
deleted file mode 100644
index 4e7d842..0000000
--- a/apex/media/framework/updatable-media-proguard.flags
+++ /dev/null
@@ -1,2 +0,0 @@
-# Keep all symbols in android.media.
--keep class android.media.* {*;}
diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp
deleted file mode 100644
index 271fc53..0000000
--- a/apex/media/service/Android.bp
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
-    name: "service-media-s-sources",
-    srcs: [
-        "java/**/*.java",
-    ],
-    path: "java",
-    visibility: ["//visibility:private"],
-}
-
-java_sdk_library {
-    name: "service-media-s",
-    permitted_packages: [
-        "com.android.server.media",
-    ],
-    defaults: ["framework-system-server-module-defaults"],
-    srcs: [
-        ":service-media-s-sources",
-    ],
-    libs: [
-        "updatable-media",
-    ],
-    sdk_version: "system_server_current",
-    min_sdk_version: "29", // TODO: We may need to bump this at some point.
-    apex_available: [
-        "com.android.media",
-    ],
-}
diff --git a/apex/media/service/api/current.txt b/apex/media/service/api/current.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/api/removed.txt b/apex/media/service/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/api/system-server-current.txt b/apex/media/service/api/system-server-current.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/system-server-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/api/system-server-removed.txt b/apex/media/service/api/system-server-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/system-server-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
deleted file mode 100644
index ed31aa3..0000000
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.media;
-
-import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.os.UserHandle.ALL;
-import static android.os.UserHandle.getUserHandleForUid;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.media.IMediaCommunicationService;
-import android.media.IMediaCommunicationServiceCallback;
-import android.media.MediaController2;
-import android.media.MediaParceledListSlice;
-import android.media.Session2CommandGroup;
-import android.media.Session2Token;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.SystemService;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.stream.Collectors;
-
-/**
- * A system service that manages {@link android.media.MediaSession2} creations
- * and their ongoing media playback state.
- * @hide
- */
-public class MediaCommunicationService extends SystemService {
-    private static final String TAG = "MediaCommunicationService";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    final Context mContext;
-
-    final Object mLock = new Object();
-    final Handler mHandler = new Handler(Looper.getMainLooper());
-
-    @GuardedBy("mLock")
-    private final SparseIntArray mFullUserIds = new SparseIntArray();
-    @GuardedBy("mLock")
-    private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<>();
-
-    final Executor mRecordExecutor = Executors.newSingleThreadExecutor();
-    @GuardedBy("mLock")
-    final List<CallbackRecord> mCallbackRecords = new ArrayList<>();
-    final NotificationManager mNotificationManager;
-
-    public MediaCommunicationService(Context context) {
-        super(context);
-        mContext = context;
-        mNotificationManager = context.getSystemService(NotificationManager.class);
-    }
-
-    @Override
-    public void onStart() {
-        publishBinderService(Context.MEDIA_COMMUNICATION_SERVICE, new Stub());
-        updateUser();
-    }
-
-    @Override
-    public void onUserStarting(@NonNull TargetUser user) {
-        if (DEBUG) Log.d(TAG, "onUserStarting: " + user);
-        updateUser();
-    }
-
-    @Override
-    public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
-        if (DEBUG) Log.d(TAG, "onUserSwitching: " + to);
-        updateUser();
-    }
-
-    @Override
-    public void onUserStopped(@NonNull TargetUser targetUser) {
-        int userId = targetUser.getUserHandle().getIdentifier();
-
-        if (DEBUG) Log.d(TAG, "onUserStopped: " + userId);
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(userId);
-            if (user != null) {
-                if (user.getFullUserId() == userId) {
-                    user.destroyAllSessions();
-                    mUserRecords.remove(userId);
-                } else {
-                    user.destroySessionsForUser(userId);
-                }
-            }
-        }
-        updateUser();
-    }
-
-    @Nullable
-    CallbackRecord findCallbackRecordLocked(@Nullable IMediaCommunicationServiceCallback callback) {
-        if (callback == null) {
-            return null;
-        }
-        for (CallbackRecord record : mCallbackRecords) {
-            if (Objects.equals(callback.asBinder(), record.mCallback.asBinder())) {
-                return record;
-            }
-        }
-        return null;
-    }
-
-    List<Session2Token> getSession2TokensLocked(int userId) {
-        List<Session2Token> list = new ArrayList<>();
-        if (userId == ALL.getIdentifier()) {
-            int size = mUserRecords.size();
-            for (int i = 0; i < size; i++) {
-                list.addAll(mUserRecords.valueAt(i).getAllSession2Tokens());
-            }
-        } else {
-            FullUserRecord user = getFullUserRecordLocked(userId);
-            if (user != null) {
-                list.addAll(user.getSession2Tokens(userId));
-            }
-        }
-        return list;
-    }
-
-    private FullUserRecord getFullUserRecordLocked(int userId) {
-        int fullUserId = mFullUserIds.get(userId, -1);
-        if (fullUserId < 0) {
-            return null;
-        }
-        return mUserRecords.get(fullUserId);
-    }
-
-    private boolean hasMediaControlPermission(int pid, int uid) {
-        // Check if it's system server or has MEDIA_CONTENT_CONTROL.
-        // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
-        // check here.
-        if (uid == Process.SYSTEM_UID || mContext.checkPermission(
-                android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
-                == PackageManager.PERMISSION_GRANTED) {
-            return true;
-        } else if (DEBUG) {
-            Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
-        }
-        return false;
-    }
-
-    private void updateUser() {
-        UserManager manager = mContext.getSystemService(UserManager.class);
-        List<UserHandle> allUsers = manager.getUserHandles(/*excludeDying=*/false);
-
-        synchronized (mLock) {
-            mFullUserIds.clear();
-            if (allUsers != null) {
-                for (UserHandle user : allUsers) {
-                    UserHandle parent = manager.getProfileParent(user);
-                    if (parent != null) {
-                        mFullUserIds.put(user.getIdentifier(), parent.getIdentifier());
-                    } else {
-                        mFullUserIds.put(user.getIdentifier(), user.getIdentifier());
-                        if (mUserRecords.get(user.getIdentifier()) == null) {
-                            mUserRecords.put(user.getIdentifier(),
-                                    new FullUserRecord(user.getIdentifier()));
-                        }
-                    }
-                }
-            }
-            // Ensure that the current full user exists.
-            int currentFullUserId = ActivityManager.getCurrentUser();
-            FullUserRecord currentFullUserRecord = mUserRecords.get(currentFullUserId);
-            if (currentFullUserRecord == null) {
-                Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
-                currentFullUserRecord = new FullUserRecord(currentFullUserId);
-                mUserRecords.put(currentFullUserId, currentFullUserRecord);
-            }
-            mFullUserIds.put(currentFullUserId, currentFullUserId);
-        }
-    }
-
-    void dispatchSession2Created(Session2Token token) {
-        synchronized (mLock) {
-            for (CallbackRecord record : mCallbackRecords) {
-                if (record.mUserId != ALL.getIdentifier()
-                        && record.mUserId != getUserHandleForUid(token.getUid()).getIdentifier()) {
-                    continue;
-                }
-                try {
-                    record.mCallback.onSession2Created(token);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to notify session2 token created " + record);
-                }
-            }
-        }
-    }
-
-    void dispatchSession2Changed(int userId) {
-        MediaParceledListSlice<Session2Token> allSession2Tokens;
-        MediaParceledListSlice<Session2Token> userSession2Tokens;
-
-        synchronized (mLock) {
-            allSession2Tokens =
-                    new MediaParceledListSlice<>(getSession2TokensLocked(ALL.getIdentifier()));
-            userSession2Tokens = new MediaParceledListSlice<>(getSession2TokensLocked(userId));
-        }
-        allSession2Tokens.setInlineCountLimit(1);
-        userSession2Tokens.setInlineCountLimit(1);
-
-        synchronized (mLock) {
-            for (CallbackRecord record : mCallbackRecords) {
-                if (record.mUserId == ALL.getIdentifier()) {
-                    try {
-                        record.mCallback.onSession2Changed(allSession2Tokens);
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to notify session2 tokens changed " + record);
-                    }
-                } else if (record.mUserId == userId) {
-                    try {
-                        record.mCallback.onSession2Changed(userSession2Tokens);
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to notify session2 tokens changed " + record);
-                    }
-                }
-            }
-        }
-    }
-
-    void onSessionDied(Session2Record session) {
-        if (DEBUG) {
-            Log.d(TAG, "Destroying " + session);
-        }
-        if (session.isClosed()) {
-            Log.w(TAG, "Destroying already destroyed session. Ignoring.");
-            return;
-        }
-
-        FullUserRecord user = session.getFullUser();
-        if (user != null) {
-            user.removeSession(session);
-        }
-        session.close();
-    }
-
-    private class Stub extends IMediaCommunicationService.Stub {
-        @Override
-        public void notifySession2Created(Session2Token sessionToken) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                if (DEBUG) {
-                    Log.d(TAG, "Session2 is created " + sessionToken);
-                }
-                if (uid != sessionToken.getUid()) {
-                    throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
-                            + " but actually=" + sessionToken.getUid());
-                }
-                FullUserRecord user;
-                int userId = getUserHandleForUid(sessionToken.getUid()).getIdentifier();
-                synchronized (mLock) {
-                    user = getFullUserRecordLocked(userId);
-                }
-                if (user == null) {
-                    Log.w(TAG, "notifySession2Created: Ignore session of an unknown user");
-                    return;
-                }
-                user.addSession(new Session2Record(MediaCommunicationService.this,
-                        user, sessionToken, mRecordExecutor));
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        /**
-         * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
-         * permission or an enabled notification listener)
-         *
-         * @param controllerPackageName package name of the controller app
-         * @param controllerPid pid of the controller app
-         * @param controllerUid uid of the controller app
-         */
-        @Override
-        public boolean isTrusted(String controllerPackageName, int controllerPid,
-                int controllerUid) {
-            final int uid = Binder.getCallingUid();
-            final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                // Don't perform check between controllerPackageName and controllerUid.
-                // When an (activity|service) runs on the another apps process by specifying
-                // android:process in the AndroidManifest.xml, then PID and UID would have the
-                // running process' information instead of the (activity|service) that has created
-                // MediaController.
-                // Note that we can use Context#getOpPackageName() instead of
-                // Context#getPackageName() for getting package name that matches with the PID/UID,
-                // but it doesn't tell which package has created the MediaController, so useless.
-                return hasMediaControlPermission(controllerPid, controllerUid)
-                        || hasEnabledNotificationListener(
-                        userId, controllerPackageName, controllerUid);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public MediaParceledListSlice getSession2Tokens(int userId) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                // Check that they can make calls on behalf of the user and get the final user id
-                int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
-                List<Session2Token> result;
-                synchronized (mLock) {
-                    result = getSession2TokensLocked(resolvedUserId);
-                }
-                MediaParceledListSlice parceledListSlice = new MediaParceledListSlice<>(result);
-                parceledListSlice.setInlineCountLimit(1);
-                return parceledListSlice;
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void registerCallback(IMediaCommunicationServiceCallback callback,
-                String packageName) throws RemoteException {
-            Objects.requireNonNull(callback, "callback should not be null");
-            Objects.requireNonNull(packageName, "packageName should not be null");
-
-            synchronized (mLock) {
-                if (findCallbackRecordLocked(callback) == null) {
-
-                    CallbackRecord record = new CallbackRecord(callback, packageName,
-                            Binder.getCallingUid(), Binder.getCallingPid());
-                    mCallbackRecords.add(record);
-                    try {
-                        callback.asBinder().linkToDeath(record, 0);
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to register callback", e);
-                        mCallbackRecords.remove(record);
-                    }
-                } else {
-                    Log.e(TAG, "registerCallback is called with already registered callback. "
-                            + "packageName=" + packageName);
-                }
-            }
-        }
-
-        @Override
-        public void unregisterCallback(IMediaCommunicationServiceCallback callback)
-                throws RemoteException {
-            synchronized (mLock) {
-                CallbackRecord existingRecord = findCallbackRecordLocked(callback);
-                if (existingRecord != null) {
-                    mCallbackRecords.remove(existingRecord);
-                    callback.asBinder().unlinkToDeath(existingRecord, 0);
-                } else {
-                    Log.e(TAG, "unregisterCallback is called with unregistered callback.");
-                }
-            }
-        }
-
-        private boolean hasEnabledNotificationListener(int callingUserId,
-                String controllerPackageName, int controllerUid) {
-            int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
-            if (callingUserId != controllerUserId) {
-                // Enabled notification listener only works within the same user.
-                return false;
-            }
-
-            if (mNotificationManager.hasEnabledNotificationListener(controllerPackageName,
-                    UserHandle.getUserHandleForUid(controllerUid))) {
-                return true;
-            }
-            if (DEBUG) {
-                Log.d(TAG, controllerPackageName + " (uid=" + controllerUid
-                        + ") doesn't have an enabled notification listener");
-            }
-            return false;
-        }
-
-        // Handles incoming user by checking whether the caller has permission to access the
-        // given user id's information or not. Permission is not necessary if the given user id is
-        // equal to the caller's user id, but if not, the caller needs to have the
-        // INTERACT_ACROSS_USERS_FULL permission. Otherwise, a security exception will be thrown.
-        // The return value will be the given user id, unless the given user id is
-        // UserHandle.CURRENT, which will return the ActivityManager.getCurrentUser() value instead.
-        private int handleIncomingUser(int pid, int uid, int userId, String packageName) {
-            int callingUserId = UserHandle.getUserHandleForUid(uid).getIdentifier();
-            if (userId == callingUserId) {
-                return userId;
-            }
-
-            boolean canInteractAcrossUsersFull = mContext.checkPermission(
-                    INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED;
-            if (canInteractAcrossUsersFull) {
-                if (userId == UserHandle.CURRENT.getIdentifier()) {
-                    return ActivityManager.getCurrentUser();
-                }
-                return userId;
-            }
-
-            throw new SecurityException("Permission denied while calling from " + packageName
-                    + " with user id: " + userId + "; Need to run as either the calling user id ("
-                    + callingUserId + "), or with " + INTERACT_ACROSS_USERS_FULL + " permission");
-        }
-    }
-
-    final class CallbackRecord implements IBinder.DeathRecipient {
-        private final IMediaCommunicationServiceCallback mCallback;
-        private final String mPackageName;
-        private final int mUid;
-        private int mPid;
-        private final int mUserId;
-
-        CallbackRecord(IMediaCommunicationServiceCallback callback,
-                String packageName, int uid, int pid) {
-            mCallback = callback;
-            mPackageName = packageName;
-            mUid = uid;
-            mPid = pid;
-            mUserId = (mContext.checkPermission(
-                    INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED)
-                    ? ALL.getIdentifier() : UserHandle.getUserHandleForUid(mUid).getIdentifier();
-        }
-
-        @Override
-        public String toString() {
-            return "CallbackRecord[callback=" + mCallback + ", pkg=" + mPackageName
-                    + ", uid=" + mUid + ", pid=" + mPid + "]";
-        }
-
-        @Override
-        public void binderDied() {
-            synchronized (mLock) {
-                mCallbackRecords.remove(this);
-            }
-        }
-    }
-
-    final class FullUserRecord {
-        private final int mFullUserId;
-        private final Object mUserLock = new Object();
-        @GuardedBy("mUserLock")
-        private final List<Session2Record> mSessionRecords = new ArrayList<>();
-
-        FullUserRecord(int fullUserId) {
-            mFullUserId = fullUserId;
-        }
-
-        public void addSession(Session2Record record) {
-            synchronized (mUserLock) {
-                mSessionRecords.add(record);
-            }
-            mHandler.post(() -> dispatchSession2Created(record.mSessionToken));
-            mHandler.post(() -> dispatchSession2Changed(mFullUserId));
-        }
-
-        private void removeSession(Session2Record record) {
-            synchronized (mUserLock) {
-                mSessionRecords.remove(record);
-            }
-            mHandler.post(() -> dispatchSession2Changed(mFullUserId));
-            //TODO: Handle if the removed session was the media button session.
-        }
-
-        public int getFullUserId() {
-            return mFullUserId;
-        }
-
-        public List<Session2Token> getAllSession2Tokens() {
-            synchronized (mUserLock) {
-                return mSessionRecords.stream()
-                        .map(Session2Record::getSessionToken)
-                        .collect(Collectors.toList());
-            }
-        }
-
-        public List<Session2Token> getSession2Tokens(int userId) {
-            synchronized (mUserLock) {
-                return mSessionRecords.stream()
-                        .filter(record -> record.getUserId() == userId)
-                        .map(Session2Record::getSessionToken)
-                        .collect(Collectors.toList());
-            }
-        }
-
-        public void destroyAllSessions() {
-            synchronized (mUserLock) {
-                for (Session2Record session : mSessionRecords) {
-                    session.close();
-                }
-                mSessionRecords.clear();
-            }
-            mHandler.post(() -> dispatchSession2Changed(mFullUserId));
-        }
-
-        public void destroySessionsForUser(int userId) {
-            boolean changed = false;
-            synchronized (mUserLock) {
-                for (int i = mSessionRecords.size() - 1; i >= 0; i--) {
-                    Session2Record session = mSessionRecords.get(i);
-                    if (session.getUserId() == userId) {
-                        mSessionRecords.remove(i);
-                        session.close();
-                        changed = true;
-                    }
-                }
-            }
-            if (changed) {
-                mHandler.post(() -> dispatchSession2Changed(mFullUserId));
-            }
-        }
-    }
-
-    static final class Session2Record {
-        final Session2Token mSessionToken;
-        final Object mSession2RecordLock = new Object();
-        final WeakReference<MediaCommunicationService> mServiceRef;
-        final WeakReference<FullUserRecord> mFullUserRef;
-        @GuardedBy("mSession2RecordLock")
-        private final MediaController2 mController;
-
-        @GuardedBy("mSession2RecordLock")
-        boolean mIsConnected;
-        @GuardedBy("mSession2RecordLock")
-        private boolean mIsClosed;
-
-        Session2Record(MediaCommunicationService service, FullUserRecord fullUser,
-                Session2Token token, Executor controllerExecutor) {
-            mServiceRef = new WeakReference<>(service);
-            mFullUserRef = new WeakReference<>(fullUser);
-            mSessionToken = token;
-            mController = new MediaController2.Builder(service.getContext(), token)
-                    .setControllerCallback(controllerExecutor, new Controller2Callback())
-                    .build();
-        }
-
-        public int getUserId() {
-            return UserHandle.getUserHandleForUid(mSessionToken.getUid()).getIdentifier();
-        }
-
-        public FullUserRecord getFullUser() {
-            return mFullUserRef.get();
-        }
-
-        public boolean isClosed() {
-            synchronized (mSession2RecordLock) {
-                return mIsClosed;
-            }
-        }
-
-        public void close() {
-            synchronized (mSession2RecordLock) {
-                mIsClosed = true;
-                mController.close();
-            }
-        }
-
-        public Session2Token getSessionToken() {
-            return mSessionToken;
-        }
-
-        private class Controller2Callback extends MediaController2.ControllerCallback {
-            @Override
-            public void onConnected(MediaController2 controller,
-                    Session2CommandGroup allowedCommands) {
-                if (DEBUG) {
-                    Log.d(TAG, "connected to " + mSessionToken + ", allowed=" + allowedCommands);
-                }
-                synchronized (mSession2RecordLock) {
-                    mIsConnected = true;
-                }
-            }
-
-            @Override
-            public void onDisconnected(MediaController2 controller) {
-                if (DEBUG) {
-                    Log.d(TAG, "disconnected from " + mSessionToken);
-                }
-                synchronized (mSession2RecordLock) {
-                    mIsConnected = false;
-                }
-                MediaCommunicationService service = mServiceRef.get();
-                if (service != null) {
-                    service.onSessionDied(Session2Record.this);
-                }
-            }
-        }
-    }
-}
diff --git a/api/Android.bp b/api/Android.bp
index f89c557..2c6cade 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -32,6 +32,7 @@
         "soong",
         "soong-android",
         "soong-genrule",
+        "soong-java",
     ],
     srcs: ["api.go"],
     pluginFor: ["soong_build"],
@@ -92,6 +93,7 @@
 // Silence reflection warnings. See b/168689341
 metalava_cmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
 metalava_cmd += " --quiet --no-banner --format=v2 "
+metalava_cmd += " --hide ChangedThrows "
 
 genrule {
     name: "current-api-xml",
@@ -102,43 +104,32 @@
     visibility: ["//visibility:public"],
 }
 
-genrule {
-    name: "frameworks-base-api-current.txt",
-    srcs: [
-        ":android.net.ipsec.ike{.public.api.txt}",
-        ":art.module.public.api{.public.api.txt}",
-        ":conscrypt.module.public.api{.public.api.txt}",
-        ":framework-appsearch{.public.api.txt}",
-        ":framework-connectivity{.public.api.txt}",
-        ":framework-graphics{.public.api.txt}",
-        ":framework-media{.public.api.txt}",
-        ":framework-mediaprovider{.public.api.txt}",
-        ":framework-permission{.public.api.txt}",
-        ":framework-permission-s{.public.api.txt}",
-        ":framework-scheduling{.public.api.txt}",
-        ":framework-sdkextensions{.public.api.txt}",
-        ":framework-statsd{.public.api.txt}",
-        ":framework-tethering{.public.api.txt}",
-        ":framework-wifi{.public.api.txt}",
-        ":i18n.module.public.api{.public.api.txt}",
-        ":non-updatable-current.txt",
+combined_apis {
+    name: "frameworks-base-api",
+    bootclasspath: [
+        "android.net.ipsec.ike",
+        "art.module.public.api",
+        "conscrypt.module.public.api",
+        "framework-appsearch",
+        "framework-bluetooth",
+        "framework-connectivity",
+        "framework-connectivity-tiramisu",
+        "framework-graphics",
+        "framework-media",
+        "framework-mediaprovider",
+        "framework-permission",
+        "framework-permission-s",
+        "framework-scheduling",
+        "framework-sdkextensions",
+        "framework-statsd",
+        "framework-tethering",
+        "framework-wifi",
+        "i18n.module.public.api",
     ],
-    out: ["current.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "current.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/public/api",
-            dest: "android.txt",
-        },
+    system_server_classpath: [
+        "service-media-s",
+        "service-permission",
     ],
-    visibility: ["//visibility:public"],
 }
 
 genrule {
@@ -158,108 +149,6 @@
 }
 
 genrule {
-    name: "frameworks-base-api-current.srcjar",
-    srcs: [
-        ":android.net.ipsec.ike{.public.stubs.source}",
-        ":api-stubs-docs-non-updatable",
-        ":art.module.public.api{.public.stubs.source}",
-        ":conscrypt.module.public.api{.public.stubs.source}",
-        ":framework-appsearch{.public.stubs.source}",
-        ":framework-connectivity{.public.stubs.source}",
-        ":framework-graphics{.public.stubs.source}",
-        ":framework-media{.public.stubs.source}",
-        ":framework-mediaprovider{.public.stubs.source}",
-        ":framework-permission{.public.stubs.source}",
-        ":framework-permission-s{.public.stubs.source}",
-        ":framework-scheduling{.public.stubs.source}",
-        ":framework-sdkextensions{.public.stubs.source}",
-        ":framework-statsd{.public.stubs.source}",
-        ":framework-tethering{.public.stubs.source}",
-        ":framework-wifi{.public.stubs.source}",
-        ":i18n.module.public.api{.public.stubs.source}",
-    ],
-    out: ["current.srcjar"],
-    tools: ["merge_zips"],
-    cmd: "$(location merge_zips) $(out) $(in)",
-    visibility: ["//visibility:private"], // Used by make module in //development, mind.
-}
-
-genrule {
-    name: "frameworks-base-api-removed.txt",
-    srcs: [
-        ":android.net.ipsec.ike{.public.removed-api.txt}",
-        ":art.module.public.api{.public.removed-api.txt}",
-        ":conscrypt.module.public.api{.public.removed-api.txt}",
-        ":framework-appsearch{.public.removed-api.txt}",
-        ":framework-connectivity{.public.removed-api.txt}",
-        ":framework-graphics{.public.removed-api.txt}",
-        ":framework-media{.public.removed-api.txt}",
-        ":framework-mediaprovider{.public.removed-api.txt}",
-        ":framework-permission{.public.removed-api.txt}",
-        ":framework-permission-s{.public.removed-api.txt}",
-        ":framework-scheduling{.public.removed-api.txt}",
-        ":framework-sdkextensions{.public.removed-api.txt}",
-        ":framework-statsd{.public.removed-api.txt}",
-        ":framework-tethering{.public.removed-api.txt}",
-        ":framework-wifi{.public.removed-api.txt}",
-        ":i18n.module.public.api{.public.removed-api.txt}",
-        ":non-updatable-removed.txt",
-    ],
-    out: ["removed.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "removed.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/public/api",
-            dest: "removed.txt",
-        },
-    ],
-}
-
-genrule {
-    name: "frameworks-base-api-system-current.txt",
-    srcs: [
-        ":art.module.public.api{.system.api.txt}",
-        ":android.net.ipsec.ike{.system.api.txt}",
-        ":framework-appsearch{.system.api.txt}",
-        ":framework-connectivity{.system.api.txt}",
-        ":framework-graphics{.system.api.txt}",
-        ":framework-media{.system.api.txt}",
-        ":framework-mediaprovider{.system.api.txt}",
-        ":framework-permission{.system.api.txt}",
-        ":framework-permission-s{.system.api.txt}",
-        ":framework-scheduling{.system.api.txt}",
-        ":framework-sdkextensions{.system.api.txt}",
-        ":framework-statsd{.system.api.txt}",
-        ":framework-tethering{.system.api.txt}",
-        ":framework-wifi{.system.api.txt}",
-        ":non-updatable-system-current.txt",
-    ],
-    out: ["system-current.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "system-current.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system/api",
-            dest: "android.txt",
-        },
-    ],
-    visibility: ["//visibility:public"],
-}
-
-genrule {
     name: "frameworks-base-api-system-current-compat",
     srcs: [
         ":android.api.system.latest",
@@ -278,79 +167,6 @@
 }
 
 genrule {
-    name: "frameworks-base-api-system-removed.txt",
-    srcs: [
-        ":art.module.public.api{.system.removed-api.txt}",
-        ":android.net.ipsec.ike{.system.removed-api.txt}",
-        ":framework-appsearch{.system.removed-api.txt}",
-        ":framework-connectivity{.system.removed-api.txt}",
-        ":framework-graphics{.system.removed-api.txt}",
-        ":framework-media{.system.removed-api.txt}",
-        ":framework-mediaprovider{.system.removed-api.txt}",
-        ":framework-permission{.system.removed-api.txt}",
-        ":framework-permission-s{.system.removed-api.txt}",
-        ":framework-scheduling{.system.removed-api.txt}",
-        ":framework-sdkextensions{.system.removed-api.txt}",
-        ":framework-statsd{.system.removed-api.txt}",
-        ":framework-tethering{.system.removed-api.txt}",
-        ":framework-wifi{.system.removed-api.txt}",
-        ":non-updatable-system-removed.txt",
-    ],
-    out: ["system-removed.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "system-removed.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system/api",
-            dest: "removed.txt",
-        },
-    ],
-    visibility: ["//visibility:public"],
-}
-
-genrule {
-    name: "frameworks-base-api-module-lib-current.txt",
-    srcs: [
-        ":art.module.public.api{.module-lib.api.txt}",
-        ":android.net.ipsec.ike{.module-lib.api.txt}",
-        ":framework-appsearch{.module-lib.api.txt}",
-        ":framework-connectivity{.module-lib.api.txt}",
-        ":framework-graphics{.module-lib.api.txt}",
-        ":framework-media{.module-lib.api.txt}",
-        ":framework-mediaprovider{.module-lib.api.txt}",
-        ":framework-permission{.module-lib.api.txt}",
-        ":framework-permission-s{.module-lib.api.txt}",
-        ":framework-scheduling{.module-lib.api.txt}",
-        ":framework-sdkextensions{.module-lib.api.txt}",
-        ":framework-statsd{.module-lib.api.txt}",
-        ":framework-tethering{.module-lib.api.txt}",
-        ":framework-wifi{.module-lib.api.txt}",
-        ":non-updatable-module-lib-current.txt",
-    ],
-    out: ["module-lib-current.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "module-lib-current.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/module-lib/api",
-            dest: "android.txt",
-        },
-    ],
-}
-
-genrule {
     name: "frameworks-base-api-module-lib-current-compat",
     srcs: [
         ":android.api.module-lib.latest",
@@ -372,42 +188,6 @@
 }
 
 genrule {
-    name: "frameworks-base-api-module-lib-removed.txt",
-    srcs: [
-        ":art.module.public.api{.module-lib.removed-api.txt}",
-        ":android.net.ipsec.ike{.module-lib.removed-api.txt}",
-        ":framework-appsearch{.module-lib.removed-api.txt}",
-        ":framework-connectivity{.module-lib.removed-api.txt}",
-        ":framework-graphics{.module-lib.removed-api.txt}",
-        ":framework-media{.module-lib.removed-api.txt}",
-        ":framework-mediaprovider{.module-lib.removed-api.txt}",
-        ":framework-permission{.module-lib.removed-api.txt}",
-        ":framework-permission-s{.module-lib.removed-api.txt}",
-        ":framework-scheduling{.module-lib.removed-api.txt}",
-        ":framework-sdkextensions{.module-lib.removed-api.txt}",
-        ":framework-statsd{.module-lib.removed-api.txt}",
-        ":framework-tethering{.module-lib.removed-api.txt}",
-        ":framework-wifi{.module-lib.removed-api.txt}",
-        ":non-updatable-module-lib-removed.txt",
-    ],
-    out: ["module-lib-removed.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "module-lib-removed.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/module-lib/api",
-            dest: "removed.txt",
-        },
-    ],
-}
-
-genrule {
     name: "combined-removed-dex",
     visibility: [
         "//frameworks/base/boot",
@@ -423,86 +203,3 @@
     out: ["combined-removed-dex.txt"],
     cmd: "$(location gen_combined_removed_dex.sh) $(location metalava) $(genDir) $(in) > $(out)",
 }
-
-genrule {
-    name: "frameworks-base-api-system-server-current.txt",
-    srcs: [
-        ":service-media-s{.system-server.api.txt}",
-        ":service-permission{.system-server.api.txt}",
-        ":non-updatable-system-server-current.txt",
-    ],
-    out: ["system-server-current.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "system-server-current.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system-server/api",
-            dest: "android.txt",
-        },
-    ],
-}
-
-genrule {
-    name: "frameworks-base-api-system-server-removed.txt",
-    srcs: [
-        ":service-media-s{.system-server.removed-api.txt}",
-        ":service-permission{.system-server.removed-api.txt}",
-        ":non-updatable-system-server-removed.txt",
-    ],
-    out: ["system-server-removed.txt"],
-    tools: ["metalava"],
-    cmd: metalava_cmd + "$(in) --api $(out)",
-    dists: [
-        {
-            targets: ["droidcore"],
-            dir: "api",
-            dest: "system-server-removed.txt",
-        },
-        {
-            targets: ["sdk"],
-            dir: "apistubs/android/system-server/api",
-            dest: "removed.txt",
-        },
-    ],
-}
-
-// This rule will filter classes present in the jar files of mainline modules
-// from the lint database in api-versions.xml.
-// This is done to reduce the number of false positive NewApi findings in
-// java libraries that compile against the module SDK
-genrule {
-    name: "api-versions-xml-public-filtered",
-    srcs: [
-        // Note: order matters: first parameter is the full api-versions.xml
-        // after that the stubs files in any order
-        // stubs files are all modules that export API surfaces EXCEPT ART
-        ":framework-doc-stubs{.api_versions.xml}",
-        ":android.net.ipsec.ike.stubs{.jar}",
-        ":conscrypt.module.public.api.stubs{.jar}",
-        ":framework-appsearch.stubs{.jar}",
-        ":framework-connectivity.stubs{.jar}",
-        ":framework-graphics.stubs{.jar}",
-        ":framework-media.stubs{.jar}",
-        ":framework-mediaprovider.stubs{.jar}",
-        ":framework-permission.stubs{.jar}",
-        ":framework-permission-s.stubs{.jar}",
-        ":framework-scheduling.stubs{.jar}",
-        ":framework-sdkextensions.stubs{.jar}",
-        ":framework-statsd.stubs{.jar}",
-        ":framework-tethering.stubs{.jar}",
-        ":framework-wifi.stubs{.jar}",
-        ":i18n.module.public.api.stubs{.jar}",
-    ],
-    out: ["api-versions-public-filtered.xml"],
-    tools: ["api_versions_trimmer"],
-    cmd: "$(location api_versions_trimmer) $(out) $(in)",
-    dist: {
-        targets: ["sdk"],
-    },
-}
diff --git a/api/OWNERS b/api/OWNERS
index a027270..4d8ed03 100644
--- a/api/OWNERS
+++ b/api/OWNERS
@@ -4,3 +4,6 @@
 file:platform/packages/modules/common:/OWNERS
 
 per-file Android.bp = file:platform/build/soong:/OWNERS
+
+# For metalava team to disable lint checks in platform
+per-file Android.bp = aurimas@google.com,emberrose@google.com,sjgilbert@google.com
\ No newline at end of file
diff --git a/api/api.go b/api/api.go
index 976b140..5e5f60e 100644
--- a/api/api.go
+++ b/api/api.go
@@ -15,12 +15,20 @@
 package api
 
 import (
+	"sort"
+
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 	"android/soong/genrule"
+	"android/soong/java"
 )
 
+const art = "art.module.public.api"
+const conscrypt = "conscrypt.module.public.api"
+const i18n = "i18n.module.public.api"
+var core_libraries_modules = []string{art, conscrypt, i18n}
+
 // The intention behind this soong plugin is to generate a number of "merged"
 // API-related modules that would otherwise require a large amount of very
 // similar Android.bp boilerplate to define. For example, the merged current.txt
@@ -30,22 +38,12 @@
 
 // The properties of the combined_apis module type.
 type CombinedApisProperties struct {
-	// Module libraries that have public APIs
-	Public []string
-	// Module libraries that have system APIs
-	System []string
-	// Module libraries that have module_library APIs
-	Module_lib []string
-	// Module libraries that have system_server APIs
-	System_server []string
-	// ART module library. The only API library not removed from the filtered api database, because
-	// 1) ART apis are available by default to all modules, while other module-to-module deps are
-	//    explicit and probably receive more scrutiny anyway
-	// 2) The number of ART/libcore APIs is large, so not linting them would create a large gap
-	// 3) It's a compromise. Ideally we wouldn't be filtering out any module APIs, and have
-	//    per-module lint databases that excludes just that module's APIs. Alas, that's more
-	//    difficult to achieve.
-	Art_module string
+	// Module libraries in the bootclasspath
+	Bootclasspath []string
+	// Module libraries on the bootclasspath if include_nonpublic_framework_api is true.
+	Conditional_bootclasspath []string
+	// Module libraries in system server
+	System_server_classpath []string
 }
 
 type CombinedApis struct {
@@ -77,6 +75,19 @@
 	Visibility []string
 }
 
+type libraryProps struct {
+	Name        *string
+	Sdk_version *string
+	Static_libs []string
+	Visibility  []string
+}
+
+type fgProps struct {
+	Name       *string
+	Srcs       []string
+	Visibility []string
+}
+
 // Struct to pass parameters for the various merged [current|removed].txt file modules we create.
 type MergedTxtDefinition struct {
 	// "current.txt" or "removed.txt"
@@ -105,9 +116,9 @@
 	props := genruleProps{}
 	props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename)
 	props.Tools = []string{"metalava"}
-	props.Out = []string{txt.TxtFilename}
+	props.Out = []string{filename}
 	props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --api $(out)")
-	props.Srcs = createSrcs(txt.BaseTxt, txt.Modules, txt.ModuleTag)
+	props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...)
 	props.Dists = []android.Dist{
 		{
 			Targets: []string{"droidcore"},
@@ -130,12 +141,34 @@
 	props.Tools = []string{"merge_zips"}
 	props.Out = []string{"current.srcjar"}
 	props.Cmd = proptools.StringPtr("$(location merge_zips) $(out) $(in)")
-	props.Srcs = createSrcs(":api-stubs-docs-non-updatable", modules, "{.public.stubs.source}")
+	props.Srcs = append([]string{":api-stubs-docs-non-updatable"}, createSrcs(modules, "{.public.stubs.source}")...)
 	props.Visibility = []string{"//visibility:private"} // Used by make module in //development, mind
 	ctx.CreateModule(genrule.GenRuleFactory, &props)
 }
 
+// This produces the same annotations.zip as framework-doc-stubs, but by using
+// outputs from individual modules instead of all the source code.
+func createMergedAnnotations(ctx android.LoadHookContext, modules []string) {
+	props := genruleProps{}
+	props.Name = proptools.StringPtr("sdk-annotations.zip")
+	props.Tools = []string{"merge_annotation_zips", "soong_zip"}
+	props.Out = []string{"annotations.zip"}
+	props.Cmd = proptools.StringPtr("$(location merge_annotation_zips) $(genDir)/out $(in) && " +
+		"$(location soong_zip) -o $(out) -C $(genDir)/out -D $(genDir)/out")
+	props.Srcs = append([]string{":android-non-updatable-doc-stubs{.annotations.zip}"}, createSrcs(modules, "{.public.annotations.zip}")...)
+	ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
 func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
+	// For the filtered api versions, we prune all APIs except art module's APIs. because
+	// 1) ART apis are available by default to all modules, while other module-to-module deps are
+	//    explicit and probably receive more scrutiny anyway
+	// 2) The number of ART/libcore APIs is large, so not linting them would create a large gap
+	// 3) It's a compromise. Ideally we wouldn't be filtering out any module APIs, and have
+	//    per-module lint databases that excludes just that module's APIs. Alas, that's more
+	//    difficult to achieve.
+	modules = remove(modules, art)
+
 	props := genruleProps{}
 	props.Name = proptools.StringPtr("api-versions-xml-public-filtered")
 	props.Tools = []string{"api_versions_trimmer"}
@@ -144,59 +177,97 @@
 	// Note: order matters: first parameter is the full api-versions.xml
 	// after that the stubs files in any order
 	// stubs files are all modules that export API surfaces EXCEPT ART
-	props.Srcs = createSrcs(":framework-doc-stubs{.api_versions.xml}", modules, ".stubs{.jar}")
+	props.Srcs = append([]string{":framework-doc-stubs{.api_versions.xml}"}, createSrcs(modules, ".stubs{.jar}")...)
 	props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
 	ctx.CreateModule(genrule.GenRuleFactory, &props)
 }
 
-func createSrcs(base string, modules []string, tag string) []string {
-	a := make([]string, 0, len(modules)+1)
-	a = append(a, base)
-	for _, module := range modules {
-		a = append(a, ":"+module+tag)
-	}
-	return a
+func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
+	props := libraryProps{}
+	props.Name = proptools.StringPtr("all-modules-public-stubs")
+	props.Static_libs = transformArray(modules, "", ".stubs")
+	props.Sdk_version = proptools.StringPtr("module_current")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func remove(s []string, v string) []string {
-	s2 := make([]string, 0, len(s))
-	for _, sv := range s {
-		if sv != v {
-			s2 = append(s2, sv)
+func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
+	props := libraryProps{}
+	props.Name = proptools.StringPtr("all-modules-system-stubs")
+	props.Static_libs = transformArray(modules, "", ".stubs.system")
+	props.Sdk_version = proptools.StringPtr("module_current")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) {
+	// This module is for the "framework-all" module, which should not include the core libraries.
+	modules = removeAll(modules, core_libraries_modules)
+	// TODO(b/214988855): remove the line below when framework-bluetooth has an impl jar.
+	modules = remove(modules, "framework-bluetooth")
+	props := libraryProps{}
+	props.Name = proptools.StringPtr("all-framework-module-impl")
+	props.Static_libs = transformArray(modules, "", ".impl")
+	// Media module's impl jar is called "updatable-media"
+	for i, v := range props.Static_libs {
+		if v == "framework-media.impl" {
+			props.Static_libs[i] = "updatable-media"
 		}
 	}
-	return s2
+	props.Sdk_version = proptools.StringPtr("module_current")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(java.LibraryFactory, &props)
 }
 
-func createMergedTxts(ctx android.LoadHookContext, props CombinedApisProperties) {
+func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) {
+	// The user of this module compiles against the "core" SDK, so remove core libraries to avoid dupes.
+	modules = removeAll(modules, core_libraries_modules)
+	props := libraryProps{}
+	props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api")
+	props.Static_libs = transformArray(modules, "", ".stubs.module_lib")
+	props.Sdk_version = proptools.StringPtr("module_current")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []string) {
+	props := fgProps{}
+	props.Name = proptools.StringPtr("all-modules-public-stubs-source")
+	props.Srcs = createSrcs(modules, "{.public.stubs.source}")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(android.FileGroupFactory, &props)
+}
+
+func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
 	var textFiles []MergedTxtDefinition
+
 	tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
 	for i, f := range []string{"current.txt", "removed.txt"} {
 		textFiles = append(textFiles, MergedTxtDefinition{
 			TxtFilename: f,
 			BaseTxt:     ":non-updatable-" + f,
-			Modules:     props.Public,
+			Modules:     bootclasspath,
 			ModuleTag:   "{.public" + tagSuffix[i],
 			Scope:       "public",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
 			TxtFilename: f,
 			BaseTxt:     ":non-updatable-system-" + f,
-			Modules:     props.System,
+			Modules:     bootclasspath,
 			ModuleTag:   "{.system" + tagSuffix[i],
 			Scope:       "system",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
 			TxtFilename: f,
 			BaseTxt:     ":non-updatable-module-lib-" + f,
-			Modules:     props.Module_lib,
+			Modules:     bootclasspath,
 			ModuleTag:   "{.module-lib" + tagSuffix[i],
 			Scope:       "module-lib",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
 			TxtFilename: f,
 			BaseTxt:     ":non-updatable-system-server-" + f,
-			Modules:     props.System_server,
+			Modules:     system_server_classpath,
 			ModuleTag:   "{.system-server" + tagSuffix[i],
 			Scope:       "system-server",
 		})
@@ -207,12 +278,25 @@
 }
 
 func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
-	createMergedTxts(ctx, a.properties)
+	bootclasspath := a.properties.Bootclasspath
+	if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") {
+		bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...)
+		sort.Strings(bootclasspath)
+	}
+	createMergedTxts(ctx, bootclasspath, a.properties.System_server_classpath)
 
-	createMergedStubsSrcjar(ctx, a.properties.Public)
+	createMergedStubsSrcjar(ctx, bootclasspath)
 
-	// For the filtered api versions, we prune all APIs except art module's APIs.
-	createFilteredApiVersions(ctx, remove(a.properties.Public, a.properties.Art_module))
+	createMergedPublicStubs(ctx, bootclasspath)
+	createMergedSystemStubs(ctx, bootclasspath)
+	createMergedFrameworkModuleLibStubs(ctx, bootclasspath)
+	createMergedFrameworkImpl(ctx, bootclasspath)
+
+	createMergedAnnotations(ctx, bootclasspath)
+
+	createFilteredApiVersions(ctx, bootclasspath)
+
+	createPublicStubsSourceFilegroup(ctx, bootclasspath)
 }
 
 func combinedApisModuleFactory() android.Module {
@@ -222,3 +306,36 @@
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) })
 	return module
 }
+
+// Various utility methods below.
+
+// Creates an array of ":<m><tag>" for each m in <modules>.
+func createSrcs(modules []string, tag string) []string {
+	return transformArray(modules, ":", tag)
+}
+
+// Creates an array of "<prefix><m><suffix>", for each m in <modules>.
+func transformArray(modules []string, prefix, suffix string) []string {
+	a := make([]string, 0, len(modules))
+	for _, module := range modules {
+		a = append(a, prefix+module+suffix)
+	}
+	return a
+}
+
+func removeAll(s []string, vs []string) []string {
+	for _, v := range vs {
+		s = remove(s, v)
+	}
+	return s
+}
+
+func remove(s []string, v string) []string {
+	s2 := make([]string, 0, len(s))
+	for _, sv := range s {
+		if sv != v {
+			s2 = append(s2, sv)
+		}
+	}
+	return s2
+}
diff --git a/boot/hiddenapi/hiddenapi-max-target-o.txt b/boot/hiddenapi/hiddenapi-max-target-o.txt
index 0ec918b..50e0a1b 100644
--- a/boot/hiddenapi/hiddenapi-max-target-o.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-o.txt
@@ -35446,51 +35446,6 @@
 Landroid/net/IIpConnectivityMetrics;->addNetdEventCallback(ILandroid/net/INetdEventCallback;)Z
 Landroid/net/IIpConnectivityMetrics;->logEvent(Landroid/net/ConnectivityMetricsEvent;)I
 Landroid/net/IIpConnectivityMetrics;->removeNetdEventCallback(I)Z
-Landroid/net/IIpSecService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/IIpSecService$Stub$Proxy;->addAddressToTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->allocateSecurityParameterIndex(Ljava/lang/String;ILandroid/os/IBinder;)Landroid/net/IpSecSpiResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->applyTransportModeTransform(Landroid/os/ParcelFileDescriptor;II)V
-Landroid/net/IIpSecService$Stub$Proxy;->applyTunnelModeTransform(IIILjava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->closeUdpEncapsulationSocket(I)V
-Landroid/net/IIpSecService$Stub$Proxy;->createTransform(Landroid/net/IpSecConfig;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTransformResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->createTunnelInterface(Ljava/lang/String;Ljava/lang/String;Landroid/net/Network;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTunnelInterfaceResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->deleteTransform(I)V
-Landroid/net/IIpSecService$Stub$Proxy;->deleteTunnelInterface(ILjava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/IIpSecService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/IIpSecService$Stub$Proxy;->openUdpEncapsulationSocket(ILandroid/os/IBinder;)Landroid/net/IpSecUdpEncapResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->releaseSecurityParameterIndex(I)V
-Landroid/net/IIpSecService$Stub$Proxy;->removeAddressFromTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->removeTransportModeTransforms(Landroid/os/ParcelFileDescriptor;)V
-Landroid/net/IIpSecService$Stub;-><init>()V
-Landroid/net/IIpSecService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IIpSecService;
-Landroid/net/IIpSecService$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/IIpSecService$Stub;->TRANSACTION_addAddressToTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_allocateSecurityParameterIndex:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_applyTransportModeTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_applyTunnelModeTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_closeUdpEncapsulationSocket:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_createTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_createTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_deleteTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_deleteTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_openUdpEncapsulationSocket:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_releaseSecurityParameterIndex:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_removeAddressFromTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_removeTransportModeTransforms:I
-Landroid/net/IIpSecService;->addAddressToTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService;->allocateSecurityParameterIndex(Ljava/lang/String;ILandroid/os/IBinder;)Landroid/net/IpSecSpiResponse;
-Landroid/net/IIpSecService;->applyTransportModeTransform(Landroid/os/ParcelFileDescriptor;II)V
-Landroid/net/IIpSecService;->applyTunnelModeTransform(IIILjava/lang/String;)V
-Landroid/net/IIpSecService;->closeUdpEncapsulationSocket(I)V
-Landroid/net/IIpSecService;->createTransform(Landroid/net/IpSecConfig;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTransformResponse;
-Landroid/net/IIpSecService;->createTunnelInterface(Ljava/lang/String;Ljava/lang/String;Landroid/net/Network;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTunnelInterfaceResponse;
-Landroid/net/IIpSecService;->deleteTransform(I)V
-Landroid/net/IIpSecService;->deleteTunnelInterface(ILjava/lang/String;)V
-Landroid/net/IIpSecService;->openUdpEncapsulationSocket(ILandroid/os/IBinder;)Landroid/net/IpSecUdpEncapResponse;
-Landroid/net/IIpSecService;->releaseSecurityParameterIndex(I)V
-Landroid/net/IIpSecService;->removeAddressFromTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService;->removeTransportModeTransforms(Landroid/os/ParcelFileDescriptor;)V
 Landroid/net/INetd$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/INetd$Stub$Proxy;->addVirtualTunnelInterface(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V
 Landroid/net/INetd$Stub$Proxy;->bandwidthEnableDataSaver(Z)Z
@@ -35914,174 +35869,6 @@
 Landroid/net/InterfaceConfiguration;->mHwAddr:Ljava/lang/String;
 Landroid/net/InterfaceConfiguration;->setHardwareAddress(Ljava/lang/String;)V
 Landroid/net/InterfaceConfiguration;->validateFlag(Ljava/lang/String;)V
-Landroid/net/IpSecAlgorithm;->checkValidOrThrow(Ljava/lang/String;II)V
-Landroid/net/IpSecAlgorithm;->CRYPT_NULL:Ljava/lang/String;
-Landroid/net/IpSecAlgorithm;->equals(Landroid/net/IpSecAlgorithm;Landroid/net/IpSecAlgorithm;)Z
-Landroid/net/IpSecAlgorithm;->isAead()Z
-Landroid/net/IpSecAlgorithm;->isAuthentication()Z
-Landroid/net/IpSecAlgorithm;->isEncryption()Z
-Landroid/net/IpSecAlgorithm;->isUnsafeBuild()Z
-Landroid/net/IpSecAlgorithm;->mKey:[B
-Landroid/net/IpSecAlgorithm;->mName:Ljava/lang/String;
-Landroid/net/IpSecAlgorithm;->mTruncLenBits:I
-Landroid/net/IpSecAlgorithm;->TAG:Ljava/lang/String;
-Landroid/net/IpSecConfig;-><init>()V
-Landroid/net/IpSecConfig;-><init>(Landroid/net/IpSecConfig;)V
-Landroid/net/IpSecConfig;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecConfig;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecConfig;->equals(Landroid/net/IpSecConfig;Landroid/net/IpSecConfig;)Z
-Landroid/net/IpSecConfig;->getAuthenticatedEncryption()Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->getAuthentication()Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->getDestinationAddress()Ljava/lang/String;
-Landroid/net/IpSecConfig;->getEncapRemotePort()I
-Landroid/net/IpSecConfig;->getEncapSocketResourceId()I
-Landroid/net/IpSecConfig;->getEncapType()I
-Landroid/net/IpSecConfig;->getEncryption()Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->getMarkMask()I
-Landroid/net/IpSecConfig;->getMarkValue()I
-Landroid/net/IpSecConfig;->getMode()I
-Landroid/net/IpSecConfig;->getNattKeepaliveInterval()I
-Landroid/net/IpSecConfig;->getNetwork()Landroid/net/Network;
-Landroid/net/IpSecConfig;->getSourceAddress()Ljava/lang/String;
-Landroid/net/IpSecConfig;->getSpiResourceId()I
-Landroid/net/IpSecConfig;->mAuthenticatedEncryption:Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->mAuthentication:Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->mDestinationAddress:Ljava/lang/String;
-Landroid/net/IpSecConfig;->mEncapRemotePort:I
-Landroid/net/IpSecConfig;->mEncapSocketResourceId:I
-Landroid/net/IpSecConfig;->mEncapType:I
-Landroid/net/IpSecConfig;->mEncryption:Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->mMarkMask:I
-Landroid/net/IpSecConfig;->mMarkValue:I
-Landroid/net/IpSecConfig;->mMode:I
-Landroid/net/IpSecConfig;->mNattKeepaliveInterval:I
-Landroid/net/IpSecConfig;->mNetwork:Landroid/net/Network;
-Landroid/net/IpSecConfig;->mSourceAddress:Ljava/lang/String;
-Landroid/net/IpSecConfig;->mSpiResourceId:I
-Landroid/net/IpSecConfig;->setAuthenticatedEncryption(Landroid/net/IpSecAlgorithm;)V
-Landroid/net/IpSecConfig;->setAuthentication(Landroid/net/IpSecAlgorithm;)V
-Landroid/net/IpSecConfig;->setDestinationAddress(Ljava/lang/String;)V
-Landroid/net/IpSecConfig;->setEncapRemotePort(I)V
-Landroid/net/IpSecConfig;->setEncapSocketResourceId(I)V
-Landroid/net/IpSecConfig;->setEncapType(I)V
-Landroid/net/IpSecConfig;->setEncryption(Landroid/net/IpSecAlgorithm;)V
-Landroid/net/IpSecConfig;->setMarkMask(I)V
-Landroid/net/IpSecConfig;->setMarkValue(I)V
-Landroid/net/IpSecConfig;->setMode(I)V
-Landroid/net/IpSecConfig;->setNattKeepaliveInterval(I)V
-Landroid/net/IpSecConfig;->setNetwork(Landroid/net/Network;)V
-Landroid/net/IpSecConfig;->setSourceAddress(Ljava/lang/String;)V
-Landroid/net/IpSecConfig;->setSpiResourceId(I)V
-Landroid/net/IpSecConfig;->TAG:Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;-><init>(Landroid/content/Context;Landroid/net/IIpSecService;Ljava/net/InetAddress;Ljava/net/InetAddress;Landroid/net/Network;)V
-Landroid/net/IpSecManager$IpSecTunnelInterface;->addAddress(Ljava/net/InetAddress;I)V
-Landroid/net/IpSecManager$IpSecTunnelInterface;->getInterfaceName()Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->getResourceId()I
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mInterfaceName:Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mLocalAddress:Ljava/net/InetAddress;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mOpPackageName:Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mRemoteAddress:Ljava/net/InetAddress;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mResourceId:I
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mUnderlyingNetwork:Landroid/net/Network;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->removeAddress(Ljava/net/InetAddress;I)V
-Landroid/net/IpSecManager$ResourceUnavailableException;-><init>(Ljava/lang/String;)V
-Landroid/net/IpSecManager$SecurityParameterIndex;-><init>(Landroid/net/IIpSecService;Ljava/net/InetAddress;I)V
-Landroid/net/IpSecManager$SecurityParameterIndex;->getResourceId()I
-Landroid/net/IpSecManager$SecurityParameterIndex;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecManager$SecurityParameterIndex;->mDestinationAddress:Ljava/net/InetAddress;
-Landroid/net/IpSecManager$SecurityParameterIndex;->mResourceId:I
-Landroid/net/IpSecManager$SecurityParameterIndex;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager$SecurityParameterIndex;->mSpi:I
-Landroid/net/IpSecManager$SpiUnavailableException;-><init>(Ljava/lang/String;I)V
-Landroid/net/IpSecManager$SpiUnavailableException;->mSpi:I
-Landroid/net/IpSecManager$Status;->OK:I
-Landroid/net/IpSecManager$Status;->RESOURCE_UNAVAILABLE:I
-Landroid/net/IpSecManager$Status;->SPI_UNAVAILABLE:I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;-><init>(Landroid/net/IIpSecService;I)V
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->getResourceId()I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mPfd:Landroid/os/ParcelFileDescriptor;
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mPort:I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mResourceId:I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager;-><init>(Landroid/content/Context;Landroid/net/IIpSecService;)V
-Landroid/net/IpSecManager;->applyTunnelModeTransform(Landroid/net/IpSecManager$IpSecTunnelInterface;ILandroid/net/IpSecTransform;)V
-Landroid/net/IpSecManager;->createIpSecTunnelInterface(Ljava/net/InetAddress;Ljava/net/InetAddress;Landroid/net/Network;)Landroid/net/IpSecManager$IpSecTunnelInterface;
-Landroid/net/IpSecManager;->INVALID_RESOURCE_ID:I
-Landroid/net/IpSecManager;->maybeHandleServiceSpecificException(Landroid/os/ServiceSpecificException;)V
-Landroid/net/IpSecManager;->mContext:Landroid/content/Context;
-Landroid/net/IpSecManager;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager;->removeTunnelModeTransform(Landroid/net/Network;Landroid/net/IpSecTransform;)V
-Landroid/net/IpSecManager;->rethrowCheckedExceptionFromServiceSpecificException(Landroid/os/ServiceSpecificException;)Ljava/io/IOException;
-Landroid/net/IpSecManager;->rethrowUncheckedExceptionFromServiceSpecificException(Landroid/os/ServiceSpecificException;)Ljava/lang/RuntimeException;
-Landroid/net/IpSecManager;->TAG:Ljava/lang/String;
-Landroid/net/IpSecSpiResponse;-><init>(I)V
-Landroid/net/IpSecSpiResponse;-><init>(III)V
-Landroid/net/IpSecSpiResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecSpiResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecSpiResponse;->resourceId:I
-Landroid/net/IpSecSpiResponse;->spi:I
-Landroid/net/IpSecSpiResponse;->status:I
-Landroid/net/IpSecSpiResponse;->TAG:Ljava/lang/String;
-Landroid/net/IpSecTransform$Builder;->buildTunnelModeTransform(Ljava/net/InetAddress;Landroid/net/IpSecManager$SecurityParameterIndex;)Landroid/net/IpSecTransform;
-Landroid/net/IpSecTransform$Builder;->mConfig:Landroid/net/IpSecConfig;
-Landroid/net/IpSecTransform$Builder;->mContext:Landroid/content/Context;
-Landroid/net/IpSecTransform$NattKeepaliveCallback;-><init>()V
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_HARDWARE_ERROR:I
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_HARDWARE_UNSUPPORTED:I
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_INVALID_NETWORK:I
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->onError(I)V
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->onStarted()V
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->onStopped()V
-Landroid/net/IpSecTransform;-><init>(Landroid/content/Context;Landroid/net/IpSecConfig;)V
-Landroid/net/IpSecTransform;->activate()Landroid/net/IpSecTransform;
-Landroid/net/IpSecTransform;->checkResultStatus(I)V
-Landroid/net/IpSecTransform;->ENCAP_ESPINUDP:I
-Landroid/net/IpSecTransform;->ENCAP_ESPINUDP_NON_IKE:I
-Landroid/net/IpSecTransform;->ENCAP_NONE:I
-Landroid/net/IpSecTransform;->equals(Landroid/net/IpSecTransform;Landroid/net/IpSecTransform;)Z
-Landroid/net/IpSecTransform;->getConfig()Landroid/net/IpSecConfig;
-Landroid/net/IpSecTransform;->getIpSecService()Landroid/net/IIpSecService;
-Landroid/net/IpSecTransform;->getResourceId()I
-Landroid/net/IpSecTransform;->mCallbackHandler:Landroid/os/Handler;
-Landroid/net/IpSecTransform;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecTransform;->mConfig:Landroid/net/IpSecConfig;
-Landroid/net/IpSecTransform;->mContext:Landroid/content/Context;
-Landroid/net/IpSecTransform;->mKeepalive:Landroid/net/ConnectivityManager$PacketKeepalive;
-Landroid/net/IpSecTransform;->mKeepaliveCallback:Landroid/net/ConnectivityManager$PacketKeepaliveCallback;
-Landroid/net/IpSecTransform;->MODE_TRANSPORT:I
-Landroid/net/IpSecTransform;->MODE_TUNNEL:I
-Landroid/net/IpSecTransform;->mResourceId:I
-Landroid/net/IpSecTransform;->mUserKeepaliveCallback:Landroid/net/IpSecTransform$NattKeepaliveCallback;
-Landroid/net/IpSecTransform;->startNattKeepalive(Landroid/net/IpSecTransform$NattKeepaliveCallback;ILandroid/os/Handler;)V
-Landroid/net/IpSecTransform;->stopNattKeepalive()V
-Landroid/net/IpSecTransform;->TAG:Ljava/lang/String;
-Landroid/net/IpSecTransformResponse;-><init>(I)V
-Landroid/net/IpSecTransformResponse;-><init>(II)V
-Landroid/net/IpSecTransformResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecTransformResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecTransformResponse;->resourceId:I
-Landroid/net/IpSecTransformResponse;->status:I
-Landroid/net/IpSecTransformResponse;->TAG:Ljava/lang/String;
-Landroid/net/IpSecTunnelInterfaceResponse;-><init>(I)V
-Landroid/net/IpSecTunnelInterfaceResponse;-><init>(IILjava/lang/String;)V
-Landroid/net/IpSecTunnelInterfaceResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecTunnelInterfaceResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecTunnelInterfaceResponse;->interfaceName:Ljava/lang/String;
-Landroid/net/IpSecTunnelInterfaceResponse;->resourceId:I
-Landroid/net/IpSecTunnelInterfaceResponse;->status:I
-Landroid/net/IpSecTunnelInterfaceResponse;->TAG:Ljava/lang/String;
-Landroid/net/IpSecUdpEncapResponse;-><init>(I)V
-Landroid/net/IpSecUdpEncapResponse;-><init>(IIILjava/io/FileDescriptor;)V
-Landroid/net/IpSecUdpEncapResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecUdpEncapResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecUdpEncapResponse;->fileDescriptor:Landroid/os/ParcelFileDescriptor;
-Landroid/net/IpSecUdpEncapResponse;->port:I
-Landroid/net/IpSecUdpEncapResponse;->resourceId:I
-Landroid/net/IpSecUdpEncapResponse;->status:I
-Landroid/net/IpSecUdpEncapResponse;->TAG:Ljava/lang/String;
 Landroid/net/ITetheringStatsProvider$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/ITetheringStatsProvider$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
 Landroid/net/ITetheringStatsProvider$Stub$Proxy;->getTetherStats(I)Landroid/net/NetworkStats;
@@ -36441,93 +36228,6 @@
 Landroid/net/MobileLinkQualityInfo;->mLteSignalStrength:I
 Landroid/net/MobileLinkQualityInfo;->mMobileNetworkType:I
 Landroid/net/MobileLinkQualityInfo;->mRssi:I
-Landroid/net/nsd/DnsSdTxtRecord;-><init>()V
-Landroid/net/nsd/DnsSdTxtRecord;-><init>(Landroid/net/nsd/DnsSdTxtRecord;)V
-Landroid/net/nsd/DnsSdTxtRecord;-><init>([B)V
-Landroid/net/nsd/DnsSdTxtRecord;->contains(Ljava/lang/String;)Z
-Landroid/net/nsd/DnsSdTxtRecord;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/nsd/DnsSdTxtRecord;->get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/net/nsd/DnsSdTxtRecord;->getKey(I)Ljava/lang/String;
-Landroid/net/nsd/DnsSdTxtRecord;->getRawData()[B
-Landroid/net/nsd/DnsSdTxtRecord;->getValue(I)[B
-Landroid/net/nsd/DnsSdTxtRecord;->getValue(Ljava/lang/String;)[B
-Landroid/net/nsd/DnsSdTxtRecord;->getValueAsString(I)Ljava/lang/String;
-Landroid/net/nsd/DnsSdTxtRecord;->insert([B[BI)V
-Landroid/net/nsd/DnsSdTxtRecord;->keyCount()I
-Landroid/net/nsd/DnsSdTxtRecord;->mData:[B
-Landroid/net/nsd/DnsSdTxtRecord;->mSeperator:B
-Landroid/net/nsd/DnsSdTxtRecord;->remove(Ljava/lang/String;)I
-Landroid/net/nsd/DnsSdTxtRecord;->set(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/net/nsd/DnsSdTxtRecord;->size()I
-Landroid/net/nsd/INsdManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/nsd/INsdManager$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/nsd/INsdManager$Stub$Proxy;->getMessenger()Landroid/os/Messenger;
-Landroid/net/nsd/INsdManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/nsd/INsdManager$Stub$Proxy;->setEnabled(Z)V
-Landroid/net/nsd/INsdManager$Stub;-><init>()V
-Landroid/net/nsd/INsdManager$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/nsd/INsdManager$Stub;->TRANSACTION_getMessenger:I
-Landroid/net/nsd/INsdManager$Stub;->TRANSACTION_setEnabled:I
-Landroid/net/nsd/INsdManager;->setEnabled(Z)V
-Landroid/net/nsd/NsdManager;-><init>(Landroid/content/Context;Landroid/net/nsd/INsdManager;)V
-Landroid/net/nsd/NsdManager;->BASE:I
-Landroid/net/nsd/NsdManager;->checkListener(Ljava/lang/Object;)V
-Landroid/net/nsd/NsdManager;->checkProtocol(I)V
-Landroid/net/nsd/NsdManager;->checkServiceInfo(Landroid/net/nsd/NsdServiceInfo;)V
-Landroid/net/nsd/NsdManager;->DBG:Z
-Landroid/net/nsd/NsdManager;->DISABLE:I
-Landroid/net/nsd/NsdManager;->disconnect()V
-Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES:I
-Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES_FAILED:I
-Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES_STARTED:I
-Landroid/net/nsd/NsdManager;->ENABLE:I
-Landroid/net/nsd/NsdManager;->EVENT_NAMES:Landroid/util/SparseArray;
-Landroid/net/nsd/NsdManager;->fatal(Ljava/lang/String;)V
-Landroid/net/nsd/NsdManager;->FIRST_LISTENER_KEY:I
-Landroid/net/nsd/NsdManager;->getListenerKey(Ljava/lang/Object;)I
-Landroid/net/nsd/NsdManager;->getMessenger()Landroid/os/Messenger;
-Landroid/net/nsd/NsdManager;->getNsdServiceInfoType(Landroid/net/nsd/NsdServiceInfo;)Ljava/lang/String;
-Landroid/net/nsd/NsdManager;->init()V
-Landroid/net/nsd/NsdManager;->mAsyncChannel:Lcom/android/internal/util/AsyncChannel;
-Landroid/net/nsd/NsdManager;->mConnected:Ljava/util/concurrent/CountDownLatch;
-Landroid/net/nsd/NsdManager;->mContext:Landroid/content/Context;
-Landroid/net/nsd/NsdManager;->mHandler:Landroid/net/nsd/NsdManager$ServiceHandler;
-Landroid/net/nsd/NsdManager;->mListenerKey:I
-Landroid/net/nsd/NsdManager;->mListenerMap:Landroid/util/SparseArray;
-Landroid/net/nsd/NsdManager;->mMapLock:Ljava/lang/Object;
-Landroid/net/nsd/NsdManager;->mService:Landroid/net/nsd/INsdManager;
-Landroid/net/nsd/NsdManager;->mServiceMap:Landroid/util/SparseArray;
-Landroid/net/nsd/NsdManager;->nameOf(I)Ljava/lang/String;
-Landroid/net/nsd/NsdManager;->NATIVE_DAEMON_EVENT:I
-Landroid/net/nsd/NsdManager;->nextListenerKey()I
-Landroid/net/nsd/NsdManager;->putListener(Ljava/lang/Object;Landroid/net/nsd/NsdServiceInfo;)I
-Landroid/net/nsd/NsdManager;->REGISTER_SERVICE:I
-Landroid/net/nsd/NsdManager;->REGISTER_SERVICE_FAILED:I
-Landroid/net/nsd/NsdManager;->REGISTER_SERVICE_SUCCEEDED:I
-Landroid/net/nsd/NsdManager;->removeListener(I)V
-Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE:I
-Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE_FAILED:I
-Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE_SUCCEEDED:I
-Landroid/net/nsd/NsdManager;->SERVICE_FOUND:I
-Landroid/net/nsd/NsdManager;->SERVICE_LOST:I
-Landroid/net/nsd/NsdManager;->setEnabled(Z)V
-Landroid/net/nsd/NsdManager;->STOP_DISCOVERY:I
-Landroid/net/nsd/NsdManager;->STOP_DISCOVERY_FAILED:I
-Landroid/net/nsd/NsdManager;->STOP_DISCOVERY_SUCCEEDED:I
-Landroid/net/nsd/NsdManager;->TAG:Ljava/lang/String;
-Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE:I
-Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE_FAILED:I
-Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE_SUCCEEDED:I
-Landroid/net/nsd/NsdServiceInfo;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/net/nsd/NsdServiceInfo;->getTxtRecord()[B
-Landroid/net/nsd/NsdServiceInfo;->getTxtRecordSize()I
-Landroid/net/nsd/NsdServiceInfo;->mHost:Ljava/net/InetAddress;
-Landroid/net/nsd/NsdServiceInfo;->mPort:I
-Landroid/net/nsd/NsdServiceInfo;->mServiceName:Ljava/lang/String;
-Landroid/net/nsd/NsdServiceInfo;->mServiceType:Ljava/lang/String;
-Landroid/net/nsd/NsdServiceInfo;->mTxtRecord:Landroid/util/ArrayMap;
-Landroid/net/nsd/NsdServiceInfo;->setTxtRecords(Ljava/lang/String;)V
-Landroid/net/nsd/NsdServiceInfo;->TAG:Ljava/lang/String;
 Landroid/net/PacProxySelector;-><init>()V
 Landroid/net/PacProxySelector;->mDefaultList:Ljava/util/List;
 Landroid/net/PacProxySelector;->mProxyService:Lcom/android/net/IProxyService;
diff --git a/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
index 79d2521..20d7cc0 100644
--- a/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
@@ -21,7 +21,6 @@
 Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
 Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
 Landroid/net/INetworkPolicyListener$Stub;-><init>()V
-Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
 Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession;
 Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
 Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index a157517..6a685a79 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -64,6 +64,8 @@
         "libwilhelm",
     ],
 
+    header_libs: ["bionic_libc_platform_headers"],
+
     compile_multilib: "both",
 
     cflags: [
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 12083b6..815f945 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,6 +15,7 @@
 
 #include <android-base/macros.h>
 #include <binder/IPCThreadState.h>
+#include <bionic/pac.h>
 #include <hwbinder/IPCThreadState.h>
 #include <utils/Log.h>
 #include <cutils/memory.h>
@@ -182,6 +183,10 @@
       ALOGV("app_process main with argv: %s", argv_String.string());
     }
 
+    // Because of applications that are using PAC instructions incorrectly, PAC
+    // is disabled in application processes for now.
+    ScopedDisablePAC x;
+
     AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
     // Process command line arguments
     // ignore argv[0]
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index c134822..c202f6f 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -39,6 +39,7 @@
         "-modernize-pass-by-value",
         "-modernize-replace-disallow-copy-and-assign-macro",
         "-modernize-return-braced-init-list",
+        "-modernize-use-default-member-init",
         "-modernize-use-equals-default",
         "-modernize-use-nodiscard",
         "-modernize-use-override",
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index a8d6489..1b2d905 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -39,11 +39,9 @@
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
-using android::IPCThreadState;
 using android::base::StringPrintf;
 using android::binder::Status;
 using android::idmap2::BinaryStreamVisitor;
-using android::idmap2::FabricatedOverlay;
 using android::idmap2::FabricatedOverlayContainer;
 using android::idmap2::Idmap;
 using android::idmap2::IdmapHeader;
diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp
index 23d80d7..0d8bd40 100644
--- a/cmds/incidentd/src/WorkDirectory.cpp
+++ b/cmds/incidentd/src/WorkDirectory.cpp
@@ -280,7 +280,7 @@
                 // Lower privacy policy (less restrictive) wins.
                 report->set_privacy_policy(args.getPrivacyPolicy());
             }
-            report->set_all_sections(report->all_sections() | args.all());
+            report->set_all_sections(report->all_sections() || args.all());
             for (int section: args.sections()) {
                 if (!has_section(*report, section)) {
                     report->add_section(section);
diff --git a/core/api/current.txt b/core/api/current.txt
index a87bb4a..b66779a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7185,6 +7185,7 @@
     method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName);
     method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName);
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig();
     method public int getRequiredPasswordComplexity();
     method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName);
     method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
@@ -7327,6 +7328,7 @@
     method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
     method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
     method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean);
+    method public void setPreferentialNetworkServiceConfig(@NonNull android.app.admin.PreferentialNetworkServiceConfig);
     method public void setPreferentialNetworkServiceEnabled(boolean);
     method public void setProfileEnabled(@NonNull android.content.ComponentName);
     method public void setProfileName(@NonNull android.content.ComponentName, String);
@@ -7572,6 +7574,32 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
   }
 
+  public final class PreferentialNetworkServiceConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public int[] getExcludedUids();
+    method @NonNull public int[] getIncludedUids();
+    method public int getNetworkId();
+    method public boolean isEnabled();
+    method public boolean isFallbackToDefaultConnectionAllowed();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.PreferentialNetworkServiceConfig> CREATOR;
+    field public static final int PREFERENTIAL_NETWORK_ID_1 = 1; // 0x1
+    field public static final int PREFERENTIAL_NETWORK_ID_2 = 2; // 0x2
+    field public static final int PREFERENTIAL_NETWORK_ID_3 = 3; // 0x3
+    field public static final int PREFERENTIAL_NETWORK_ID_4 = 4; // 0x4
+    field public static final int PREFERENTIAL_NETWORK_ID_5 = 5; // 0x5
+  }
+
+  public static final class PreferentialNetworkServiceConfig.Builder {
+    ctor public PreferentialNetworkServiceConfig.Builder();
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig build();
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setEnabled(boolean);
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setExcludedUids(@NonNull int[]);
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(boolean);
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setIncludedUids(@NonNull int[]);
+    method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setNetworkId(int);
+  }
+
   public class SecurityLog {
     ctor public SecurityLog();
     field public static final int LEVEL_ERROR = 3; // 0x3
@@ -8616,1317 +8644,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
-    method public void finalize();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isA2dpPlaying(android.bluetooth.BluetoothDevice);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PLAYING_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
-    field public static final int STATE_NOT_PLAYING = 11; // 0xb
-    field public static final int STATE_PLAYING = 10; // 0xa
-  }
-
-  public final class BluetoothAdapter {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean cancelDiscovery();
-    method public static boolean checkBluetoothAddress(String);
-    method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, "android.permission.LOCAL_MAC_ADDRESS"}) public String getAddress();
-    method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser();
-    method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
-    method @Deprecated public static android.bluetooth.BluetoothAdapter getDefaultAdapter();
-    method public int getLeMaximumAdvertisingDataLength();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getProfileConnectionState(int);
-    method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
-    method public android.bluetooth.BluetoothDevice getRemoteDevice(String);
-    method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
-    method public int getState();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
-    method public boolean isEnabled();
-    method public boolean isLe2MPhySupported();
-    method public int isLeAudioSupported();
-    method public boolean isLeCodedPhySupported();
-    method public boolean isLeExtendedAdvertisingSupported();
-    method public boolean isLePeriodicAdvertisingSupported();
-    method public int isLePeriodicAdvertisingSyncTransferSenderSupported();
-    method public boolean isMultipleAdvertisementSupported();
-    method public boolean isOffloadedFilteringSupported();
-    method public boolean isOffloadedScanBatchingSupported();
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setName(String);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startDiscovery();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
-    field public static final String ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
-    field public static final int ERROR = -2147483648; // 0x80000000
-    field public static final String EXTRA_CONNECTION_STATE = "android.bluetooth.adapter.extra.CONNECTION_STATE";
-    field public static final String EXTRA_DISCOVERABLE_DURATION = "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
-    field public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
-    field public static final String EXTRA_PREVIOUS_CONNECTION_STATE = "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
-    field public static final String EXTRA_PREVIOUS_SCAN_MODE = "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
-    field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.adapter.extra.PREVIOUS_STATE";
-    field public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
-    field public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
-    field public static final int SCAN_MODE_CONNECTABLE = 21; // 0x15
-    field public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; // 0x17
-    field public static final int SCAN_MODE_NONE = 20; // 0x14
-    field public static final int STATE_CONNECTED = 2; // 0x2
-    field public static final int STATE_CONNECTING = 1; // 0x1
-    field public static final int STATE_DISCONNECTED = 0; // 0x0
-    field public static final int STATE_DISCONNECTING = 3; // 0x3
-    field public static final int STATE_OFF = 10; // 0xa
-    field public static final int STATE_ON = 12; // 0xc
-    field public static final int STATE_TURNING_OFF = 13; // 0xd
-    field public static final int STATE_TURNING_ON = 11; // 0xb
-  }
-
-  public static interface BluetoothAdapter.LeScanCallback {
-    method public void onLeScan(android.bluetooth.BluetoothDevice, int, byte[]);
-  }
-
-  public class BluetoothAssignedNumbers {
-    field public static final int AAMP_OF_AMERICA = 190; // 0xbe
-    field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a
-    field public static final int ACE_SENSOR = 188; // 0xbc
-    field public static final int ADIDAS = 195; // 0xc3
-    field public static final int ADVANCED_PANMOBIL_SYSTEMS = 145; // 0x91
-    field public static final int AIROHA_TECHNOLOGY = 148; // 0x94
-    field public static final int ALCATEL = 36; // 0x24
-    field public static final int ALPWISE = 154; // 0x9a
-    field public static final int AMICCOM_ELECTRONICS = 192; // 0xc0
-    field public static final int APLIX = 189; // 0xbd
-    field public static final int APPLE = 76; // 0x4c
-    field public static final int APT_LICENSING = 79; // 0x4f
-    field public static final int ARCHOS = 207; // 0xcf
-    field public static final int ARP_DEVICES = 168; // 0xa8
-    field public static final int ATHEROS_COMMUNICATIONS = 69; // 0x45
-    field public static final int ATMEL = 19; // 0x13
-    field public static final int AUSTCO_COMMUNICATION_SYSTEMS = 213; // 0xd5
-    field public static final int AUTONET_MOBILE = 127; // 0x7f
-    field public static final int AVAGO = 78; // 0x4e
-    field public static final int AVM_BERLIN = 31; // 0x1f
-    field public static final int A_AND_D_ENGINEERING = 105; // 0x69
-    field public static final int A_AND_R_CAMBRIDGE = 124; // 0x7c
-    field public static final int BANDSPEED = 32; // 0x20
-    field public static final int BAND_XI_INTERNATIONAL = 100; // 0x64
-    field public static final int BDE_TECHNOLOGY = 180; // 0xb4
-    field public static final int BEATS_ELECTRONICS = 204; // 0xcc
-    field public static final int BEAUTIFUL_ENTERPRISE = 108; // 0x6c
-    field public static final int BEKEY = 178; // 0xb2
-    field public static final int BELKIN_INTERNATIONAL = 92; // 0x5c
-    field public static final int BINAURIC = 203; // 0xcb
-    field public static final int BIOSENTRONICS = 219; // 0xdb
-    field public static final int BLUEGIGA = 71; // 0x47
-    field public static final int BLUERADIOS = 133; // 0x85
-    field public static final int BLUETOOTH_SIG = 63; // 0x3f
-    field public static final int BLUETREK_TECHNOLOGIES = 151; // 0x97
-    field public static final int BOSE = 158; // 0x9e
-    field public static final int BRIARTEK = 109; // 0x6d
-    field public static final int BROADCOM = 15; // 0xf
-    field public static final int CAEN_RFID = 170; // 0xaa
-    field public static final int CAMBRIDGE_SILICON_RADIO = 10; // 0xa
-    field public static final int CATC = 52; // 0x34
-    field public static final int CINETIX = 175; // 0xaf
-    field public static final int CLARINOX_TECHNOLOGIES = 179; // 0xb3
-    field public static final int COLORFY = 156; // 0x9c
-    field public static final int COMMIL = 51; // 0x33
-    field public static final int CONEXANT_SYSTEMS = 28; // 0x1c
-    field public static final int CONNECTBLUE = 113; // 0x71
-    field public static final int CONTINENTAL_AUTOMOTIVE = 75; // 0x4b
-    field public static final int CONWISE_TECHNOLOGY = 66; // 0x42
-    field public static final int CREATIVE_TECHNOLOGY = 118; // 0x76
-    field public static final int C_TECHNOLOGIES = 38; // 0x26
-    field public static final int DANLERS = 225; // 0xe1
-    field public static final int DELORME_PUBLISHING_COMPANY = 128; // 0x80
-    field public static final int DEXCOM = 208; // 0xd0
-    field public static final int DIALOG_SEMICONDUCTOR = 210; // 0xd2
-    field public static final int DIGIANSWER = 12; // 0xc
-    field public static final int ECLIPSE = 53; // 0x35
-    field public static final int ECOTEST = 136; // 0x88
-    field public static final int ELGATO_SYSTEMS = 206; // 0xce
-    field public static final int EM_MICROELECTRONIC_MARIN = 90; // 0x5a
-    field public static final int EQUINOX_AG = 134; // 0x86
-    field public static final int ERICSSON_TECHNOLOGY = 0; // 0x0
-    field public static final int EVLUMA = 201; // 0xc9
-    field public static final int FREE2MOVE = 83; // 0x53
-    field public static final int FUNAI_ELECTRIC = 144; // 0x90
-    field public static final int GARMIN_INTERNATIONAL = 135; // 0x87
-    field public static final int GCT_SEMICONDUCTOR = 45; // 0x2d
-    field public static final int GELO = 200; // 0xc8
-    field public static final int GENEQ = 194; // 0xc2
-    field public static final int GENERAL_MOTORS = 104; // 0x68
-    field public static final int GENNUM = 59; // 0x3b
-    field public static final int GEOFORCE = 157; // 0x9d
-    field public static final int GIBSON_GUITARS = 98; // 0x62
-    field public static final int GN_NETCOM = 103; // 0x67
-    field public static final int GN_RESOUND = 137; // 0x89
-    field public static final int GOOGLE = 224; // 0xe0
-    field public static final int GREEN_THROTTLE_GAMES = 172; // 0xac
-    field public static final int GROUP_SENSE = 115; // 0x73
-    field public static final int HANLYNN_TECHNOLOGIES = 123; // 0x7b
-    field public static final int HARMAN_INTERNATIONAL = 87; // 0x57
-    field public static final int HEWLETT_PACKARD = 101; // 0x65
-    field public static final int HITACHI = 41; // 0x29
-    field public static final int HOSIDEN = 221; // 0xdd
-    field public static final int IBM = 3; // 0x3
-    field public static final int INFINEON_TECHNOLOGIES = 9; // 0x9
-    field public static final int INGENIEUR_SYSTEMGRUPPE_ZAHN = 171; // 0xab
-    field public static final int INTEGRATED_SILICON_SOLUTION = 65; // 0x41
-    field public static final int INTEGRATED_SYSTEM_SOLUTION = 57; // 0x39
-    field public static final int INTEL = 2; // 0x2
-    field public static final int INVENTEL = 30; // 0x1e
-    field public static final int IPEXTREME = 61; // 0x3d
-    field public static final int I_TECH_DYNAMIC_GLOBAL_DISTRIBUTION = 153; // 0x99
-    field public static final int JAWBONE = 138; // 0x8a
-    field public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS = 155; // 0x9b
-    field public static final int JOHNSON_CONTROLS = 185; // 0xb9
-    field public static final int J_AND_M = 82; // 0x52
-    field public static final int KAWANTECH = 212; // 0xd4
-    field public static final int KC_TECHNOLOGY = 22; // 0x16
-    field public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 160; // 0xa0
-    field public static final int LAIRD_TECHNOLOGIES = 119; // 0x77
-    field public static final int LESSWIRE = 121; // 0x79
-    field public static final int LG_ELECTRONICS = 196; // 0xc4
-    field public static final int LINAK = 164; // 0xa4
-    field public static final int LUCENT = 7; // 0x7
-    field public static final int LUDUS_HELSINKI = 132; // 0x84
-    field public static final int MACRONIX = 44; // 0x2c
-    field public static final int MAGNETI_MARELLI = 169; // 0xa9
-    field public static final int MANSELLA = 33; // 0x21
-    field public static final int MARVELL = 72; // 0x48
-    field public static final int MATSUSHITA_ELECTRIC = 58; // 0x3a
-    field public static final int MC10 = 202; // 0xca
-    field public static final int MEDIATEK = 70; // 0x46
-    field public static final int MESO_INTERNATIONAL = 182; // 0xb6
-    field public static final int META_WATCH = 163; // 0xa3
-    field public static final int MEWTEL_TECHNOLOGY = 47; // 0x2f
-    field public static final int MICOMMAND = 99; // 0x63
-    field public static final int MICROCHIP_TECHNOLOGY = 205; // 0xcd
-    field public static final int MICROSOFT = 6; // 0x6
-    field public static final int MINDTREE = 106; // 0x6a
-    field public static final int MISFIT_WEARABLES = 223; // 0xdf
-    field public static final int MITEL_SEMICONDUCTOR = 16; // 0x10
-    field public static final int MITSUBISHI_ELECTRIC = 20; // 0x14
-    field public static final int MOBILIAN_CORPORATION = 55; // 0x37
-    field public static final int MONSTER = 112; // 0x70
-    field public static final int MOTOROLA = 8; // 0x8
-    field public static final int MSTAR_SEMICONDUCTOR = 122; // 0x7a
-    field public static final int MUZIK = 222; // 0xde
-    field public static final int NEC = 34; // 0x22
-    field public static final int NEC_LIGHTING = 149; // 0x95
-    field public static final int NEWLOGIC = 23; // 0x17
-    field public static final int NIKE = 120; // 0x78
-    field public static final int NINE_SOLUTIONS = 102; // 0x66
-    field public static final int NOKIA_MOBILE_PHONES = 1; // 0x1
-    field public static final int NORDIC_SEMICONDUCTOR = 89; // 0x59
-    field public static final int NORWOOD_SYSTEMS = 46; // 0x2e
-    field public static final int ODM_TECHNOLOGY = 150; // 0x96
-    field public static final int OMEGAWAVE = 174; // 0xae
-    field public static final int ONSET_COMPUTER = 197; // 0xc5
-    field public static final int OPEN_INTERFACE = 39; // 0x27
-    field public static final int OTL_DYNAMICS = 165; // 0xa5
-    field public static final int PANDA_OCEAN = 166; // 0xa6
-    field public static final int PARROT = 67; // 0x43
-    field public static final int PARTHUS_TECHNOLOGIES = 14; // 0xe
-    field public static final int PASSIF_SEMICONDUCTOR = 176; // 0xb0
-    field public static final int PETER_SYSTEMTECHNIK = 173; // 0xad
-    field public static final int PHILIPS_SEMICONDUCTORS = 37; // 0x25
-    field public static final int PLANTRONICS = 85; // 0x55
-    field public static final int POLAR_ELECTRO = 107; // 0x6b
-    field public static final int POLAR_ELECTRO_EUROPE = 209; // 0xd1
-    field public static final int PROCTER_AND_GAMBLE = 220; // 0xdc
-    field public static final int QUALCOMM = 29; // 0x1d
-    field public static final int QUALCOMM_CONNECTED_EXPERIENCES = 216; // 0xd8
-    field public static final int QUALCOMM_INNOVATION_CENTER = 184; // 0xb8
-    field public static final int QUALCOMM_LABS = 140; // 0x8c
-    field public static final int QUALCOMM_TECHNOLOGIES = 215; // 0xd7
-    field public static final int QUINTIC = 142; // 0x8e
-    field public static final int QUUPPA = 199; // 0xc7
-    field public static final int RALINK_TECHNOLOGY = 91; // 0x5b
-    field public static final int RDA_MICROELECTRONICS = 97; // 0x61
-    field public static final int REALTEK_SEMICONDUCTOR = 93; // 0x5d
-    field public static final int RED_M = 50; // 0x32
-    field public static final int RENESAS_TECHNOLOGY = 54; // 0x36
-    field public static final int RESEARCH_IN_MOTION = 60; // 0x3c
-    field public static final int RF_MICRO_DEVICES = 40; // 0x28
-    field public static final int RIVIERAWAVES = 96; // 0x60
-    field public static final int ROHDE_AND_SCHWARZ = 25; // 0x19
-    field public static final int RTX_TELECOM = 21; // 0x15
-    field public static final int SAMSUNG_ELECTRONICS = 117; // 0x75
-    field public static final int SARIS_CYCLING_GROUP = 177; // 0xb1
-    field public static final int SEERS_TECHNOLOGY = 125; // 0x7d
-    field public static final int SEIKO_EPSON = 64; // 0x40
-    field public static final int SELFLY = 198; // 0xc6
-    field public static final int SEMILINK = 226; // 0xe2
-    field public static final int SENNHEISER_COMMUNICATIONS = 130; // 0x82
-    field public static final int SHANGHAI_SUPER_SMART_ELECTRONICS = 114; // 0x72
-    field public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY = 193; // 0xc1
-    field public static final int SIGNIA_TECHNOLOGIES = 27; // 0x1b
-    field public static final int SILICON_WAVE = 11; // 0xb
-    field public static final int SIRF_TECHNOLOGY = 80; // 0x50
-    field public static final int SOCKET_MOBILE = 68; // 0x44
-    field public static final int SONY_ERICSSON = 86; // 0x56
-    field public static final int SOUND_ID = 111; // 0x6f
-    field public static final int SPORTS_TRACKING_TECHNOLOGIES = 126; // 0x7e
-    field public static final int SR_MEDIZINELEKTRONIK = 161; // 0xa1
-    field public static final int STACCATO_COMMUNICATIONS = 77; // 0x4d
-    field public static final int STALMART_TECHNOLOGY = 191; // 0xbf
-    field public static final int STARKEY_LABORATORIES = 186; // 0xba
-    field public static final int STOLLMAN_E_PLUS_V = 143; // 0x8f
-    field public static final int STONESTREET_ONE = 94; // 0x5e
-    field public static final int ST_MICROELECTRONICS = 48; // 0x30
-    field public static final int SUMMIT_DATA_COMMUNICATIONS = 110; // 0x6e
-    field public static final int SUUNTO = 159; // 0x9f
-    field public static final int SWIRL_NETWORKS = 181; // 0xb5
-    field public static final int SYMBOL_TECHNOLOGIES = 42; // 0x2a
-    field public static final int SYNOPSYS = 49; // 0x31
-    field public static final int SYSTEMS_AND_CHIPS = 62; // 0x3e
-    field public static final int S_POWER_ELECTRONICS = 187; // 0xbb
-    field public static final int TAIXINGBANG_TECHNOLOGY = 211; // 0xd3
-    field public static final int TENOVIS = 43; // 0x2b
-    field public static final int TERAX = 56; // 0x38
-    field public static final int TEXAS_INSTRUMENTS = 13; // 0xd
-    field public static final int THINKOPTICS = 146; // 0x92
-    field public static final int THREECOM = 5; // 0x5
-    field public static final int THREE_DIJOY = 84; // 0x54
-    field public static final int THREE_DSP = 73; // 0x49
-    field public static final int TIMEKEEPING_SYSTEMS = 131; // 0x83
-    field public static final int TIMEX_GROUP_USA = 214; // 0xd6
-    field public static final int TOPCORN_POSITIONING_SYSTEMS = 139; // 0x8b
-    field public static final int TOSHIBA = 4; // 0x4
-    field public static final int TRANSILICA = 24; // 0x18
-    field public static final int TRELAB = 183; // 0xb7
-    field public static final int TTPCOM = 26; // 0x1a
-    field public static final int TXTR = 218; // 0xda
-    field public static final int TZERO_TECHNOLOGIES = 81; // 0x51
-    field public static final int UNIVERSAL_ELECTRONICS = 147; // 0x93
-    field public static final int VERTU = 162; // 0xa2
-    field public static final int VISTEON = 167; // 0xa7
-    field public static final int VIZIO = 88; // 0x58
-    field public static final int VOYETRA_TURTLE_BEACH = 217; // 0xd9
-    field public static final int WAVEPLUS_TECHNOLOGY = 35; // 0x23
-    field public static final int WICENTRIC = 95; // 0x5f
-    field public static final int WIDCOMM = 17; // 0x11
-    field public static final int WUXI_VIMICRO = 129; // 0x81
-    field public static final int ZEEVO = 18; // 0x12
-    field public static final int ZER01_TV = 152; // 0x98
-    field public static final int ZOMM = 116; // 0x74
-    field public static final int ZSCAN_SOFTWARE = 141; // 0x8d
-  }
-
-  public final class BluetoothClass implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getDeviceClass();
-    method public int getMajorDeviceClass();
-    method public boolean hasService(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothClass> CREATOR;
-  }
-
-  public static class BluetoothClass.Device {
-    ctor public BluetoothClass.Device();
-    field public static final int AUDIO_VIDEO_CAMCORDER = 1076; // 0x434
-    field public static final int AUDIO_VIDEO_CAR_AUDIO = 1056; // 0x420
-    field public static final int AUDIO_VIDEO_HANDSFREE = 1032; // 0x408
-    field public static final int AUDIO_VIDEO_HEADPHONES = 1048; // 0x418
-    field public static final int AUDIO_VIDEO_HIFI_AUDIO = 1064; // 0x428
-    field public static final int AUDIO_VIDEO_LOUDSPEAKER = 1044; // 0x414
-    field public static final int AUDIO_VIDEO_MICROPHONE = 1040; // 0x410
-    field public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 1052; // 0x41c
-    field public static final int AUDIO_VIDEO_SET_TOP_BOX = 1060; // 0x424
-    field public static final int AUDIO_VIDEO_UNCATEGORIZED = 1024; // 0x400
-    field public static final int AUDIO_VIDEO_VCR = 1068; // 0x42c
-    field public static final int AUDIO_VIDEO_VIDEO_CAMERA = 1072; // 0x430
-    field public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 1088; // 0x440
-    field public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 1084; // 0x43c
-    field public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 1096; // 0x448
-    field public static final int AUDIO_VIDEO_VIDEO_MONITOR = 1080; // 0x438
-    field public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 1028; // 0x404
-    field public static final int COMPUTER_DESKTOP = 260; // 0x104
-    field public static final int COMPUTER_HANDHELD_PC_PDA = 272; // 0x110
-    field public static final int COMPUTER_LAPTOP = 268; // 0x10c
-    field public static final int COMPUTER_PALM_SIZE_PC_PDA = 276; // 0x114
-    field public static final int COMPUTER_SERVER = 264; // 0x108
-    field public static final int COMPUTER_UNCATEGORIZED = 256; // 0x100
-    field public static final int COMPUTER_WEARABLE = 280; // 0x118
-    field public static final int HEALTH_BLOOD_PRESSURE = 2308; // 0x904
-    field public static final int HEALTH_DATA_DISPLAY = 2332; // 0x91c
-    field public static final int HEALTH_GLUCOSE = 2320; // 0x910
-    field public static final int HEALTH_PULSE_OXIMETER = 2324; // 0x914
-    field public static final int HEALTH_PULSE_RATE = 2328; // 0x918
-    field public static final int HEALTH_THERMOMETER = 2312; // 0x908
-    field public static final int HEALTH_UNCATEGORIZED = 2304; // 0x900
-    field public static final int HEALTH_WEIGHING = 2316; // 0x90c
-    field public static final int PHONE_CELLULAR = 516; // 0x204
-    field public static final int PHONE_CORDLESS = 520; // 0x208
-    field public static final int PHONE_ISDN = 532; // 0x214
-    field public static final int PHONE_MODEM_OR_GATEWAY = 528; // 0x210
-    field public static final int PHONE_SMART = 524; // 0x20c
-    field public static final int PHONE_UNCATEGORIZED = 512; // 0x200
-    field public static final int TOY_CONTROLLER = 2064; // 0x810
-    field public static final int TOY_DOLL_ACTION_FIGURE = 2060; // 0x80c
-    field public static final int TOY_GAME = 2068; // 0x814
-    field public static final int TOY_ROBOT = 2052; // 0x804
-    field public static final int TOY_UNCATEGORIZED = 2048; // 0x800
-    field public static final int TOY_VEHICLE = 2056; // 0x808
-    field public static final int WEARABLE_GLASSES = 1812; // 0x714
-    field public static final int WEARABLE_HELMET = 1808; // 0x710
-    field public static final int WEARABLE_JACKET = 1804; // 0x70c
-    field public static final int WEARABLE_PAGER = 1800; // 0x708
-    field public static final int WEARABLE_UNCATEGORIZED = 1792; // 0x700
-    field public static final int WEARABLE_WRIST_WATCH = 1796; // 0x704
-  }
-
-  public static class BluetoothClass.Device.Major {
-    ctor public BluetoothClass.Device.Major();
-    field public static final int AUDIO_VIDEO = 1024; // 0x400
-    field public static final int COMPUTER = 256; // 0x100
-    field public static final int HEALTH = 2304; // 0x900
-    field public static final int IMAGING = 1536; // 0x600
-    field public static final int MISC = 0; // 0x0
-    field public static final int NETWORKING = 768; // 0x300
-    field public static final int PERIPHERAL = 1280; // 0x500
-    field public static final int PHONE = 512; // 0x200
-    field public static final int TOY = 2048; // 0x800
-    field public static final int UNCATEGORIZED = 7936; // 0x1f00
-    field public static final int WEARABLE = 1792; // 0x700
-  }
-
-  public static final class BluetoothClass.Service {
-    ctor public BluetoothClass.Service();
-    field public static final int AUDIO = 2097152; // 0x200000
-    field public static final int CAPTURE = 524288; // 0x80000
-    field public static final int INFORMATION = 8388608; // 0x800000
-    field public static final int LE_AUDIO = 16384; // 0x4000
-    field public static final int LIMITED_DISCOVERABILITY = 8192; // 0x2000
-    field public static final int NETWORKING = 131072; // 0x20000
-    field public static final int OBJECT_TRANSFER = 1048576; // 0x100000
-    field public static final int POSITIONING = 65536; // 0x10000
-    field public static final int RENDER = 262144; // 0x40000
-    field public static final int TELEPHONY = 4194304; // 0x400000
-  }
-
-  public final class BluetoothCodecConfig implements android.os.Parcelable {
-    ctor public BluetoothCodecConfig(int);
-    method public int describeContents();
-    method public int getBitsPerSample();
-    method public int getChannelMode();
-    method public int getCodecPriority();
-    method public long getCodecSpecific1();
-    method public long getCodecSpecific2();
-    method public long getCodecSpecific3();
-    method public long getCodecSpecific4();
-    method public int getCodecType();
-    method public static int getMaxCodecType();
-    method public int getSampleRate();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
-    field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
-    field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
-    field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
-    field public static final int CHANNEL_MODE_MONO = 1; // 0x1
-    field public static final int CHANNEL_MODE_NONE = 0; // 0x0
-    field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
-    field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
-    field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
-    field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
-    field public static final int SAMPLE_RATE_176400 = 16; // 0x10
-    field public static final int SAMPLE_RATE_192000 = 32; // 0x20
-    field public static final int SAMPLE_RATE_44100 = 1; // 0x1
-    field public static final int SAMPLE_RATE_48000 = 2; // 0x2
-    field public static final int SAMPLE_RATE_88200 = 4; // 0x4
-    field public static final int SAMPLE_RATE_96000 = 8; // 0x8
-    field public static final int SAMPLE_RATE_NONE = 0; // 0x0
-    field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
-    field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
-    field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
-    field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
-    field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
-    field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
-  }
-
-  public static final class BluetoothCodecConfig.Builder {
-    ctor public BluetoothCodecConfig.Builder();
-    method @NonNull public android.bluetooth.BluetoothCodecConfig build();
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setBitsPerSample(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setChannelMode(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecPriority(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific1(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific2(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific3(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific4(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecType(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setSampleRate(int);
-  }
-
-  public final class BluetoothCodecStatus implements android.os.Parcelable {
-    ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>);
-    method public int describeContents();
-    method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
-    method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsLocalCapabilities();
-    method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsSelectableCapabilities();
-    method public boolean isCodecConfigSelectable(@Nullable android.bluetooth.BluetoothCodecConfig);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
-    field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
-  }
-
-  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_CONNECT) 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 @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond();
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
-    method public int describeContents();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean fetchUuidsWithSdp();
-    method public String getAddress();
-    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getAlias();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothClass getBluetoothClass();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBondState();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int setAlias(@Nullable String);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.device.action.ALIAS_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_UUID = "android.bluetooth.device.action.UUID";
-    field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
-    field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
-    field public static final int BOND_BONDED = 12; // 0xc
-    field public static final int BOND_BONDING = 11; // 0xb
-    field public static final int BOND_NONE = 10; // 0xa
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothDevice> CREATOR;
-    field public static final int DEVICE_TYPE_CLASSIC = 1; // 0x1
-    field public static final int DEVICE_TYPE_DUAL = 3; // 0x3
-    field public static final int DEVICE_TYPE_LE = 2; // 0x2
-    field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int ERROR = -2147483648; // 0x80000000
-    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";
-    field public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
-    field public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
-    field public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
-    field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
-    field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
-    field public static final int PHY_LE_1M = 1; // 0x1
-    field public static final int PHY_LE_1M_MASK = 1; // 0x1
-    field public static final int PHY_LE_2M = 2; // 0x2
-    field public static final int PHY_LE_2M_MASK = 2; // 0x2
-    field public static final int PHY_LE_CODED = 3; // 0x3
-    field public static final int PHY_LE_CODED_MASK = 4; // 0x4
-    field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
-    field public static final int PHY_OPTION_S2 = 1; // 0x1
-    field public static final int PHY_OPTION_S8 = 2; // 0x2
-    field public static final int TRANSPORT_AUTO = 0; // 0x0
-    field public static final int TRANSPORT_BREDR = 1; // 0x1
-    field public static final int TRANSPORT_LE = 2; // 0x2
-  }
-
-  public final class BluetoothGatt implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean beginReliableWrite();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void disconnect();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean discoverServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean executeReliableWrite();
-    method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @Deprecated public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method public android.bluetooth.BluetoothDevice getDevice();
-    method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readRemoteRssi();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestConnectionPriority(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]);
-    field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
-    field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
-    field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
-    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
-    field public static final int GATT_READ_NOT_PERMITTED = 2; // 0x2
-    field public static final int GATT_REQUEST_NOT_SUPPORTED = 6; // 0x6
-    field public static final int GATT_SUCCESS = 0; // 0x0
-    field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
-  }
-
-  public abstract class BluetoothGattCallback {
-    ctor public BluetoothGattCallback();
-    method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
-    method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]);
-    method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
-    method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
-    method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
-    method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
-    method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
-    method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]);
-    method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
-    method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
-    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
-    method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int);
-    method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
-    method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
-    method public void onServiceChanged(@NonNull android.bluetooth.BluetoothGatt);
-    method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
-  }
-
-  public class BluetoothGattCharacteristic implements android.os.Parcelable {
-    ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
-    method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
-    method public int describeContents();
-    method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
-    method @Deprecated public Float getFloatValue(int, int);
-    method public int getInstanceId();
-    method @Deprecated public Integer getIntValue(int, int);
-    method public int getPermissions();
-    method public int getProperties();
-    method public android.bluetooth.BluetoothGattService getService();
-    method @Deprecated public String getStringValue(int);
-    method public java.util.UUID getUuid();
-    method @Deprecated public byte[] getValue();
-    method public int getWriteType();
-    method @Deprecated public boolean setValue(byte[]);
-    method @Deprecated public boolean setValue(int, int, int);
-    method @Deprecated public boolean setValue(int, int, int, int);
-    method @Deprecated public boolean setValue(String);
-    method public void setWriteType(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
-    field public static final int FORMAT_FLOAT = 52; // 0x34
-    field public static final int FORMAT_SFLOAT = 50; // 0x32
-    field public static final int FORMAT_SINT16 = 34; // 0x22
-    field public static final int FORMAT_SINT32 = 36; // 0x24
-    field public static final int FORMAT_SINT8 = 33; // 0x21
-    field public static final int FORMAT_UINT16 = 18; // 0x12
-    field public static final int FORMAT_UINT32 = 20; // 0x14
-    field public static final int FORMAT_UINT8 = 17; // 0x11
-    field public static final int PERMISSION_READ = 1; // 0x1
-    field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
-    field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
-    field public static final int PERMISSION_WRITE = 16; // 0x10
-    field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
-    field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
-    field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
-    field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
-    field public static final int PROPERTY_BROADCAST = 1; // 0x1
-    field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
-    field public static final int PROPERTY_INDICATE = 32; // 0x20
-    field public static final int PROPERTY_NOTIFY = 16; // 0x10
-    field public static final int PROPERTY_READ = 2; // 0x2
-    field public static final int PROPERTY_SIGNED_WRITE = 64; // 0x40
-    field public static final int PROPERTY_WRITE = 8; // 0x8
-    field public static final int PROPERTY_WRITE_NO_RESPONSE = 4; // 0x4
-    field public static final int WRITE_TYPE_DEFAULT = 2; // 0x2
-    field public static final int WRITE_TYPE_NO_RESPONSE = 1; // 0x1
-    field public static final int WRITE_TYPE_SIGNED = 4; // 0x4
-    field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors;
-  }
-
-  public class BluetoothGattDescriptor implements android.os.Parcelable {
-    ctor public BluetoothGattDescriptor(java.util.UUID, int);
-    method public int describeContents();
-    method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
-    method public int getPermissions();
-    method public java.util.UUID getUuid();
-    method @Deprecated public byte[] getValue();
-    method @Deprecated public boolean setValue(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
-    field public static final byte[] DISABLE_NOTIFICATION_VALUE;
-    field public static final byte[] ENABLE_INDICATION_VALUE;
-    field public static final byte[] ENABLE_NOTIFICATION_VALUE;
-    field public static final int PERMISSION_READ = 1; // 0x1
-    field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
-    field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
-    field public static final int PERMISSION_WRITE = 16; // 0x10
-    field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
-    field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
-    field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
-    field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
-  }
-
-  public final class BluetoothGattServer implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean addService(android.bluetooth.BluetoothGattService);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void cancelConnection(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void clearServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice, boolean);
-    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
-  }
-
-  public abstract class BluetoothGattServerCallback {
-    ctor public BluetoothGattServerCallback();
-    method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
-    method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
-    method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
-    method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor);
-    method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]);
-    method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
-    method public void onMtuChanged(android.bluetooth.BluetoothDevice, int);
-    method public void onNotificationSent(android.bluetooth.BluetoothDevice, int);
-    method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int);
-    method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int);
-    method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
-  }
-
-  public class BluetoothGattService implements android.os.Parcelable {
-    ctor public BluetoothGattService(java.util.UUID, int);
-    method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method public boolean addService(android.bluetooth.BluetoothGattService);
-    method public int describeContents();
-    method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
-    method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
-    method public int getInstanceId();
-    method public int getType();
-    method public java.util.UUID getUuid();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR;
-    field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
-    field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
-    field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics;
-    field protected java.util.List<android.bluetooth.BluetoothGattService> mIncludedServices;
-  }
-
-  public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isAudioConnected(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isNoiseReductionSupported(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isVoiceRecognitionSupported(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendVendorSpecificResultCode(android.bluetooth.BluetoothDevice, String, String);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startVoiceRecognition(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean stopVoiceRecognition(android.bluetooth.BluetoothDevice);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
-    field public static final int AT_CMD_TYPE_ACTION = 4; // 0x4
-    field public static final int AT_CMD_TYPE_BASIC = 3; // 0x3
-    field public static final int AT_CMD_TYPE_READ = 0; // 0x0
-    field public static final int AT_CMD_TYPE_SET = 2; // 0x2
-    field public static final int AT_CMD_TYPE_TEST = 1; // 0x1
-    field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
-    field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
-    field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
-    field public static final int STATE_AUDIO_CONNECTED = 12; // 0xc
-    field public static final int STATE_AUDIO_CONNECTING = 11; // 0xb
-    field public static final int STATE_AUDIO_DISCONNECTED = 10; // 0xa
-    field public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
-    field public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
-  }
-
-  @Deprecated public final class BluetoothHealth implements android.bluetooth.BluetoothProfile {
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerSinkAppConfiguration(String, int, android.bluetooth.BluetoothHealthCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration);
-    field @Deprecated public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1
-    field @Deprecated public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0
-    field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3
-    field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2
-    field @Deprecated public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa
-    field @Deprecated public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb
-    field @Deprecated public static final int SINK_ROLE = 2; // 0x2
-    field @Deprecated public static final int SOURCE_ROLE = 1; // 0x1
-    field @Deprecated public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2
-    field @Deprecated public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1
-    field @Deprecated public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0
-    field @Deprecated public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3
-  }
-
-  @Deprecated public final class BluetoothHealthAppConfiguration implements android.os.Parcelable {
-    method @Deprecated public int describeContents();
-    method @Deprecated public int getDataType();
-    method @Deprecated public String getName();
-    method @Deprecated public int getRole();
-    method @Deprecated public void writeToParcel(android.os.Parcel, int);
-    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHealthAppConfiguration> CREATOR;
-  }
-
-  @Deprecated public abstract class BluetoothHealthCallback {
-    ctor @Deprecated public BluetoothHealthCallback();
-    method @Deprecated @BinderThread public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int);
-    method @Deprecated @BinderThread public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
-  }
-
-  public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerApp(android.bluetooth.BluetoothHidDeviceAppSdpSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, java.util.concurrent.Executor, android.bluetooth.BluetoothHidDevice.Callback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean replyReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean reportError(android.bluetooth.BluetoothDevice, byte);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendReport(android.bluetooth.BluetoothDevice, int, byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterApp();
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
-    field public static final byte ERROR_RSP_INVALID_PARAM = 4; // 0x4
-    field public static final byte ERROR_RSP_INVALID_RPT_ID = 2; // 0x2
-    field public static final byte ERROR_RSP_NOT_READY = 1; // 0x1
-    field public static final byte ERROR_RSP_SUCCESS = 0; // 0x0
-    field public static final byte ERROR_RSP_UNKNOWN = 14; // 0xe
-    field public static final byte ERROR_RSP_UNSUPPORTED_REQ = 3; // 0x3
-    field public static final byte PROTOCOL_BOOT_MODE = 0; // 0x0
-    field public static final byte PROTOCOL_REPORT_MODE = 1; // 0x1
-    field public static final byte REPORT_TYPE_FEATURE = 3; // 0x3
-    field public static final byte REPORT_TYPE_INPUT = 1; // 0x1
-    field public static final byte REPORT_TYPE_OUTPUT = 2; // 0x2
-    field public static final byte SUBCLASS1_COMBO = -64; // 0xffffffc0
-    field public static final byte SUBCLASS1_KEYBOARD = 64; // 0x40
-    field public static final byte SUBCLASS1_MOUSE = -128; // 0xffffff80
-    field public static final byte SUBCLASS1_NONE = 0; // 0x0
-    field public static final byte SUBCLASS2_CARD_READER = 6; // 0x6
-    field public static final byte SUBCLASS2_DIGITIZER_TABLET = 5; // 0x5
-    field public static final byte SUBCLASS2_GAMEPAD = 2; // 0x2
-    field public static final byte SUBCLASS2_JOYSTICK = 1; // 0x1
-    field public static final byte SUBCLASS2_REMOTE_CONTROL = 3; // 0x3
-    field public static final byte SUBCLASS2_SENSING_DEVICE = 4; // 0x4
-    field public static final byte SUBCLASS2_UNCATEGORIZED = 0; // 0x0
-  }
-
-  public abstract static class BluetoothHidDevice.Callback {
-    ctor public BluetoothHidDevice.Callback();
-    method public void onAppStatusChanged(android.bluetooth.BluetoothDevice, boolean);
-    method public void onConnectionStateChanged(android.bluetooth.BluetoothDevice, int);
-    method public void onGetReport(android.bluetooth.BluetoothDevice, byte, byte, int);
-    method public void onInterruptData(android.bluetooth.BluetoothDevice, byte, byte[]);
-    method public void onSetProtocol(android.bluetooth.BluetoothDevice, byte);
-    method public void onSetReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
-    method public void onVirtualCableUnplug(android.bluetooth.BluetoothDevice);
-  }
-
-  public final class BluetoothHidDeviceAppQosSettings implements android.os.Parcelable {
-    ctor public BluetoothHidDeviceAppQosSettings(int, int, int, int, int, int);
-    method public int describeContents();
-    method public int getDelayVariation();
-    method public int getLatency();
-    method public int getPeakBandwidth();
-    method public int getServiceType();
-    method public int getTokenBucketSize();
-    method public int getTokenRate();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppQosSettings> CREATOR;
-    field public static final int MAX = -1; // 0xffffffff
-    field public static final int SERVICE_BEST_EFFORT = 1; // 0x1
-    field public static final int SERVICE_GUARANTEED = 2; // 0x2
-    field public static final int SERVICE_NO_TRAFFIC = 0; // 0x0
-  }
-
-  public final class BluetoothHidDeviceAppSdpSettings implements android.os.Parcelable {
-    ctor public BluetoothHidDeviceAppSdpSettings(String, String, String, byte, byte[]);
-    method public int describeContents();
-    method public String getDescription();
-    method public byte[] getDescriptors();
-    method public String getName();
-    method public String getProvider();
-    method public byte getSubclass();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
-  }
-
-  public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method public void close();
-    method protected void finalize();
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getGroupId(@NonNull android.bluetooth.BluetoothDevice);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothLeAudioCodecConfig {
-    method @NonNull public String getCodecName();
-    method public int getCodecType();
-    method public static int getMaxCodecType();
-    field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
-    field public static final int SOURCE_CODEC_TYPE_LC3 = 0; // 0x0
-  }
-
-  public static final class BluetoothLeAudioCodecConfig.Builder {
-    ctor public BluetoothLeAudioCodecConfig.Builder();
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build();
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int);
-  }
-
-  public final class BluetoothManager {
-    method public android.bluetooth.BluetoothAdapter getAdapter();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int, int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGattServer openGattServer(android.content.Context, android.bluetooth.BluetoothGattServerCallback);
-  }
-
-  public interface BluetoothProfile {
-    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method 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
-    field public static final int GATT_SERVER = 8; // 0x8
-    field public static final int HEADSET = 1; // 0x1
-    field @Deprecated public static final int HEALTH = 3; // 0x3
-    field public static final int HEARING_AID = 21; // 0x15
-    field public static final int HID_DEVICE = 19; // 0x13
-    field public static final int LE_AUDIO = 22; // 0x16
-    field public static final int SAP = 10; // 0xa
-    field public static final int STATE_CONNECTED = 2; // 0x2
-    field public static final int STATE_CONNECTING = 1; // 0x1
-    field public static final int STATE_DISCONNECTED = 0; // 0x0
-    field public static final int STATE_DISCONNECTING = 3; // 0x3
-  }
-
-  public static interface BluetoothProfile.ServiceListener {
-    method public void onServiceConnected(int, android.bluetooth.BluetoothProfile);
-    method public void onServiceDisconnected(int);
-  }
-
-  public final class BluetoothServerSocket implements java.io.Closeable {
-    method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
-    method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
-    method public void close() throws java.io.IOException;
-    method public int getPsm();
-  }
-
-  public final class BluetoothSocket implements java.io.Closeable {
-    method public void close() throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void connect() throws java.io.IOException;
-    method public int getConnectionType();
-    method public java.io.InputStream getInputStream() throws java.io.IOException;
-    method public int getMaxReceivePacketSize();
-    method public int getMaxTransmitPacketSize();
-    method public java.io.OutputStream getOutputStream() throws java.io.IOException;
-    method public android.bluetooth.BluetoothDevice getRemoteDevice();
-    method public boolean isConnected();
-    field public static final int TYPE_L2CAP = 3; // 0x3
-    field public static final int TYPE_RFCOMM = 1; // 0x1
-    field public static final int TYPE_SCO = 2; // 0x2
-  }
-
-  public final class BluetoothStatusCodes {
-    field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
-    field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
-    field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
-    field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa
-    field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65
-    field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66
-    field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
-    field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8
-    field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9
-    field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
-    field public static final int SUCCESS = 0; // 0x0
-  }
-
-}
-
-package android.bluetooth.le {
-
-  public abstract class AdvertiseCallback {
-    ctor public AdvertiseCallback();
-    method public void onStartFailure(int);
-    method public void onStartSuccess(android.bluetooth.le.AdvertiseSettings);
-    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
-    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
-    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
-    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
-    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
-  }
-
-  public final class AdvertiseData implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean getIncludeDeviceName();
-    method public boolean getIncludeTxPowerLevel();
-    method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
-    method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
-    method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
-    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
-    method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR;
-  }
-
-  public static final class AdvertiseData.Builder {
-    ctor public AdvertiseData.Builder();
-    method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]);
-    method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
-    method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid);
-    method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
-    method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData);
-    method public android.bluetooth.le.AdvertiseData build();
-    method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
-    method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean);
-  }
-
-  public final class AdvertiseSettings implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getMode();
-    method public int getTimeout();
-    method public int getTxPowerLevel();
-    method public boolean isConnectable();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1
-    field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2
-    field public static final int ADVERTISE_MODE_LOW_POWER = 0; // 0x0
-    field public static final int ADVERTISE_TX_POWER_HIGH = 3; // 0x3
-    field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1
-    field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2
-    field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseSettings> CREATOR;
-  }
-
-  public static final class AdvertiseSettings.Builder {
-    ctor public AdvertiseSettings.Builder();
-    method public android.bluetooth.le.AdvertiseSettings build();
-    method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int);
-    method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean);
-    method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int);
-    method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
-  }
-
-  public final class AdvertisingSet {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void enableAdvertising(boolean, int, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setScanResponseData(android.bluetooth.le.AdvertiseData);
-  }
-
-  public abstract class AdvertisingSetCallback {
-    ctor public AdvertisingSetCallback();
-    method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
-    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
-    method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
-    method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
-    method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
-    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
-    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
-    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
-    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
-    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
-    field public static final int ADVERTISE_SUCCESS = 0; // 0x0
-  }
-
-  public final class AdvertisingSetParameters implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getInterval();
-    method public int getPrimaryPhy();
-    method public int getSecondaryPhy();
-    method public int getTxPowerLevel();
-    method public boolean includeTxPower();
-    method public boolean isAnonymous();
-    method public boolean isConnectable();
-    method public boolean isLegacy();
-    method public boolean isScannable();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
-    field public static final int INTERVAL_HIGH = 1600; // 0x640
-    field public static final int INTERVAL_LOW = 160; // 0xa0
-    field public static final int INTERVAL_MAX = 16777215; // 0xffffff
-    field public static final int INTERVAL_MEDIUM = 400; // 0x190
-    field public static final int INTERVAL_MIN = 160; // 0xa0
-    field public static final int TX_POWER_HIGH = 1; // 0x1
-    field public static final int TX_POWER_LOW = -15; // 0xfffffff1
-    field public static final int TX_POWER_MAX = 1; // 0x1
-    field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9
-    field public static final int TX_POWER_MIN = -127; // 0xffffff81
-    field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb
-  }
-
-  public static final class AdvertisingSetParameters.Builder {
-    ctor public AdvertisingSetParameters.Builder();
-    method public android.bluetooth.le.AdvertisingSetParameters build();
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
-  }
-
-  public final class BluetoothLeAdvertiser {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
-  }
-
-  public final class BluetoothLeScanner {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int startScan(@Nullable java.util.List<android.bluetooth.le.ScanFilter>, @Nullable android.bluetooth.le.ScanSettings, @NonNull android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.app.PendingIntent);
-    field public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
-    field public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
-    field public static final String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
-  }
-
-  public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean getIncludeTxPower();
-    method public int getInterval();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR;
-  }
-
-  public static final class PeriodicAdvertisingParameters.Builder {
-    ctor public PeriodicAdvertisingParameters.Builder();
-    method public android.bluetooth.le.PeriodicAdvertisingParameters build();
-    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
-    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
-  }
-
-  public abstract class ScanCallback {
-    ctor public ScanCallback();
-    method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
-    method public void onScanFailed(int);
-    method public void onScanResult(int, android.bluetooth.le.ScanResult);
-    field public static final int SCAN_FAILED_ALREADY_STARTED = 1; // 0x1
-    field public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2; // 0x2
-    field public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; // 0x4
-    field public static final int SCAN_FAILED_INTERNAL_ERROR = 3; // 0x3
-  }
-
-  public final class ScanFilter implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public String getDeviceAddress();
-    method @Nullable public String getDeviceName();
-    method @Nullable public byte[] getManufacturerData();
-    method @Nullable public byte[] getManufacturerDataMask();
-    method public int getManufacturerId();
-    method @Nullable public byte[] getServiceData();
-    method @Nullable public byte[] getServiceDataMask();
-    method @Nullable public android.os.ParcelUuid getServiceDataUuid();
-    method @Nullable public android.os.ParcelUuid getServiceSolicitationUuid();
-    method @Nullable public android.os.ParcelUuid getServiceSolicitationUuidMask();
-    method @Nullable public android.os.ParcelUuid getServiceUuid();
-    method @Nullable public android.os.ParcelUuid getServiceUuidMask();
-    method public boolean matches(android.bluetooth.le.ScanResult);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanFilter> CREATOR;
-  }
-
-  public static final class ScanFilter.Builder {
-    ctor public ScanFilter.Builder();
-    method public android.bluetooth.le.ScanFilter build();
-    method public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(String);
-    method public android.bluetooth.le.ScanFilter.Builder setDeviceName(String);
-    method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[]);
-    method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]);
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid);
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid, @Nullable android.os.ParcelUuid);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
-  }
-
-  public final class ScanRecord {
-    method public int getAdvertiseFlags();
-    method public byte[] getBytes();
-    method @Nullable public String getDeviceName();
-    method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
-    method @Nullable public byte[] getManufacturerSpecificData(int);
-    method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
-    method @Nullable public byte[] getServiceData(android.os.ParcelUuid);
-    method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
-    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
-    method public int getTxPowerLevel();
-  }
-
-  public final class ScanResult implements android.os.Parcelable {
-    ctor @Deprecated public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
-    ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long);
-    method public int describeContents();
-    method public int getAdvertisingSid();
-    method public int getDataStatus();
-    method public android.bluetooth.BluetoothDevice getDevice();
-    method public int getPeriodicAdvertisingInterval();
-    method public int getPrimaryPhy();
-    method public int getRssi();
-    method @Nullable public android.bluetooth.le.ScanRecord getScanRecord();
-    method public int getSecondaryPhy();
-    method public long getTimestampNanos();
-    method public int getTxPower();
-    method public boolean isConnectable();
-    method public boolean isLegacy();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
-    field public static final int DATA_COMPLETE = 0; // 0x0
-    field public static final int DATA_TRUNCATED = 2; // 0x2
-    field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0
-    field public static final int PHY_UNUSED = 0; // 0x0
-    field public static final int SID_NOT_PRESENT = 255; // 0xff
-    field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f
-  }
-
-  public final class ScanSettings implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getCallbackType();
-    method public boolean getLegacy();
-    method public int getPhy();
-    method public long getReportDelayMillis();
-    method public int getScanMode();
-    method public int getScanResultType();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1
-    field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
-    field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanSettings> CREATOR;
-    field public static final int MATCH_MODE_AGGRESSIVE = 1; // 0x1
-    field public static final int MATCH_MODE_STICKY = 2; // 0x2
-    field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
-    field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
-    field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
-    field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
-    field public static final int SCAN_MODE_BALANCED = 1; // 0x1
-    field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
-    field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
-    field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
-  }
-
-  public static final class ScanSettings.Builder {
-    ctor public ScanSettings.Builder();
-    method public android.bluetooth.le.ScanSettings build();
-    method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
-    method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean);
-    method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
-    method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
-    method public android.bluetooth.le.ScanSettings.Builder setPhy(int);
-    method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
-    method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
-  }
-
-  public final class TransportBlock implements android.os.Parcelable {
-    ctor public TransportBlock(int, int, int, @Nullable byte[]);
-    method public int describeContents();
-    method public int getOrgId();
-    method public int getTdsFlags();
-    method @Nullable public byte[] getTransportData();
-    method public int getTransportDataLength();
-    method @Nullable public byte[] toByteArray();
-    method public int totalBytes();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR;
-  }
-
-  public final class TransportDiscoveryData implements android.os.Parcelable {
-    ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>);
-    ctor public TransportDiscoveryData(@NonNull byte[]);
-    method public int describeContents();
-    method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks();
-    method public int getTransportDataType();
-    method @Nullable public byte[] toByteArray();
-    method public int totalBytes();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR;
-  }
-
-}
-
 package android.companion {
 
   public final class AssociationRequest implements android.os.Parcelable {
@@ -17980,10 +16697,12 @@
     ctor public BiometricPrompt.CryptoObject(@NonNull java.security.Signature);
     ctor public BiometricPrompt.CryptoObject(@NonNull javax.crypto.Cipher);
     ctor public BiometricPrompt.CryptoObject(@NonNull javax.crypto.Mac);
-    ctor public BiometricPrompt.CryptoObject(@NonNull android.security.identity.IdentityCredential);
+    ctor @Deprecated public BiometricPrompt.CryptoObject(@NonNull android.security.identity.IdentityCredential);
+    ctor public BiometricPrompt.CryptoObject(@NonNull android.security.identity.PresentationSession);
     method public javax.crypto.Cipher getCipher();
-    method @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
+    method @Deprecated @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
     method public javax.crypto.Mac getMac();
+    method @Nullable public android.security.identity.PresentationSession getPresentationSession();
     method public java.security.Signature getSignature();
   }
 
@@ -20395,6 +19114,7 @@
     method public boolean isSink();
     method public boolean isSource();
     field public static final int TYPE_AUX_LINE = 19; // 0x13
+    field public static final int TYPE_BLE_BROADCAST = 30; // 0x1e
     field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
     field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b
     field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
@@ -21879,9 +20599,11 @@
     field public static final int COLOR_Format24bitBGR888 = 12; // 0xc
     field @Deprecated public static final int COLOR_Format24bitRGB888 = 11; // 0xb
     field @Deprecated public static final int COLOR_Format25bitARGB1888 = 14; // 0xe
+    field public static final int COLOR_Format32bitABGR2101010 = 2130750114; // 0x7f00aaa2
     field public static final int COLOR_Format32bitABGR8888 = 2130747392; // 0x7f00a000
     field @Deprecated public static final int COLOR_Format32bitARGB8888 = 16; // 0x10
     field @Deprecated public static final int COLOR_Format32bitBGRA8888 = 15; // 0xf
+    field public static final int COLOR_Format64bitABGRFloat = 2130710294; // 0x7f000f16
     field @Deprecated public static final int COLOR_Format8bitRGB332 = 2; // 0x2
     field @Deprecated public static final int COLOR_FormatCbYCrY = 27; // 0x1b
     field @Deprecated public static final int COLOR_FormatCrYCbY = 28; // 0x1c
@@ -21914,10 +20636,12 @@
     field @Deprecated public static final int COLOR_FormatYUV422SemiPlanar = 24; // 0x18
     field public static final int COLOR_FormatYUV444Flexible = 2135181448; // 0x7f444888
     field @Deprecated public static final int COLOR_FormatYUV444Interleaved = 29; // 0x1d
+    field public static final int COLOR_FormatYUVP010 = 54; // 0x36
     field @Deprecated public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
     field @Deprecated public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final String FEATURE_AdaptivePlayback = "adaptive-playback";
     field public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
+    field public static final String FEATURE_EncodingStatistics = "encoding-statistics";
     field public static final String FEATURE_FrameParsing = "frame-parsing";
     field public static final String FEATURE_IntraRefresh = "intra-refresh";
     field public static final String FEATURE_LowLatency = "low-latency";
@@ -22001,11 +20725,14 @@
     field public static final int AVCProfileHigh422 = 32; // 0x20
     field public static final int AVCProfileHigh444 = 64; // 0x40
     field public static final int AVCProfileMain = 2; // 0x2
+    field public static final int DolbyVisionLevel8k30 = 1024; // 0x400
+    field public static final int DolbyVisionLevel8k60 = 2048; // 0x800
     field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
     field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
     field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
     field public static final int DolbyVisionLevelHd24 = 1; // 0x1
     field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+    field public static final int DolbyVisionLevelUhd120 = 512; // 0x200
     field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
     field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
     field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
@@ -22691,6 +21418,7 @@
     field public static final String KEY_OPERATING_RATE = "operating-rate";
     field public static final String KEY_OUTPUT_REORDER_DEPTH = "output-reorder-depth";
     field public static final String KEY_PCM_ENCODING = "pcm-encoding";
+    field public static final String KEY_PICTURE_TYPE = "picture-type";
     field public static final String KEY_PIXEL_ASPECT_RATIO_HEIGHT = "sar-height";
     field public static final String KEY_PIXEL_ASPECT_RATIO_WIDTH = "sar-width";
     field public static final String KEY_PREPEND_HEADER_TO_SYNC_FRAMES = "prepend-sps-pps-to-idr-frames";
@@ -22708,6 +21436,8 @@
     field public static final String KEY_TILE_HEIGHT = "tile-height";
     field public static final String KEY_TILE_WIDTH = "tile-width";
     field public static final String KEY_TRACK_ID = "track-id";
+    field public static final String KEY_VIDEO_ENCODING_STATISTICS_LEVEL = "video-encoding-statistics-level";
+    field public static final String KEY_VIDEO_QP_AVERAGE = "video-qp-average";
     field public static final String KEY_VIDEO_QP_B_MAX = "video-qp-b-max";
     field public static final String KEY_VIDEO_QP_B_MIN = "video-qp-b-min";
     field public static final String KEY_VIDEO_QP_I_MAX = "video-qp-i-max";
@@ -22752,12 +21482,18 @@
     field public static final String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled";
     field public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
     field public static final String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+    field public static final int PICTURE_TYPE_B = 3; // 0x3
+    field public static final int PICTURE_TYPE_I = 1; // 0x1
+    field public static final int PICTURE_TYPE_P = 2; // 0x2
+    field public static final int PICTURE_TYPE_UNKNOWN = 0; // 0x0
     field public static final int TYPE_BYTE_BUFFER = 5; // 0x5
     field public static final int TYPE_FLOAT = 3; // 0x3
     field public static final int TYPE_INTEGER = 1; // 0x1
     field public static final int TYPE_LONG = 2; // 0x2
     field public static final int TYPE_NULL = 0; // 0x0
     field public static final int TYPE_STRING = 4; // 0x4
+    field public static final int VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1; // 0x1
+    field public static final int VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0; // 0x0
   }
 
   public final class MediaMetadata implements android.os.Parcelable {
@@ -26463,6 +25199,14 @@
     method public int getUid();
   }
 
+  public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+    ctor public EthernetNetworkSpecifier(@NonNull String);
+    method public int describeContents();
+    method @Nullable public String getInterfaceName();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR;
+  }
+
   public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
     method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
     method public int getMaxMtu();
@@ -26481,84 +25225,18 @@
 
   public static final class Ikev2VpnProfile.Builder {
     ctor public Ikev2VpnProfile.Builder(@NonNull String, @NonNull String);
+    ctor public Ikev2VpnProfile.Builder(@NonNull android.net.ipsec.ike.IkeTunnelConnectionParams);
     method @NonNull public android.net.Ikev2VpnProfile build();
     method @NonNull public android.net.Ikev2VpnProfile.Builder setAllowedAlgorithms(@NonNull java.util.List<java.lang.String>);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey, @Nullable java.security.cert.X509Certificate);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthPsk(@NonNull byte[]);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthUsernamePassword(@NonNull String, @NonNull String, @Nullable java.security.cert.X509Certificate);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setBypassable(boolean);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setLocalRoutesExcluded(boolean);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setMaxMtu(int);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setMetered(boolean);
     method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo);
-  }
-
-  public final class IpSecAlgorithm implements android.os.Parcelable {
-    ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[]);
-    ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[], int);
-    method public int describeContents();
-    method @NonNull public byte[] getKey();
-    method @NonNull public String getName();
-    method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
-    method public int getTruncationLengthBits();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final String AUTH_AES_CMAC = "cmac(aes)";
-    field public static final String AUTH_AES_XCBC = "xcbc(aes)";
-    field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
-    field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
-    field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
-    field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
-    field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
-    field public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
-    field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
-    field public static final String CRYPT_AES_CBC = "cbc(aes)";
-    field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
-  }
-
-  public final class IpSecManager {
-    method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
-    method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
-    method public void applyTransportModeTransform(@NonNull java.net.Socket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(@NonNull java.net.DatagramSocket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(@NonNull java.io.FileDescriptor, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
-    method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransforms(@NonNull java.net.Socket) throws java.io.IOException;
-    method public void removeTransportModeTransforms(@NonNull java.net.DatagramSocket) throws java.io.IOException;
-    method public void removeTransportModeTransforms(@NonNull java.io.FileDescriptor) throws java.io.IOException;
-    field public static final int DIRECTION_IN = 0; // 0x0
-    field public static final int DIRECTION_OUT = 1; // 0x1
-  }
-
-  public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
-  }
-
-  public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable {
-    method public void close();
-    method public int getSpi();
-  }
-
-  public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException {
-    method public int getSpi();
-  }
-
-  public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close() throws java.io.IOException;
-    method public java.io.FileDescriptor getFileDescriptor();
-    method public int getPort();
-  }
-
-  public final class IpSecTransform implements java.lang.AutoCloseable {
-    method public void close();
-  }
-
-  public static class IpSecTransform.Builder {
-    ctor public IpSecTransform.Builder(@NonNull android.content.Context);
-    method @NonNull public android.net.IpSecTransform buildTransportModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
-    method @NonNull public android.net.IpSecTransform.Builder setAuthenticatedEncryption(@NonNull android.net.IpSecAlgorithm);
-    method @NonNull public android.net.IpSecTransform.Builder setAuthentication(@NonNull android.net.IpSecAlgorithm);
-    method @NonNull public android.net.IpSecTransform.Builder setEncryption(@NonNull android.net.IpSecAlgorithm);
-    method @NonNull public android.net.IpSecTransform.Builder setIpv4Encapsulation(@NonNull android.net.IpSecManager.UdpEncapsulationSocket, int);
+    method @NonNull public android.net.Ikev2VpnProfile.Builder setRequiresInternetValidation(boolean);
   }
 
   public class LocalServerSocket implements java.io.Closeable {
@@ -26632,6 +25310,8 @@
   }
 
   public abstract class PlatformVpnProfile {
+    method public final boolean areLocalRoutesExcluded();
+    method public final boolean getRequiresInternetValidation();
     method public final int getType();
     method @NonNull public final String getTypeString();
     field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
@@ -26868,8 +25548,26 @@
   public class VpnManager {
     method public void deleteProvisionedVpnProfile();
     method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
-    method public void startProvisionedVpnProfile();
+    method @Deprecated public void startProvisionedVpnProfile();
+    method @NonNull public String startProvisionedVpnProfileSession();
     method public void stopProvisionedVpnProfile();
+    field public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
+    field public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER = "android.net.category.EVENT_DEACTIVATED_BY_USER";
+    field public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
+    field public static final String CATEGORY_EVENT_NETWORK_ERROR = "android.net.category.EVENT_NETWORK_ERROR";
+    field public static final int ERROR_CLASS_NOT_RECOVERABLE = 1; // 0x1
+    field public static final int ERROR_CLASS_RECOVERABLE = 2; // 0x2
+    field public static final int ERROR_CODE_NETWORK_IO = 3; // 0x3
+    field public static final int ERROR_CODE_NETWORK_LOST = 2; // 0x2
+    field public static final int ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT = 1; // 0x1
+    field public static final int ERROR_CODE_NETWORK_UNKNOWN_HOST = 0; // 0x0
+    field public static final String EXTRA_ERROR_CLASS = "android.net.extra.ERROR_CLASS";
+    field public static final String EXTRA_ERROR_CODE = "android.net.extra.ERROR_CODE";
+    field public static final String EXTRA_SESSION_KEY = "android.net.extra.SESSION_KEY";
+    field public static final String EXTRA_TIMESTAMP = "android.net.extra.TIMESTAMP";
+    field public static final String EXTRA_UNDERLYING_LINK_PROPERTIES = "android.net.extra.UNDERLYING_LINK_PROPERTIES";
+    field public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
+    field public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES = "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
   }
 
   public class VpnService extends android.app.Service {
@@ -26896,11 +25594,13 @@
     method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull java.net.InetAddress);
     method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull String);
     method @NonNull public android.net.VpnService.Builder addRoute(@NonNull java.net.InetAddress, int);
+    method @NonNull public android.net.VpnService.Builder addRoute(@NonNull android.net.IpPrefix);
     method @NonNull public android.net.VpnService.Builder addRoute(@NonNull String, int);
     method @NonNull public android.net.VpnService.Builder addSearchDomain(@NonNull String);
     method @NonNull public android.net.VpnService.Builder allowBypass();
     method @NonNull public android.net.VpnService.Builder allowFamily(int);
     method @Nullable public android.os.ParcelFileDescriptor establish();
+    method @NonNull public android.net.VpnService.Builder excludeRoute(@NonNull android.net.IpPrefix);
     method @NonNull public android.net.VpnService.Builder setBlocking(boolean);
     method @NonNull public android.net.VpnService.Builder setConfigureIntent(@NonNull android.app.PendingIntent);
     method @NonNull public android.net.VpnService.Builder setHttpProxy(@NonNull android.net.ProxyInfo);
@@ -26980,65 +25680,6 @@
 
 }
 
-package android.net.nsd {
-
-  public final class NsdManager {
-    method public void discoverServices(String, int, android.net.nsd.NsdManager.DiscoveryListener);
-    method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener);
-    method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
-    method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener);
-    method public void unregisterService(android.net.nsd.NsdManager.RegistrationListener);
-    field public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
-    field public static final String EXTRA_NSD_STATE = "nsd_state";
-    field public static final int FAILURE_ALREADY_ACTIVE = 3; // 0x3
-    field public static final int FAILURE_INTERNAL_ERROR = 0; // 0x0
-    field public static final int FAILURE_MAX_LIMIT = 4; // 0x4
-    field public static final int NSD_STATE_DISABLED = 1; // 0x1
-    field public static final int NSD_STATE_ENABLED = 2; // 0x2
-    field public static final int PROTOCOL_DNS_SD = 1; // 0x1
-  }
-
-  public static interface NsdManager.DiscoveryListener {
-    method public void onDiscoveryStarted(String);
-    method public void onDiscoveryStopped(String);
-    method public void onServiceFound(android.net.nsd.NsdServiceInfo);
-    method public void onServiceLost(android.net.nsd.NsdServiceInfo);
-    method public void onStartDiscoveryFailed(String, int);
-    method public void onStopDiscoveryFailed(String, int);
-  }
-
-  public static interface NsdManager.RegistrationListener {
-    method public void onRegistrationFailed(android.net.nsd.NsdServiceInfo, int);
-    method public void onServiceRegistered(android.net.nsd.NsdServiceInfo);
-    method public void onServiceUnregistered(android.net.nsd.NsdServiceInfo);
-    method public void onUnregistrationFailed(android.net.nsd.NsdServiceInfo, int);
-  }
-
-  public static interface NsdManager.ResolveListener {
-    method public void onResolveFailed(android.net.nsd.NsdServiceInfo, int);
-    method public void onServiceResolved(android.net.nsd.NsdServiceInfo);
-  }
-
-  public final class NsdServiceInfo implements android.os.Parcelable {
-    ctor public NsdServiceInfo();
-    method public int describeContents();
-    method public java.util.Map<java.lang.String,byte[]> getAttributes();
-    method public java.net.InetAddress getHost();
-    method public int getPort();
-    method public String getServiceName();
-    method public String getServiceType();
-    method public void removeAttribute(String);
-    method public void setAttribute(String, String);
-    method public void setHost(java.net.InetAddress);
-    method public void setPort(int);
-    method public void setServiceName(String);
-    method public void setServiceType(String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.nsd.NsdServiceInfo> CREATOR;
-  }
-
-}
-
 package android.net.rtp {
 
   @Deprecated public class AudioCodec {
@@ -27288,6 +25929,8 @@
     ctor public VcnCellUnderlyingNetworkTemplate.Builder();
     method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate build();
     method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setMetered(int);
+    method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setMinDownstreamBandwidthKbps(int, int);
+    method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setMinUpstreamBandwidthKbps(int, int);
     method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setOperatorPlmnIds(@NonNull java.util.Set<java.lang.String>);
     method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setOpportunistic(int);
     method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setRoaming(int);
@@ -27348,6 +25991,10 @@
 
   public abstract class VcnUnderlyingNetworkTemplate {
     method public int getMetered();
+    method public int getMinEntryDownstreamBandwidthKbps();
+    method public int getMinEntryUpstreamBandwidthKbps();
+    method public int getMinExitDownstreamBandwidthKbps();
+    method public int getMinExitUpstreamBandwidthKbps();
     field public static final int MATCH_ANY = 0; // 0x0
     field public static final int MATCH_FORBIDDEN = 2; // 0x2
     field public static final int MATCH_REQUIRED = 1; // 0x1
@@ -27361,6 +26008,8 @@
     ctor public VcnWifiUnderlyingNetworkTemplate.Builder();
     method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate build();
     method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate.Builder setMetered(int);
+    method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate.Builder setMinDownstreamBandwidthKbps(int, int);
+    method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate.Builder setMinUpstreamBandwidthKbps(int, int);
     method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate.Builder setSsids(@NonNull java.util.Set<java.lang.String>);
   }
 
@@ -27540,7 +26189,6 @@
     field public static final String CATEGORY_PAYMENT = "payment";
     field public static final String EXTRA_CATEGORY = "category";
     field public static final String EXTRA_SERVICE_COMPONENT = "component";
-    field public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
     field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
     field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
     field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
@@ -30986,6 +29634,7 @@
     field public static final int Q = 29; // 0x1d
     field public static final int R = 30; // 0x1e
     field public static final int S = 31; // 0x1f
+    field public static final int S_V2 = 32; // 0x20
     field public static final int TIRAMISU = 10000; // 0x2710
   }
 
@@ -31580,6 +30229,9 @@
     method @Nullable public byte[] createByteArray();
     method @Nullable public char[] createCharArray();
     method @Nullable public double[] createDoubleArray();
+    method @Nullable public <T> T createFixedArray(@NonNull Class<T>, @NonNull int...);
+    method @Nullable public <T, S extends android.os.IInterface> T createFixedArray(@NonNull Class<T>, @NonNull java.util.function.Function<android.os.IBinder,S>, @NonNull int...);
+    method @Nullable public <T, S extends android.os.Parcelable> T createFixedArray(@NonNull Class<T>, @NonNull android.os.Parcelable.Creator<S>, @NonNull int...);
     method @Nullable public float[] createFloatArray();
     method @Nullable public int[] createIntArray();
     method @Nullable public <T extends android.os.IInterface> T[] createInterfaceArray(@NonNull java.util.function.IntFunction<T[]>, @NonNull java.util.function.Function<android.os.IBinder,T>);
@@ -31620,6 +30272,9 @@
     method public void readException();
     method public void readException(int, String);
     method public android.os.ParcelFileDescriptor readFileDescriptor();
+    method public <T> void readFixedArray(@NonNull T);
+    method public <T, S extends android.os.IInterface> void readFixedArray(@NonNull T, @NonNull java.util.function.Function<android.os.IBinder,S>);
+    method public <T, S extends android.os.Parcelable> void readFixedArray(@NonNull T, @NonNull android.os.Parcelable.Creator<S>);
     method public float readFloat();
     method public void readFloatArray(@NonNull float[]);
     method @Deprecated @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
@@ -31663,6 +30318,7 @@
     method public void setDataCapacity(int);
     method public void setDataPosition(int);
     method public void setDataSize(int);
+    method public void setPropagateAllowBlocking();
     method public void unmarshall(@NonNull byte[], int, int);
     method public void writeArray(@Nullable Object[]);
     method public void writeBinderArray(@Nullable android.os.IBinder[]);
@@ -31678,6 +30334,7 @@
     method public void writeDoubleArray(@Nullable double[]);
     method public void writeException(@NonNull Exception);
     method public void writeFileDescriptor(@NonNull java.io.FileDescriptor);
+    method public <T> void writeFixedArray(@Nullable T, int, @NonNull int...);
     method public void writeFloat(float);
     method public void writeFloatArray(@Nullable float[]);
     method public void writeInt(int);
@@ -37494,6 +36151,28 @@
     method @Deprecated @NonNull public android.security.KeyPairGeneratorSpec.Builder setSubject(@NonNull javax.security.auth.x500.X500Principal);
   }
 
+  public class KeyStoreException extends java.lang.Exception {
+    method public int getNumericErrorCode();
+    method public boolean isSystemError();
+    method public boolean isTransientFailure();
+    method public boolean requiresUserAuthentication();
+    field public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9; // 0x9
+    field public static final int ERROR_ID_ATTESTATION_FAILURE = 8; // 0x8
+    field public static final int ERROR_INCORRECT_USAGE = 13; // 0xd
+    field public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4; // 0x4
+    field public static final int ERROR_KEYMINT_FAILURE = 10; // 0xa
+    field public static final int ERROR_KEYSTORE_FAILURE = 11; // 0xb
+    field public static final int ERROR_KEYSTORE_UNINITIALIZED = 3; // 0x3
+    field public static final int ERROR_KEY_CORRUPTED = 7; // 0x7
+    field public static final int ERROR_KEY_DOES_NOT_EXIST = 6; // 0x6
+    field public static final int ERROR_KEY_NOT_TEMPORALLY_VALID = 14; // 0xe
+    field public static final int ERROR_KEY_OPERATION_EXPIRED = 15; // 0xf
+    field public static final int ERROR_OTHER = 1; // 0x1
+    field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5
+    field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc
+    field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2
+  }
+
   @Deprecated public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
     method @Deprecated public boolean isEncryptionRequired();
   }
@@ -37540,6 +36219,51 @@
     ctor public CipherSuiteNotSupportedException(@NonNull String, @NonNull Throwable);
   }
 
+  public class CredentialDataRequest {
+    method @NonNull public java.util.Map<java.lang.String,java.util.Collection<java.lang.String>> getDeviceSignedEntriesToRequest();
+    method @NonNull public java.util.Map<java.lang.String,java.util.Collection<java.lang.String>> getIssuerSignedEntriesToRequest();
+    method @Nullable public byte[] getReaderSignature();
+    method @Nullable public byte[] getRequestMessage();
+    method public boolean isAllowUsingExhaustedKeys();
+    method public boolean isAllowUsingExpiredKeys();
+    method public boolean isIncrementUseCount();
+  }
+
+  public static final class CredentialDataRequest.Builder {
+    ctor public CredentialDataRequest.Builder();
+    method @NonNull public android.security.identity.CredentialDataRequest build();
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setAllowUsingExhaustedKeys(boolean);
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setAllowUsingExpiredKeys(boolean);
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setDeviceSignedEntriesToRequest(@NonNull java.util.Map<java.lang.String,java.util.Collection<java.lang.String>>);
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setIncrementUseCount(boolean);
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setIssuerSignedEntriesToRequest(@NonNull java.util.Map<java.lang.String,java.util.Collection<java.lang.String>>);
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setReaderSignature(@NonNull byte[]);
+    method @NonNull public android.security.identity.CredentialDataRequest.Builder setRequestMessage(@NonNull byte[]);
+  }
+
+  public abstract class CredentialDataResult {
+    method @Nullable public abstract byte[] getDeviceMac();
+    method @NonNull public abstract byte[] getDeviceNameSpaces();
+    method @NonNull public abstract android.security.identity.CredentialDataResult.Entries getDeviceSignedEntries();
+    method @NonNull public abstract android.security.identity.CredentialDataResult.Entries getIssuerSignedEntries();
+    method @NonNull public abstract byte[] getStaticAuthenticationData();
+  }
+
+  public static interface CredentialDataResult.Entries {
+    method @Nullable public byte[] getEntry(@NonNull String, @NonNull String);
+    method @NonNull public java.util.Collection<java.lang.String> getEntryNames(@NonNull String);
+    method @NonNull public java.util.Collection<java.lang.String> getNamespaces();
+    method @NonNull public java.util.Collection<java.lang.String> getRetrievedEntryNames(@NonNull String);
+    method public int getStatus(@NonNull String, @NonNull String);
+    field public static final int STATUS_NOT_IN_REQUEST_MESSAGE = 3; // 0x3
+    field public static final int STATUS_NOT_REQUESTED = 2; // 0x2
+    field public static final int STATUS_NO_ACCESS_CONTROL_PROFILES = 6; // 0x6
+    field public static final int STATUS_NO_SUCH_ENTRY = 1; // 0x1
+    field public static final int STATUS_OK = 0; // 0x0
+    field public static final int STATUS_READER_AUTHENTICATION_FAILED = 5; // 0x5
+    field public static final int STATUS_USER_AUTHENTICATION_FAILED = 4; // 0x4
+  }
+
   public class DocTypeNotSupportedException extends android.security.identity.IdentityCredentialException {
     ctor public DocTypeNotSupportedException(@NonNull String);
     ctor public DocTypeNotSupportedException(@NonNull String, @NonNull Throwable);
@@ -37551,19 +36275,19 @@
   }
 
   public abstract class IdentityCredential {
-    method @NonNull public abstract java.security.KeyPair createEphemeralKeyPair();
-    method @NonNull public abstract byte[] decryptMessageFromReader(@NonNull byte[]) throws android.security.identity.MessageDecryptionException;
+    method @Deprecated @NonNull public abstract java.security.KeyPair createEphemeralKeyPair();
+    method @Deprecated @NonNull public abstract byte[] decryptMessageFromReader(@NonNull byte[]) throws android.security.identity.MessageDecryptionException;
     method @NonNull public byte[] delete(@NonNull byte[]);
-    method @NonNull public abstract byte[] encryptMessageToReader(@NonNull byte[]);
+    method @Deprecated @NonNull public abstract byte[] encryptMessageToReader(@NonNull byte[]);
     method @NonNull public abstract java.util.Collection<java.security.cert.X509Certificate> getAuthKeysNeedingCertification();
     method @NonNull public abstract int[] getAuthenticationDataUsageCount();
     method @NonNull public abstract java.util.Collection<java.security.cert.X509Certificate> getCredentialKeyCertificateChain();
-    method @NonNull public abstract android.security.identity.ResultData getEntries(@Nullable byte[], @NonNull java.util.Map<java.lang.String,java.util.Collection<java.lang.String>>, @Nullable byte[], @Nullable byte[]) throws android.security.identity.EphemeralPublicKeyNotFoundException, android.security.identity.InvalidReaderSignatureException, android.security.identity.InvalidRequestMessageException, android.security.identity.NoAuthenticationKeyAvailableException, android.security.identity.SessionTranscriptMismatchException;
+    method @Deprecated @NonNull public abstract android.security.identity.ResultData getEntries(@Nullable byte[], @NonNull java.util.Map<java.lang.String,java.util.Collection<java.lang.String>>, @Nullable byte[], @Nullable byte[]) throws android.security.identity.EphemeralPublicKeyNotFoundException, android.security.identity.InvalidReaderSignatureException, android.security.identity.InvalidRequestMessageException, android.security.identity.NoAuthenticationKeyAvailableException, android.security.identity.SessionTranscriptMismatchException;
     method @NonNull public byte[] proveOwnership(@NonNull byte[]);
-    method public abstract void setAllowUsingExhaustedKeys(boolean);
-    method public void setAllowUsingExpiredKeys(boolean);
+    method @Deprecated public abstract void setAllowUsingExhaustedKeys(boolean);
+    method @Deprecated public void setAllowUsingExpiredKeys(boolean);
     method public abstract void setAvailableAuthenticationKeys(int, int);
-    method public abstract void setReaderEphemeralPublicKey(@NonNull java.security.PublicKey) throws java.security.InvalidKeyException;
+    method @Deprecated public abstract void setReaderEphemeralPublicKey(@NonNull java.security.PublicKey) throws java.security.InvalidKeyException;
     method @Deprecated public abstract void storeStaticAuthenticationData(@NonNull java.security.cert.X509Certificate, @NonNull byte[]) throws android.security.identity.UnknownAuthenticationKeyException;
     method public void storeStaticAuthenticationData(@NonNull java.security.cert.X509Certificate, @NonNull java.time.Instant, @NonNull byte[]) throws android.security.identity.UnknownAuthenticationKeyException;
     method @NonNull public byte[] update(@NonNull android.security.identity.PersonalizationData);
@@ -37576,6 +36300,7 @@
 
   public abstract class IdentityCredentialStore {
     method @NonNull public abstract android.security.identity.WritableIdentityCredential createCredential(@NonNull String, @NonNull String) throws android.security.identity.AlreadyPersonalizedException, android.security.identity.DocTypeNotSupportedException;
+    method @NonNull public android.security.identity.PresentationSession createPresentationSession(int) throws android.security.identity.CipherSuiteNotSupportedException;
     method @Deprecated @Nullable public abstract byte[] deleteCredentialByName(@NonNull String);
     method @Nullable public abstract android.security.identity.IdentityCredential getCredentialByName(@NonNull String, int) throws android.security.identity.CipherSuiteNotSupportedException;
     method @Nullable public static android.security.identity.IdentityCredentialStore getDirectAccessInstance(@NonNull android.content.Context);
@@ -37614,22 +36339,29 @@
     method @NonNull public android.security.identity.PersonalizationData.Builder putEntry(@NonNull String, @NonNull String, @NonNull java.util.Collection<android.security.identity.AccessControlProfileId>, @NonNull byte[]);
   }
 
-  public abstract class ResultData {
-    method @NonNull public abstract byte[] getAuthenticatedData();
-    method @Nullable public abstract byte[] getEntry(@NonNull String, @NonNull String);
-    method @Nullable public abstract java.util.Collection<java.lang.String> getEntryNames(@NonNull String);
-    method @Nullable public abstract byte[] getMessageAuthenticationCode();
-    method @NonNull public abstract java.util.Collection<java.lang.String> getNamespaces();
-    method @Nullable public abstract java.util.Collection<java.lang.String> getRetrievedEntryNames(@NonNull String);
-    method @NonNull public abstract byte[] getStaticAuthenticationData();
-    method public abstract int getStatus(@NonNull String, @NonNull String);
-    field public static final int STATUS_NOT_IN_REQUEST_MESSAGE = 3; // 0x3
-    field public static final int STATUS_NOT_REQUESTED = 2; // 0x2
-    field public static final int STATUS_NO_ACCESS_CONTROL_PROFILES = 6; // 0x6
-    field public static final int STATUS_NO_SUCH_ENTRY = 1; // 0x1
-    field public static final int STATUS_OK = 0; // 0x0
-    field public static final int STATUS_READER_AUTHENTICATION_FAILED = 5; // 0x5
-    field public static final int STATUS_USER_AUTHENTICATION_FAILED = 4; // 0x4
+  public abstract class PresentationSession {
+    method @Nullable public abstract android.security.identity.CredentialDataResult getCredentialData(@NonNull String, @NonNull android.security.identity.CredentialDataRequest) throws android.security.identity.EphemeralPublicKeyNotFoundException, android.security.identity.InvalidReaderSignatureException, android.security.identity.InvalidRequestMessageException, android.security.identity.NoAuthenticationKeyAvailableException;
+    method @NonNull public abstract java.security.KeyPair getEphemeralKeyPair();
+    method public abstract void setReaderEphemeralPublicKey(@NonNull java.security.PublicKey) throws java.security.InvalidKeyException;
+    method public abstract void setSessionTranscript(@NonNull byte[]);
+  }
+
+  @Deprecated public abstract class ResultData {
+    method @Deprecated @NonNull public abstract byte[] getAuthenticatedData();
+    method @Deprecated @Nullable public abstract byte[] getEntry(@NonNull String, @NonNull String);
+    method @Deprecated @Nullable public abstract java.util.Collection<java.lang.String> getEntryNames(@NonNull String);
+    method @Deprecated @Nullable public abstract byte[] getMessageAuthenticationCode();
+    method @Deprecated @NonNull public abstract java.util.Collection<java.lang.String> getNamespaces();
+    method @Deprecated @Nullable public abstract java.util.Collection<java.lang.String> getRetrievedEntryNames(@NonNull String);
+    method @Deprecated @NonNull public abstract byte[] getStaticAuthenticationData();
+    method @Deprecated public abstract int getStatus(@NonNull String, @NonNull String);
+    field @Deprecated public static final int STATUS_NOT_IN_REQUEST_MESSAGE = 3; // 0x3
+    field @Deprecated public static final int STATUS_NOT_REQUESTED = 2; // 0x2
+    field @Deprecated public static final int STATUS_NO_ACCESS_CONTROL_PROFILES = 6; // 0x6
+    field @Deprecated public static final int STATUS_NO_SUCH_ENTRY = 1; // 0x1
+    field @Deprecated public static final int STATUS_OK = 0; // 0x0
+    field @Deprecated public static final int STATUS_READER_AUTHENTICATION_FAILED = 5; // 0x5
+    field @Deprecated public static final int STATUS_USER_AUTHENTICATION_FAILED = 4; // 0x4
   }
 
   public class SessionTranscriptMismatchException extends android.security.identity.IdentityCredentialException {
@@ -40994,13 +39726,14 @@
     field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_bool";
     field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
+    field public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL = "carrier_supports_tethering_bool";
     field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int";
-    field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
+    field @Deprecated public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
     field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool";
-    field public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
-    field public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
+    field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
+    field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
     field @Deprecated public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
@@ -41076,6 +39809,7 @@
     field public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
     field public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
     field public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+    field public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL = "is_opportunistic_subscription_bool";
     field public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
     field public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array";
     field public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "lte_rssnr_thresholds_int_array";
@@ -41160,6 +39894,7 @@
     field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final String KEY_SMDP_SERVER_ADDRESS_STRING = "smdp_server_address_string";
     field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
+    field public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING = "subscription_group_uuid_string";
     field public static final String KEY_SUPPORTS_CALL_COMPOSER_BOOL = "supports_call_composer_bool";
     field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_DTMF_BOOL = "supports_device_to_device_communication_using_dtmf_bool";
     field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_RTP_BOOL = "supports_device_to_device_communication_using_rtp_bool";
@@ -41203,6 +39938,7 @@
     field public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING = "wfc_emergency_address_carrier_app_string";
     field public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
     field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
+    field public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000";
     field public static final int SERVICE_CLASS_NONE = 0; // 0x0
     field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
     field public static final int USSD_OVER_CS_ONLY = 2; // 0x2
@@ -41226,14 +39962,24 @@
   }
 
   public static final class CarrierConfigManager.Ims {
+    field public static final String KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY = "ims.capability_type_call_composer_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY = "ims.capability_type_options_uce_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY = "ims.capability_type_presence_uce_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY = "ims.capability_type_sms_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY = "ims.capability_type_ut_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY = "ims.capability_type_video_int_array";
+    field public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY = "ims.capability_type_voice_int_array";
     field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool";
     field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool";
     field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
     field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
+    field public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE = "ims.mmtel_requires_provisioning_bundle";
     field public static final String KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT = "ims.non_rcs_capabilities_cache_expiration_sec_int";
     field public static final String KEY_PREFIX = "ims.";
     field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
     field public static final String KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY = "ims.rcs_feature_tag_allowed_string_array";
+    field public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE = "ims.rcs_requires_provisioning_bundle";
+    field public static final String KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL = "ims.use_sip_uri_for_presence_subscribe_bool";
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
   }
 
@@ -41252,6 +39998,7 @@
     field public static final int EPDG_ADDRESS_PCO = 2; // 0x2
     field public static final int EPDG_ADDRESS_PLMN = 1; // 0x1
     field public static final int EPDG_ADDRESS_STATIC = 0; // 0x0
+    field public static final int EPDG_ADDRESS_VISITED_COUNTRY = 4; // 0x4
     field public static final int ID_TYPE_FQDN = 2; // 0x2
     field public static final int ID_TYPE_KEY_ID = 11; // 0xb
     field public static final int ID_TYPE_RFC822_ADDR = 3; // 0x3
@@ -41283,6 +40030,7 @@
     field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
     field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
     field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
+    field public static final String KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL = "iwlan.supports_eap_aka_fast_reauth_bool";
   }
 
   public abstract class CellIdentity implements android.os.Parcelable {
@@ -42308,16 +41056,16 @@
     ctor @Deprecated public ServiceState(android.os.Parcel);
     method protected void copyFrom(android.telephony.ServiceState);
     method public int describeContents();
-    method public int getCdmaNetworkId();
-    method public int getCdmaSystemId();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public int getCdmaNetworkId();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public int getCdmaSystemId();
     method public int[] getCellBandwidths();
     method public int getChannelNumber();
     method public int getDuplexMode();
     method public boolean getIsManualSelection();
     method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
-    method public String getOperatorAlphaLong();
-    method public String getOperatorAlphaShort();
-    method public String getOperatorNumeric();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorAlphaLong();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorAlphaShort();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorNumeric();
     method public boolean getRoaming();
     method public int getState();
     method public boolean isSearching();
@@ -42854,6 +41602,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
     method public int getActiveModemCount();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getAllowedNetworkTypesForReason(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
     method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public int getCallState();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCallStateForSubscription();
@@ -42914,6 +41663,7 @@
     method public int getSubscriptionId();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubscriptionId(@NonNull android.telecom.PhoneAccountHandle);
     method public int getSupportedModemCount();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getSupportedRadioAccessFamily();
     method @Nullable public String getTypeAllocationCode();
     method @Nullable public String getTypeAllocationCode(int);
     method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
@@ -42959,6 +41709,7 @@
     method public String sendEnvelopeWithStatus(String);
     method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
     method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean);
@@ -42995,6 +41746,8 @@
     field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
     field public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
     field public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
+    field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2
+    field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0
     field public static final int APPTYPE_CSIM = 4; // 0x4
     field public static final int APPTYPE_ISIM = 5; // 0x5
     field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -43065,6 +41818,26 @@
     field public static final int NETWORK_SELECTION_MODE_MANUAL = 2; // 0x2
     field public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0; // 0x0
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
+    field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
+    field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
+    field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
+    field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
+    field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
+    field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
+    field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
+    field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
+    field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
+    field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
+    field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
+    field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
+    field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
+    field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
+    field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
+    field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
+    field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
+    field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
     field public static final int NETWORK_TYPE_EHRPD = 14; // 0xe
@@ -43646,6 +42419,7 @@
   public class ImsManager {
     method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
     method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+    method @NonNull public android.telephony.ims.ProvisioningManager getProvisioningManager(int);
     field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
     field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
     field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
@@ -43896,6 +42670,23 @@
     field public static final int REASON_UNKNOWN_TEMPORARY_ERROR = 1; // 0x1
   }
 
+  public class ProvisioningManager {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isProvisioningRequiredForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isRcsProvisioningRequiredForCapability(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerFeatureProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, int, boolean);
+    method public void unregisterFeatureProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback);
+  }
+
+  public static class ProvisioningManager.FeatureProvisioningCallback {
+    ctor public ProvisioningManager.FeatureProvisioningCallback();
+    method public void onFeatureProvisioningChanged(int, int, boolean);
+    method public void onRcsFeatureProvisioningChanged(int, int, boolean);
+  }
+
   public class RcsUceAdapter {
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
   }
@@ -43936,6 +42727,27 @@
     field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
   }
 
+  public class RcsFeature {
+  }
+
+  public static class RcsFeature.RcsImsCapabilities {
+    field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0
+    field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1
+    field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
+  }
+
+}
+
+package android.telephony.ims.stub {
+
+  public class ImsRegistrationImplBase {
+    field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2
+    field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+    field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+    field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+    field public static final int REGISTRATION_TECH_NR = 3; // 0x3
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index d13170bf..bcdd0a46 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -54,7 +54,24 @@
 package android.app.usage {
 
   public class NetworkStatsManager {
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void forceUpdate();
+    method public static int getCollapsedRatType(int);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyNetworkStatus(@NonNull java.util.List<android.net.Network>, @NonNull java.util.List<android.net.NetworkStateSnapshot>, @Nullable String, @NonNull java.util.List<android.net.UnderlyingNetworkInfo>);
+    method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForDevice(@NonNull android.net.NetworkTemplate, long, long);
+    method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(@NonNull android.net.NetworkTemplate, long, long, int, int, int) throws java.lang.SecurityException;
+    method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
+    method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long);
+    method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
+    method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setStatsProviderWarningAndLimitAsync(@NonNull String, long, long);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setUidForeground(int, boolean);
+    field public static final int NETWORK_TYPE_5G_NSA = -2; // 0xfffffffe
+  }
+
+  public abstract static class NetworkStatsManager.UsageCallback {
+    method public void onThresholdReached(@NonNull android.net.NetworkTemplate);
   }
 
 }
@@ -71,6 +88,14 @@
     field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
 
+  public class Intent implements java.lang.Cloneable android.os.Parcelable {
+    field public static final String ACTION_SETTING_RESTORED = "android.os.action.SETTING_RESTORED";
+    field public static final String EXTRA_SETTING_NAME = "setting_name";
+    field public static final String EXTRA_SETTING_NEW_VALUE = "new_value";
+    field public static final String EXTRA_SETTING_PREVIOUS_VALUE = "previous_value";
+    field public static final String EXTRA_SETTING_RESTORED_FROM_SDK_INT = "restored_from_sdk_int";
+  }
+
 }
 
 package android.content.pm {
@@ -115,7 +140,7 @@
     method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
     method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp();
     method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio();
-    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BtProfileConnectionInfo);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BluetoothProfileConnectionInfo);
     method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
     method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
     method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
@@ -125,17 +150,18 @@
     field public static final int FLAG_FROM_KEY = 4096; // 0x1000
   }
 
-  public final class BtProfileConnectionInfo implements android.os.Parcelable {
-    method @NonNull public static android.media.BtProfileConnectionInfo a2dpInfo(boolean, int);
+  public final class BluetoothProfileConnectionInfo implements android.os.Parcelable {
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpInfo(boolean, int);
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpSinkInfo(int);
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createHearingAidInfo(boolean);
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createLeAudioInfo(boolean, boolean);
     method public int describeContents();
-    method public boolean getIsLeOutput();
     method public int getProfile();
-    method public boolean getSuppressNoisyIntent();
     method public int getVolume();
-    method @NonNull public static android.media.BtProfileConnectionInfo hearingAidInfo(boolean);
-    method @NonNull public static android.media.BtProfileConnectionInfo leAudio(boolean, boolean);
+    method public boolean isLeOutput();
+    method public boolean isSuppressNoisyIntent();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.BtProfileConnectionInfo> CREATOR;
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.BluetoothProfileConnectionInfo> CREATOR;
   }
 
   public class MediaMetadataRetriever implements java.lang.AutoCloseable {
@@ -192,31 +218,59 @@
 
 package android.net {
 
-  public final class ConnectivityFrameworkInitializerTiramisu {
-    method public static void registerServiceWrappers();
+  public class EthernetManager {
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void addInterfaceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.InterfaceStateListener);
+    method public void removeInterfaceStateListener(@NonNull android.net.EthernetManager.InterfaceStateListener);
+    method public void setIncludeTestInterfaces(boolean);
+    field public static final int ROLE_CLIENT = 1; // 0x1
+    field public static final int ROLE_NONE = 0; // 0x0
+    field public static final int ROLE_SERVER = 2; // 0x2
+    field public static final int STATE_ABSENT = 0; // 0x0
+    field public static final int STATE_LINK_DOWN = 1; // 0x1
+    field public static final int STATE_LINK_UP = 2; // 0x2
   }
 
-  public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
-    ctor public EthernetNetworkSpecifier(@NonNull String);
-    method public int describeContents();
-    method @Nullable public String getInterfaceName();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR;
+  public static interface EthernetManager.InterfaceStateListener {
+    method public void onInterfaceStateChanged(@NonNull String, int, int, @Nullable android.net.IpConfiguration);
   }
 
-  public final class IpSecManager {
-    field public static final int DIRECTION_FWD = 2; // 0x2
+  public class LocalSocket implements java.io.Closeable {
+    ctor public LocalSocket(@NonNull java.io.FileDescriptor);
   }
 
-  public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public int getResourceId();
+  public class NetworkIdentity {
+    method public int getOemManaged();
+    method public int getRatType();
+    method @Nullable public String getSubscriberId();
+    method public int getType();
+    method @Nullable public String getWifiNetworkKey();
+    method public boolean isDefaultNetwork();
+    method public boolean isMetered();
+    method public boolean isRoaming();
+  }
+
+  public static final class NetworkIdentity.Builder {
+    ctor public NetworkIdentity.Builder();
+    method @NonNull public android.net.NetworkIdentity build();
+    method @NonNull public android.net.NetworkIdentity.Builder clearRatType();
+    method @NonNull public android.net.NetworkIdentity.Builder setDefaultNetwork(boolean);
+    method @NonNull public android.net.NetworkIdentity.Builder setMetered(boolean);
+    method @NonNull public android.net.NetworkIdentity.Builder setNetworkStateSnapshot(@NonNull android.net.NetworkStateSnapshot);
+    method @NonNull public android.net.NetworkIdentity.Builder setOemManaged(int);
+    method @NonNull public android.net.NetworkIdentity.Builder setRatType(int);
+    method @NonNull public android.net.NetworkIdentity.Builder setRoaming(boolean);
+    method @NonNull public android.net.NetworkIdentity.Builder setSubscriberId(@Nullable String);
+    method @NonNull public android.net.NetworkIdentity.Builder setType(int);
+    method @NonNull public android.net.NetworkIdentity.Builder setWifiNetworkKey(@Nullable String);
   }
 
   public class NetworkPolicyManager {
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int);
+    method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.telephony.SubscriptionPlan getSubscriptionPlan(@NonNull android.net.NetworkTemplate);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningOrLimitReached();
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
   }
@@ -237,6 +291,44 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStateSnapshot> CREATOR;
   }
 
+  public class NetworkStatsCollection {
+    method @NonNull public java.util.Map<android.net.NetworkStatsCollection.Key,android.net.NetworkStatsHistory> getEntries();
+  }
+
+  public static final class NetworkStatsCollection.Builder {
+    ctor public NetworkStatsCollection.Builder(long);
+    method @NonNull public android.net.NetworkStatsCollection.Builder addEntry(@NonNull android.net.NetworkStatsCollection.Key, @NonNull android.net.NetworkStatsHistory);
+    method @NonNull public android.net.NetworkStatsCollection build();
+  }
+
+  public static class NetworkStatsCollection.Key {
+    ctor public NetworkStatsCollection.Key(@NonNull java.util.Set<android.net.NetworkIdentity>, int, int, int);
+  }
+
+  public final class NetworkStatsHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.net.NetworkStatsHistory.Entry> getEntries();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStatsHistory> CREATOR;
+  }
+
+  public static final class NetworkStatsHistory.Builder {
+    ctor public NetworkStatsHistory.Builder(long, int);
+    method @NonNull public android.net.NetworkStatsHistory.Builder addEntry(@NonNull android.net.NetworkStatsHistory.Entry);
+    method @NonNull public android.net.NetworkStatsHistory build();
+  }
+
+  public static final class NetworkStatsHistory.Entry {
+    ctor public NetworkStatsHistory.Entry(long, long, long, long, long, long, long);
+    method public long getActiveTime();
+    method public long getBucketStart();
+    method public long getOperations();
+    method public long getRxBytes();
+    method public long getRxPackets();
+    method public long getTxBytes();
+    method public long getTxPackets();
+  }
+
   public final class NetworkTemplate implements android.os.Parcelable {
     method public int describeContents();
     method public int getDefaultNetworkStatus();
@@ -247,6 +339,7 @@
     method public int getRoaming();
     method @NonNull public java.util.Set<java.lang.String> getSubscriberIds();
     method @NonNull public java.util.Set<java.lang.String> getWifiNetworkKeys();
+    method public boolean matches(@NonNull android.net.NetworkIdentity);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkTemplate> CREATOR;
     field public static final int MATCH_BLUETOOTH = 8; // 0x8
@@ -292,6 +385,11 @@
     method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo);
   }
 
+  public class TrafficStats {
+    method public static void attachSocketTagger();
+    method public static void init(@NonNull android.content.Context);
+  }
+
   public final class UnderlyingNetworkInfo implements android.os.Parcelable {
     ctor public UnderlyingNetworkInfo(int, @NonNull String, @NonNull java.util.List<java.lang.String>);
     method public int describeContents();
@@ -312,6 +410,17 @@
 
 }
 
+package android.net.netstats {
+
+  public class NetworkStatsDataMigrationUtils {
+    method @NonNull public static android.net.NetworkStatsCollection readPlatformCollection(@NonNull String, long) throws java.io.IOException;
+    field public static final String PREFIX_UID = "uid";
+    field public static final String PREFIX_UID_TAG = "uid_tag";
+    field public static final String PREFIX_XT = "xt";
+  }
+
+}
+
 package android.os {
 
   public final class BatteryStatsManager {
@@ -335,6 +444,7 @@
   }
 
   public class Process {
+    field public static final int NFC_UID = 1027; // 0x403
     field public static final int VPN_UID = 1016; // 0x3f8
   }
 
@@ -366,6 +476,16 @@
     method @NonNull public java.util.List<android.content.ComponentName> getEnabledComponentOverrides(@NonNull String);
   }
 
+  public final class Trace {
+    method public static void asyncTraceBegin(long, @NonNull String, int);
+    method public static void asyncTraceEnd(long, @NonNull String, int);
+    method public static boolean isTagEnabled(long);
+    method public static void traceBegin(long, @NonNull String);
+    method public static void traceCounter(long, @NonNull String, int);
+    method public static void traceEnd(long);
+    field public static final long TRACE_TAG_NETWORK = 2097152L; // 0x200000L
+  }
+
 }
 
 package android.os.storage {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index b4a82ff..5c6076b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -63,6 +63,7 @@
     field public static final String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
     field public static final String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE";
     field public static final String BIND_TIME_ZONE_PROVIDER_SERVICE = "android.permission.BIND_TIME_ZONE_PROVIDER_SERVICE";
+    field public static final String BIND_TRACE_REPORT_SERVICE = "android.permission.BIND_TRACE_REPORT_SERVICE";
     field public static final String BIND_TRANSLATION_SERVICE = "android.permission.BIND_TRANSLATION_SERVICE";
     field public static final String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
     field public static final String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
@@ -138,11 +139,13 @@
     field public static final String MANAGE_APP_PREDICTIONS = "android.permission.MANAGE_APP_PREDICTIONS";
     field public static final String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
     field public static final String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
+    field public static final String MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED = "android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED";
     field public static final String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
     field public static final String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
     field public static final String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
     field public static final String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS";
     field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
+    field public static final String MANAGE_ETHERNET_NETWORKS = "android.permission.MANAGE_ETHERNET_NETWORKS";
     field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
     field public static final String MANAGE_HOTWORD_DETECTION = "android.permission.MANAGE_HOTWORD_DETECTION";
     field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
@@ -273,6 +276,7 @@
     field public static final String SIGNAL_REBOOT_READINESS = "android.permission.SIGNAL_REBOOT_READINESS";
     field public static final String SOUND_TRIGGER_RUN_IN_BATTERY_SAVER = "android.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER";
     field public static final String START_ACTIVITIES_FROM_BACKGROUND = "android.permission.START_ACTIVITIES_FROM_BACKGROUND";
+    field public static final String START_CROSS_PROFILE_ACTIVITIES = "android.permission.START_CROSS_PROFILE_ACTIVITIES";
     field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
     field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
     field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
@@ -314,6 +318,7 @@
 
   public static final class R.array {
     field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
+    field public static final int config_optionalIpSecAlgorithms;
   }
 
   public static final class R.attr {
@@ -1848,6 +1853,8 @@
   }
 
   public class NetworkStatsManager {
+    method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getMobileUidStats();
+    method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getWifiUidStats();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
   }
@@ -1911,423 +1918,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
-    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BufferConstraints getBufferConstraints();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getDynamicBufferSupport();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setBufferLengthMillis(int, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1; // 0x1
-    field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2; // 0x2
-    field public static final int DYNAMIC_BUFFER_SUPPORT_NONE = 0; // 0x0
-    field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
-    field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
-    field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff
-    field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1
-    field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public final class BluetoothA2dpSink implements android.bluetooth.BluetoothProfile {
-    method public void finalize();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isAudioPlaying(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothActivityEnergyInfo implements android.os.Parcelable {
-    method public int getBluetoothStackState();
-    method public long getControllerEnergyUsed();
-    method public long getControllerIdleTimeMillis();
-    method public long getControllerRxTimeMillis();
-    method public long getControllerTxTimeMillis();
-    method public long getTimestampMillis();
-    method @NonNull public java.util.List<android.bluetooth.UidTraffic> getUidTraffic();
-    method public boolean isValid();
-    field public static final int BT_STACK_STATE_INVALID = 0; // 0x0
-    field public static final int BT_STACK_STATE_STATE_ACTIVE = 1; // 0x1
-    field public static final int BT_STACK_STATE_STATE_IDLE = 3; // 0x3
-    field public static final int BT_STACK_STATE_STATE_SCANNING = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothActivityEnergyInfo> CREATOR;
-  }
-
-  public final class BluetoothAdapter {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableNoAutoConnect();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis();
-    method public boolean isBleScanAlwaysAvailable();
-    method public boolean isLeEnabled();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int);
-    field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
-    field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
-    field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2
-    field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0
-    field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1
-  }
-
-  public static interface BluetoothAdapter.OnMetadataChangedListener {
-    method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
-  }
-
-  public static interface BluetoothAdapter.OobDataCallback {
-    method public void onError(int);
-    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(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean fetchUuidsWithSdp(int);
-    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getSimAccessPermission();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isEncrypted();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInSilenceMode();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMessageAccessPermission(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMetadata(int, @NonNull byte[]);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPhonebookAccessPermission(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSilenceMode(boolean);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSimAccessPermission(int);
-    field public static final int ACCESS_ALLOWED = 1; // 0x1
-    field public static final int ACCESS_REJECTED = 2; // 0x2
-    field public static final int ACCESS_UNKNOWN = 0; // 0x0
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
-    field public static final String DEVICE_TYPE_DEFAULT = "Default";
-    field public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset";
-    field public static final String DEVICE_TYPE_WATCH = "Watch";
-    field public static final int METADATA_COMPANION_APP = 4; // 0x4
-    field public static final int METADATA_DEVICE_TYPE = 17; // 0x11
-    field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10
-    field public static final int METADATA_HARDWARE_VERSION = 3; // 0x3
-    field public static final int METADATA_IS_UNTETHERED_HEADSET = 6; // 0x6
-    field public static final int METADATA_MAIN_BATTERY = 18; // 0x12
-    field public static final int METADATA_MAIN_CHARGING = 19; // 0x13
-    field public static final int METADATA_MAIN_ICON = 5; // 0x5
-    field public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20; // 0x14
-    field public static final int METADATA_MANUFACTURER_NAME = 0; // 0x0
-    field public static final int METADATA_MAX_LENGTH = 2048; // 0x800
-    field public static final int METADATA_MODEL_NAME = 1; // 0x1
-    field public static final int METADATA_SOFTWARE_VERSION = 2; // 0x2
-    field public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; // 0xc
-    field public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; // 0xf
-    field public static final int METADATA_UNTETHERED_CASE_ICON = 9; // 0x9
-    field public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23; // 0x17
-    field public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; // 0xa
-    field public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; // 0xd
-    field public static final int METADATA_UNTETHERED_LEFT_ICON = 7; // 0x7
-    field public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21; // 0x15
-    field public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; // 0xb
-    field public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; // 0xe
-    field public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; // 0x8
-    field public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22; // 0x16
-  }
-
-  public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall();
-  }
-
-  public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-  }
-
-  public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-  }
-
-  public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothMap implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method public void close();
-    method protected void finalize();
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothMapClient implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.SEND_SMS}) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent);
-  }
-
-  public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isTetheringOn();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.TETHER_PRIVILEGED}) public void setBluetoothTethering(boolean);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
-    field public static final String ACTION_TETHERING_STATE_CHANGED = "android.bluetooth.action.TETHERING_STATE_CHANGED";
-    field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
-    field public static final String EXTRA_TETHERING_STATE = "android.bluetooth.extra.TETHERING_STATE";
-    field public static final int LOCAL_NAP_ROLE = 1; // 0x1
-    field public static final int LOCAL_PANU_ROLE = 2; // 0x2
-    field public static final int PAN_ROLE_NONE = 0; // 0x0
-    field public static final int REMOTE_NAP_ROLE = 1; // 0x1
-    field public static final int REMOTE_PANU_ROLE = 2; // 0x2
-    field public static final int TETHERING_STATE_OFF = 1; // 0x1
-    field public static final int TETHERING_STATE_ON = 2; // 0x2
-  }
-
-  public class BluetoothPbap implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public interface BluetoothProfile {
-    field public static final int A2DP_SINK = 11; // 0xb
-    field public static final int AVRCP_CONTROLLER = 12; // 0xc
-    field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
-    field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
-    field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
-    field public static final int HEADSET_CLIENT = 16; // 0x10
-    field public static final int MAP_CLIENT = 18; // 0x12
-    field public static final int PAN = 5; // 0x5
-    field public static final int PBAP_CLIENT = 17; // 0x11
-    field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
-    field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
-    field public static final int VOLUME_CONTROL = 23; // 0x17
-  }
-
-  public final class BluetoothStatusCodes {
-    field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
-  }
-
-  public final class BluetoothUuid {
-    method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]);
-    method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]);
-    field @NonNull public static final android.os.ParcelUuid A2DP_SINK;
-    field @NonNull public static final android.os.ParcelUuid A2DP_SOURCE;
-    field @NonNull public static final android.os.ParcelUuid ADV_AUDIO_DIST;
-    field @NonNull public static final android.os.ParcelUuid AVRCP_CONTROLLER;
-    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 CAP;
-    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;
-    field @NonNull public static final android.os.ParcelUuid HID;
-    field @NonNull public static final android.os.ParcelUuid HOGP;
-    field @NonNull public static final android.os.ParcelUuid HSP;
-    field @NonNull public static final android.os.ParcelUuid HSP_AG;
-    field @NonNull public static final android.os.ParcelUuid LE_AUDIO;
-    field @NonNull public static final android.os.ParcelUuid MAP;
-    field @NonNull public static final android.os.ParcelUuid MAS;
-    field @NonNull public static final android.os.ParcelUuid 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;
-    field @NonNull public static final android.os.ParcelUuid PANU;
-    field @NonNull public static final android.os.ParcelUuid PBAP_PCE;
-    field @NonNull public static final android.os.ParcelUuid PBAP_PSE;
-    field @NonNull public static final android.os.ParcelUuid SAP;
-    field public static final int UUID_BYTES_128_BIT = 16; // 0x10
-    field public static final int UUID_BYTES_16_BIT = 2; // 0x2
-    field public static final int UUID_BYTES_32_BIT = 4; // 0x4
-    field @NonNull public static final android.os.ParcelUuid VOLUME_CONTROL;
-  }
-
-  public final class BluetoothVolumeControl implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void close();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize();
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@Nullable android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BufferConstraint implements android.os.Parcelable {
-    ctor public BufferConstraint(int, int, int);
-    method public int describeContents();
-    method public int getDefaultMillis();
-    method public int getMaxMillis();
-    method public int getMinMillis();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraint> CREATOR;
-  }
-
-  public final class BufferConstraints implements android.os.Parcelable {
-    ctor public BufferConstraints(@NonNull java.util.List<android.bluetooth.BufferConstraint>);
-    method public int describeContents();
-    method @Nullable public android.bluetooth.BufferConstraint forCodec(int);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int BUFFER_CODEC_MAX_NUM = 32; // 0x20
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR;
-  }
-
-  public final class OobData implements android.os.Parcelable {
-    method @NonNull public byte[] getClassOfDevice();
-    method @NonNull public byte[] getClassicLength();
-    method @NonNull public byte[] getConfirmationHash();
-    method @NonNull public byte[] getDeviceAddressWithType();
-    method @Nullable public byte[] getDeviceName();
-    method @Nullable public byte[] getLeAppearance();
-    method @NonNull public int getLeDeviceRole();
-    method @NonNull public int getLeFlags();
-    method @Nullable public byte[] getLeTemporaryKey();
-    method @NonNull public byte[] getRandomizerHash();
-    field public static final int CLASS_OF_DEVICE_OCTETS = 3; // 0x3
-    field public static final int CONFIRMATION_OCTETS = 16; // 0x10
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
-    field public static final int DEVICE_ADDRESS_OCTETS = 7; // 0x7
-    field public static final int LE_APPEARANCE_OCTETS = 2; // 0x2
-    field public static final int LE_DEVICE_FLAG_OCTETS = 1; // 0x1
-    field public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 3; // 0x3
-    field public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 2; // 0x2
-    field public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 1; // 0x1
-    field public static final int LE_DEVICE_ROLE_OCTETS = 1; // 0x1
-    field public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0; // 0x0
-    field public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 2; // 0x2
-    field public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 1; // 0x1
-    field public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0; // 0x0
-    field public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 3; // 0x3
-    field public static final int LE_FLAG_SIMULTANEOUS_HOST = 4; // 0x4
-    field public static final int LE_TK_OCTETS = 16; // 0x10
-    field public static final int OOB_LENGTH_OCTETS = 2; // 0x2
-    field public static final int RANDOMIZER_OCTETS = 16; // 0x10
-  }
-
-  public static final class OobData.ClassicBuilder {
-    ctor public OobData.ClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData build();
-    method @NonNull public android.bluetooth.OobData.ClassicBuilder setClassOfDevice(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.ClassicBuilder setDeviceName(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.ClassicBuilder setRandomizerHash(@NonNull byte[]);
-  }
-
-  public static final class OobData.LeBuilder {
-    ctor public OobData.LeBuilder(@NonNull byte[], @NonNull byte[], int);
-    method @NonNull public android.bluetooth.OobData build();
-    method @NonNull public android.bluetooth.OobData.LeBuilder setDeviceName(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.LeBuilder setLeFlags(int);
-    method @NonNull public android.bluetooth.OobData.LeBuilder setLeTemporaryKey(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]);
-  }
-
-  public final class UidTraffic implements java.lang.Cloneable android.os.Parcelable {
-    method public long getRxBytes();
-    method public long getTxBytes();
-    method public int getUid();
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.UidTraffic> CREATOR;
-  }
-
-}
-
-package android.bluetooth.le {
-
-  public final class AdvertiseSettings implements android.os.Parcelable {
-    method public int getOwnAddressType();
-  }
-
-  public static final class AdvertiseSettings.Builder {
-    method @NonNull public android.bluetooth.le.AdvertiseSettings.Builder setOwnAddressType(int);
-  }
-
-  public final class AdvertisingSetParameters implements android.os.Parcelable {
-    method public int getOwnAddressType();
-    field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff
-    field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
-    field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
-  }
-
-  public static final class AdvertisingSetParameters.Builder {
-    method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int);
-  }
-
-  public final class BluetoothLeScanner {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
-  }
-
-  @Deprecated public final class ResultStorageDescriptor implements android.os.Parcelable {
-    ctor @Deprecated public ResultStorageDescriptor(int, int, int);
-    method @Deprecated public int describeContents();
-    method @Deprecated public int getLength();
-    method @Deprecated public int getOffset();
-    method @Deprecated public int getType();
-    method @Deprecated public void writeToParcel(android.os.Parcel, int);
-    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR;
-  }
-
-  public final class ScanFilter implements android.os.Parcelable {
-    method public int getAddressType();
-    method @Nullable public byte[] getIrk();
-  }
-
-  public static final class ScanFilter.Builder {
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int);
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int, @NonNull byte[]);
-    field public static final int LEN_IRK_OCTETS = 16; // 0x10
-  }
-
-  public final class ScanSettings implements android.os.Parcelable {
-    field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3
-    field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
-    field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
-  }
-
-  public static final class ScanSettings.Builder {
-    method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int);
-  }
-
-  @Deprecated public final class TruncatedFilter {
-    ctor @Deprecated public TruncatedFilter(android.bluetooth.le.ScanFilter, java.util.List<android.bluetooth.le.ResultStorageDescriptor>);
-    method @Deprecated public android.bluetooth.le.ScanFilter getFilter();
-    method @Deprecated public java.util.List<android.bluetooth.le.ResultStorageDescriptor> getStorageDescriptors();
-  }
-
-}
-
 package android.companion {
 
   public final class CompanionDeviceManager {
@@ -2406,6 +1996,7 @@
     field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
     field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
+    field public static final String NEARBY_SERVICE = "nearby";
     field public static final String NETD_SERVICE = "netd";
     field public static final String NETWORK_SCORE_SERVICE = "network_score";
     field public static final String OEM_LOCK_SERVICE = "oem_lock";
@@ -3364,6 +2955,7 @@
     method public void sendKeyEvent(int, boolean);
     method public void sendVendorCommand(int, byte[], boolean);
     method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener);
+    method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener, int);
   }
 
   public final class HdmiControlManager {
@@ -5880,6 +5472,7 @@
 
   public static final class TvInputManager.Hardware {
     method public void overrideAudioSink(int, String, int, int, int);
+    method public void overrideAudioSink(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int, int, int);
     method public void setStreamVolume(float);
     method public boolean setSurface(android.view.Surface, android.media.tv.TvStreamConfig);
   }
@@ -7430,7 +7023,10 @@
 package android.net {
 
   public class EthernetManager {
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
   }
 
   public static interface EthernetManager.TetheredInterfaceCallback {
@@ -7442,21 +7038,20 @@
     method public void release();
   }
 
-  public final class IpSecManager {
-    method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
-    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+  public final class EthernetNetworkManagementException extends java.lang.RuntimeException implements android.os.Parcelable {
+    ctor public EthernetNetworkManagementException(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkManagementException> CREATOR;
   }
 
-  public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
-    method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
-    method public void close();
-    method @NonNull public String getInterfaceName();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void setUnderlyingNetwork(@NonNull android.net.Network) throws java.io.IOException;
-  }
-
-  public static class IpSecTransform.Builder {
-    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecTransform buildTunnelModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+  public final class EthernetNetworkUpdateRequest implements android.os.Parcelable {
+    ctor public EthernetNetworkUpdateRequest(@NonNull android.net.StaticIpConfiguration, @NonNull android.net.NetworkCapabilities);
+    method public int describeContents();
+    method @NonNull public android.net.StaticIpConfiguration getIpConfig();
+    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR;
   }
 
   public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
@@ -7520,11 +7115,12 @@
     field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
   }
 
-  public final class NetworkStats implements android.os.Parcelable {
+  public final class NetworkStats implements java.lang.Iterable<android.net.NetworkStats.Entry> android.os.Parcelable {
     ctor public NetworkStats(long, int);
     method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
     method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
     method public int describeContents();
+    method @NonNull public java.util.Iterator<android.net.NetworkStats.Entry> iterator();
     method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStats> CREATOR;
@@ -7548,6 +7144,17 @@
 
   public static class NetworkStats.Entry {
     ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
+    method public int getDefaultNetwork();
+    method public int getMetered();
+    method public long getOperations();
+    method public int getRoaming();
+    method public long getRxBytes();
+    method public long getRxPackets();
+    method public int getSet();
+    method public int getTag();
+    method public long getTxBytes();
+    method public long getTxPackets();
+    method public int getUid();
   }
 
   public class RssiCurve implements android.os.Parcelable {
@@ -7584,6 +7191,7 @@
   public class TrafficStats {
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
+    method public static void setThreadStatsTagDownload();
     method public static void setThreadStatsTagRestore();
     field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = -113; // 0xffffff8f
     field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = -128; // 0xffffff80
@@ -8225,6 +7833,7 @@
   }
 
   public static class Build.VERSION {
+    field @NonNull public static final java.util.Set<java.lang.String> KNOWN_CODENAMES;
     field @NonNull public static final String PREVIEW_SDK_FINGERPRINT;
   }
 
@@ -8506,6 +8115,7 @@
     field public static final int EVENT_UNSPECIFIED = 0; // 0x0
     field public static final int REASON_ACCOUNT_TRANSFER = 104; // 0x68
     field public static final int REASON_ACTIVITY_RECOGNITION = 103; // 0x67
+    field public static final int REASON_BLUETOOTH_BROADCAST = 203; // 0xcb
     field public static final int REASON_GEOFENCING = 100; // 0x64
     field public static final int REASON_LOCATION_PROVIDER = 312; // 0x138
     field public static final int REASON_OTHER = 1; // 0x1
@@ -10517,6 +10127,20 @@
 
 }
 
+package android.service.tracing {
+
+  public class TraceReportService extends android.app.Service {
+    ctor public TraceReportService();
+    method public void onReportTrace(@NonNull android.service.tracing.TraceReportService.TraceParams);
+  }
+
+  public static final class TraceReportService.TraceParams {
+    method @NonNull public android.os.ParcelFileDescriptor getFd();
+    method @NonNull public java.util.UUID getUuid();
+  }
+
+}
+
 package android.service.translation {
 
   public abstract class TranslationService extends android.app.Service {
@@ -12047,7 +11671,6 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesBitmask();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesForReason(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -12090,7 +11713,6 @@
     method public int getSimCardState();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -12141,7 +11763,6 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int sendThermalMitigationRequest(@NonNull android.telephony.ThermalMitigationRequest);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
@@ -12191,10 +11812,8 @@
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
-    field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2
     field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3
     field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1
-    field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0
     field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
     field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
     field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
@@ -12233,26 +11852,6 @@
     field public static final int KEY_TYPE_WLAN = 2; // 0x2
     field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
     field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
-    field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
-    field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
-    field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
-    field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
-    field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
-    field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
-    field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
-    field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
-    field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
-    field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
-    field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
-    field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
-    field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
-    field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
-    field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
-    field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
-    field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
-    field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
-    field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
-    field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
     field public static final int NR_DUAL_CONNECTIVITY_DISABLE = 2; // 0x2
     field public static final int NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE = 3; // 0x3
     field public static final int NR_DUAL_CONNECTIVITY_ENABLE = 1; // 0x1
@@ -12309,6 +11908,7 @@
   }
 
   public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
+    ctor public TelephonyManager.ModemActivityInfoException(int);
     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
@@ -13277,13 +12877,21 @@
 
   public class ImsService extends android.app.Service {
     ctor public ImsService();
-    method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
-    method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
-    method public void disableIms(int);
-    method public void enableIms(int);
-    method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+    method @Nullable public android.telephony.ims.feature.MmTelFeature createEmergencyOnlyMmTelFeature(int);
+    method @Deprecated public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+    method @Nullable public android.telephony.ims.feature.MmTelFeature createMmTelFeatureForSubscription(int, int);
+    method @Deprecated public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+    method @Nullable public android.telephony.ims.feature.RcsFeature createRcsFeatureForSubscription(int, int);
+    method @Deprecated public void disableIms(int);
+    method public void disableImsForSubscription(int, int);
+    method @Deprecated public void enableIms(int);
+    method public void enableImsForSubscription(int, int);
+    method @Deprecated public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+    method @NonNull public android.telephony.ims.stub.ImsConfigImplBase getConfigForSubscription(int, int);
+    method @NonNull public java.util.concurrent.Executor getExecutor();
     method public long getImsServiceCapabilities();
-    method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+    method @Deprecated public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+    method @NonNull public android.telephony.ims.stub.ImsRegistrationImplBase getRegistrationForSubscription(int, int);
     method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
     method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
     method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
@@ -13507,18 +13115,16 @@
   public class ProvisioningManager {
     method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
     method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
@@ -13565,6 +13171,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsClientConfiguration> CREATOR;
     field public static final String RCS_PROFILE_1_0 = "UP_1.0";
     field public static final String RCS_PROFILE_2_3 = "UP_2.3";
+    field public static final String RCS_PROFILE_2_4 = "UP_2.4";
   }
 
   public final class RcsContactPresenceTuple implements android.os.Parcelable {
@@ -13632,6 +13239,7 @@
     method @Nullable public android.telephony.ims.RcsContactPresenceTuple getCapabilityTuple(@NonNull String);
     method @NonNull public java.util.List<android.telephony.ims.RcsContactPresenceTuple> getCapabilityTuples();
     method @NonNull public android.net.Uri getContactUri();
+    method @Nullable public android.net.Uri getEntityUri();
     method @NonNull public java.util.Set<java.lang.String> getFeatureTags();
     method public int getRequestResult();
     method public int getSourceType();
@@ -13660,6 +13268,7 @@
     method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuple(@NonNull android.telephony.ims.RcsContactPresenceTuple);
     method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuples(@NonNull java.util.List<android.telephony.ims.RcsContactPresenceTuple>);
     method @NonNull public android.telephony.ims.RcsContactUceCapability build();
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder setEntityUri(@NonNull android.net.Uri);
   }
 
   public class RcsUceAdapter {
@@ -13675,6 +13284,7 @@
     field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6; // 0x6
     field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4; // 0x4
     field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5; // 0x5
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12; // 0xc
     field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9; // 0x9
     field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2; // 0x2
     field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3; // 0x3
@@ -13900,6 +13510,7 @@
 
   public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public MmTelFeature();
+    ctor public MmTelFeature(@NonNull java.util.concurrent.Executor);
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
     method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
     method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
@@ -13933,7 +13544,7 @@
   }
 
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
-    ctor @Deprecated public RcsFeature();
+    ctor public RcsFeature();
     ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
     method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
@@ -13950,9 +13561,6 @@
     method public void addCapabilities(int);
     method public boolean isCapable(int);
     method public void removeCapabilities(int);
-    field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0
-    field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1
-    field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
   }
 
 }
@@ -14038,6 +13646,7 @@
   }
 
   public class ImsConfigImplBase {
+    ctor public ImsConfigImplBase(@NonNull java.util.concurrent.Executor);
     ctor public ImsConfigImplBase();
     method public int getConfigInt(int);
     method public String getConfigString(int);
@@ -14090,6 +13699,7 @@
 
   public class ImsRegistrationImplBase {
     ctor public ImsRegistrationImplBase();
+    ctor public ImsRegistrationImplBase(@NonNull java.util.concurrent.Executor);
     method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
     method public final void onRegistered(int);
     method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes);
@@ -14100,11 +13710,6 @@
     method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String);
     method public void triggerSipDelegateDeregistration();
     method public void updateSipDelegateRegistration();
-    field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2
-    field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
-    field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
-    field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
-    field public static final int REGISTRATION_TECH_NR = 3; // 0x3
   }
 
   public class ImsSmsImplBase {
@@ -14202,6 +13807,7 @@
   }
 
   public class SipTransportImplBase {
+    ctor public SipTransportImplBase();
     ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
     method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback);
     method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int);
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index b435acf..97eda7a 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -1,12 +1,6 @@
 // Baseline format: 1.0
 ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
 
-
-
-BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
-    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
-
-
 ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
     Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
 
@@ -15,8 +9,6 @@
 
 GenericException: android.hardware.location.ContextHubClient#finalize():
 
-GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize():
-
 GenericException: android.service.autofill.augmented.FillWindow#finalize():
 
 
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 9a8a493..327bfef 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -68,14 +68,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
-  }
-
-}
-
 package android.content {
 
   public class Intent implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index d0e659b..a0b3580 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -675,14 +675,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothClass implements android.os.Parcelable {
-    method public int getClassOfDevice();
-  }
-
-}
-
 package android.content {
 
   public final class AttributionSource implements android.os.Parcelable {
@@ -1581,14 +1573,6 @@
 
 package android.net {
 
-  public class EthernetManager {
-    method public void setIncludeTestInterfaces(boolean);
-  }
-
-  public final class IpSecManager {
-    field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
-  }
-
   public class NetworkPolicyManager {
     method public boolean getRestrictBackground();
     method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
@@ -1715,8 +1699,11 @@
 
   public final class Parcel {
     method public boolean allowSquashing();
+    method public int getFlags();
     method public int readExceptionCode();
     method public void restoreAllowSquashing(boolean);
+    field public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1; // 0x1
+    field public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 2; // 0x2
   }
 
   public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
@@ -2201,8 +2188,8 @@
   }
 
   public class KeyStoreException extends java.lang.Exception {
-    ctor public KeyStoreException(int, String);
     method public int getErrorCode();
+    method public static boolean hasFailureInfoForError(int);
   }
 
 }
@@ -2505,7 +2492,6 @@
     method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
     method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 343830a..27f3fc5 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -33,6 +33,11 @@
     srcs: ["android/tracing/ITracingServiceProxy.aidl"],
 }
 
+filegroup {
+    name: "TraceReportParams.aidl",
+    srcs: ["android/tracing/TraceReportParams.aidl"],
+}
+
 // These are subset of framework-core-sources that are needed by the
 // android.test.mock library. The implementation of android.test.mock references
 // private members of various components to allow mocking of classes that cannot
@@ -144,7 +149,6 @@
 filegroup {
     name: "framework-services-net-module-wifi-shared-srcs",
     srcs: [
-        "android/net/DhcpResults.java",
         "android/util/LocalLog.java",
     ],
 }
@@ -160,6 +164,18 @@
         "com/android/internal/util/IndentingPrintWriter.java",
         "com/android/internal/util/MessageUtils.java",
         "com/android/internal/util/WakeupMessage.java",
+        // TODO: delete as soon as NetworkStatsFactory stops using
+        "com/android/internal/util/ProcFileReader.java",
+    ],
+}
+
+// keep these files in sync with the packages/modules/Connectivity jarjar-rules.txt for
+// the connectivity module.
+filegroup {
+    name: "framework-connectivity-api-shared-srcs",
+    srcs: [
+        "android/util/IndentingPrintWriter.java",
+        "com/android/internal/util/FileRotator.java",
     ],
 }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3b0a5f3..6d7835f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -97,6 +97,7 @@
 import android.media.MediaServiceManager;
 import android.net.ConnectivityManager;
 import android.net.Proxy;
+import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
@@ -6663,6 +6664,13 @@
         NetworkSecurityConfigProvider.install(appContext);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
+        // For backward compatibility, TrafficStats needs static access to the application context.
+        // But for isolated apps which cannot access network related services, service discovery
+        // is restricted. Hence, calling this would result in NPE.
+        if (!Process.isIsolated()) {
+            TrafficStats.init(appContext);
+        }
+
         // Continue loading instrumentation.
         if (ii != null) {
             initInstrumentation(ii, data, appContext);
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 6261950..877e7d3 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -119,7 +119,7 @@
         for (int i = mExitTransitionCoordinators.size() - 1; i >= 0; i--) {
             WeakReference<ExitTransitionCoordinator> oldRef
                     = mExitTransitionCoordinators.valueAt(i);
-            if (oldRef.get() == null) {
+            if (oldRef.refersTo(null)) {
                 mExitTransitionCoordinators.removeAt(i);
             }
         }
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 198c33e..ab82398 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -678,8 +678,7 @@
         int refCount = mResourceImpls.size();
         for (int i = 0; i < refCount; i++) {
             WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
-            ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
-            if (resourceImpl == impl) {
+            if (weakImplRef != null && weakImplRef.refersTo(resourceImpl)) {
                 return mResourceImpls.keyAt(i);
             }
         }
@@ -1671,7 +1670,7 @@
                 for (int i = mResourceImpls.size() - 1; i >= 0; i--) {
                     final ResourcesKey key = mResourceImpls.keyAt(i);
                     final WeakReference<ResourcesImpl> impl = mResourceImpls.valueAt(i);
-                    if (impl == null || impl.get() == null
+                    if (impl == null || impl.refersTo(null)
                             || !ArrayUtils.contains(key.mLoaders, loader)) {
                         continue;
                     }
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f9739a4..3766dc8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -128,12 +128,10 @@
 import android.net.ConnectivityFrameworkInitializerTiramisu;
 import android.net.EthernetManager;
 import android.net.IEthernetManager;
-import android.net.IIpSecService;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
 import android.net.IPacProxyManager;
 import android.net.IVpnManager;
-import android.net.IpSecManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkScoreManager;
 import android.net.NetworkWatchlistManager;
@@ -420,15 +418,6 @@
                 return new VcnManager(ctx, service);
             }});
 
-        registerService(Context.IPSEC_SERVICE, IpSecManager.class,
-                new CachedServiceFetcher<IpSecManager>() {
-            @Override
-            public IpSecManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getService(Context.IPSEC_SERVICE);
-                IIpSecService service = IIpSecService.Stub.asInterface(b);
-                return new IpSecManager(ctx, service);
-            }});
-
         registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
                 new StaticServiceFetcher<CountryDetector>() {
             @Override
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6cfa39c..ab64596 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1452,18 +1452,27 @@
                     mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
-                boolean ok = false;
+                final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid));
                 try {
-                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                    copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
-                    // The 'close()' is the trigger for any server-side image manipulation,
-                    // so we must do that before waiting for completion.
-                    fos.close();
-                    completion.waitForCompletion();
+                    // If the stream can't be decoded, treat it as an invalid input.
+                    if (tmp != null) {
+                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+                        // The 'close()' is the trigger for any server-side image manipulation,
+                        // so we must do that before waiting for completion.
+                        fos.close();
+                        completion.waitForCompletion();
+                    } else {
+                        throw new IllegalArgumentException(
+                                "Resource 0x" + Integer.toHexString(resid) + " is invalid");
+                    }
                 } finally {
                     // Might be redundant but completion shouldn't wait unless the write
                     // succeeded; this is a fallback if it threw past the close+wait.
                     IoUtils.closeQuietly(fos);
+                    if (tmp != null) {
+                        tmp.recycle();
+                    }
                 }
             }
         } catch (RemoteException e) {
@@ -1705,13 +1714,22 @@
                     result, which, completion, mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
+                final Bitmap tmp = BitmapFactory.decodeStream(bitmapData);
                 try {
-                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                    copyStreamToWallpaperFile(bitmapData, fos);
-                    fos.close();
-                    completion.waitForCompletion();
+                    // If the stream can't be decoded, treat it as an invalid input.
+                    if (tmp != null) {
+                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+                        fos.close();
+                        completion.waitForCompletion();
+                    } else {
+                        throw new IllegalArgumentException("InputStream is invalid");
+                    }
                 } finally {
                     IoUtils.closeQuietly(fos);
+                    if (tmp != null) {
+                        tmp.recycle();
+                    }
                 }
             }
         } catch (RemoteException e) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0fe80c4..3840f76 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10177,6 +10177,9 @@
      * On fully-managed devices this method is unsupported because all traffic is considered
      * work traffic.
      *
+     * <p> This method enables preferential network service with a default configuration.
+     * To fine-tune the configuration, use {@link #setPreferentialNetworkServiceConfig) instead.
+     *
      * <p>This method can only be called by the profile owner of a managed profile.
      * @param enabled whether preferential network service should be enabled.
      * @throws SecurityException if the caller is not the profile owner.
@@ -10215,6 +10218,56 @@
     }
 
     /**
+     * Sets preferential network configuration on the work profile.
+     * {@see PreferentialNetworkServiceConfig}
+     *
+     * An example of a supported preferential network service is the Enterprise
+     * slice on 5G networks.
+     *
+     * By default, preferential network service is disabled on the work profile on supported
+     * carriers and devices. Admins can explicitly enable it with this API.
+     * On fully-managed devices this method is unsupported because all traffic is considered
+     * work traffic.
+     *
+     * <p>This method can only be called by the profile owner of a managed profile.
+     * @param preferentialNetworkServiceConfig preferential network configuration.
+     * @throws SecurityException if the caller is not the profile owner.
+     **/
+    public void setPreferentialNetworkServiceConfig(
+            @NonNull PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) {
+        throwIfParentInstance("setPreferentialNetworkServiceConfig");
+        if (mService == null) {
+            return;
+        }
+        try {
+            mService.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfig);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get preferential network configuration
+     * {@see PreferentialNetworkServiceConfig}
+     *
+     * <p>This method can be called by the profile owner of a managed profile.
+     *
+     * @return preferential network configuration.
+     * @throws SecurityException if the caller is not the profile owner.
+     */
+    public @NonNull PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig() {
+        throwIfParentInstance("getPreferentialNetworkServiceConfig");
+        if (mService == null) {
+            return PreferentialNetworkServiceConfig.DEFAULT;
+        }
+        try {
+            return mService.getPreferentialNetworkServiceConfig();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * This method is mostly deprecated.
      * Most of the settings that still have an effect have dedicated setter methods or user
      * restrictions. See individual settings for details.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d287437..c78a5a0 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -21,6 +21,7 @@
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.admin.ParcelableGranteeMap;
+import android.app.admin.PreferentialNetworkServiceConfig;
 import android.app.admin.StartInstallingUpdateCallback;
 import android.app.admin.SystemUpdateInfo;
 import android.app.admin.SystemUpdatePolicy;
@@ -278,6 +279,10 @@
     void setPreferentialNetworkServiceEnabled(in boolean enabled);
     boolean isPreferentialNetworkServiceEnabled(int userHandle);
 
+    void setPreferentialNetworkServiceConfig(
+            in PreferentialNetworkServiceConfig preferentialNetworkServiceConfig);
+    PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig();
+
     void setLockTaskPackages(in ComponentName who, in String[] packages);
     String[] getLockTaskPackages(in ComponentName who);
     boolean isLockTaskPermitted(in String pkg);
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl b/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl
new file mode 100644
index 0000000..6b6ee7d
--- /dev/null
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2022, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.app.admin;
+
+parcelable PreferentialNetworkServiceConfig;
\ No newline at end of file
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
new file mode 100644
index 0000000..2849139
--- /dev/null
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.admin;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Network configuration to be set for the user profile
+ * {@see DevicePolicyManager#setPreferentialNetworkServiceConfig}.
+ */
+public final class PreferentialNetworkServiceConfig implements Parcelable {
+    final boolean mIsEnabled;
+    final int mNetworkId;
+    final boolean mAllowFallbackToDefaultConnection;
+    final int[] mIncludedUids;
+    final int[] mExcludedUids;
+
+    /** @hide */
+    public static final PreferentialNetworkServiceConfig DEFAULT =
+            (new PreferentialNetworkServiceConfig.Builder()).build();
+
+    /**
+     * Preferential network identifier 1.
+     */
+    public static final int PREFERENTIAL_NETWORK_ID_1 = 1;
+
+    /**
+     * Preferential network identifier 2.
+     */
+    public static final int PREFERENTIAL_NETWORK_ID_2 = 2;
+
+    /**
+     * Preferential network identifier 3.
+     */
+    public static final int PREFERENTIAL_NETWORK_ID_3 = 3;
+
+    /**
+     * Preferential network identifier 4.
+     */
+    public static final int PREFERENTIAL_NETWORK_ID_4 = 4;
+
+    /**
+     * Preferential network identifier 5.
+     */
+    public static final int PREFERENTIAL_NETWORK_ID_5 = 5;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "PREFERENTIAL_NETWORK_ID_" }, value = {
+            PREFERENTIAL_NETWORK_ID_1,
+            PREFERENTIAL_NETWORK_ID_2,
+            PREFERENTIAL_NETWORK_ID_3,
+            PREFERENTIAL_NETWORK_ID_4,
+            PREFERENTIAL_NETWORK_ID_5,
+    })
+
+    public @interface PreferentialNetworkPreferenceId {
+    }
+
+    private PreferentialNetworkServiceConfig(boolean isEnabled,
+            boolean allowFallbackToDefaultConnection, int[] includedUids,
+            int[] excludedUids, @PreferentialNetworkPreferenceId int networkId) {
+        mIsEnabled = isEnabled;
+        mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
+        mIncludedUids = includedUids;
+        mExcludedUids = excludedUids;
+        mNetworkId = networkId;
+    }
+
+    private PreferentialNetworkServiceConfig(Parcel in) {
+        mIsEnabled = in.readBoolean();
+        mAllowFallbackToDefaultConnection = in.readBoolean();
+        mNetworkId = in.readInt();
+        mIncludedUids = in.createIntArray();
+        mExcludedUids = in.createIntArray();
+    }
+
+    /**
+     * Is the preferential network enabled.
+     * @return true if enabled else false
+     */
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    /**
+     * is fallback to default network allowed. This boolean configures whether default connection
+     * (default internet or wifi) should be used or not if a preferential network service
+     * connection is not available.
+     * @return true if fallback is allowed, else false.
+     */
+    public boolean isFallbackToDefaultConnectionAllowed() {
+        return mAllowFallbackToDefaultConnection;
+    }
+
+    /**
+     * Get the array of uids that are applicable for the profile preference.
+     *
+     * {@see #getExcludedUids()}
+     * Included UIDs and Excluded UIDs can't both be non-empty.
+     * if both are empty, it means this request applies to all uids in the user profile.
+     * if included is not empty, then only included UIDs are applied.
+     * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+     * @return Array of uids applicable for the profile preference.
+     *      Empty array would mean that this request applies to all uids in the profile.
+     */
+    public @NonNull int[] getIncludedUids() {
+        return mIncludedUids;
+    }
+
+    /**
+     * Get the array of uids that are excluded for the profile preference.
+     *
+     * {@see #getIncludedUids()}
+     * Included UIDs and Excluded UIDs can't both be non-empty.
+     * if both are empty, it means this request applies to all uids in the user profile.
+     * if included is not empty, then only included UIDs are applied.
+     * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+     * @return Array of uids that are excluded for the profile preference.
+     *      Empty array would mean that this request applies to all uids in the profile.
+     */
+    public @NonNull int[] getExcludedUids() {
+        return mExcludedUids;
+    }
+
+    /**
+     * @return preference enterprise identifier.
+     * valid values starts from
+     * {@link #PREFERENTIAL_NETWORK_ID_1} to {@link #PREFERENTIAL_NETWORK_ID_5}.
+     * preference identifier is applicable only if preference network service is enabled
+     *
+     */
+    public @PreferentialNetworkPreferenceId int getNetworkId() {
+        return mNetworkId;
+    }
+
+    @Override
+    public String toString() {
+        return "PreferentialNetworkServiceConfig{"
+                + "mIsEnabled=" + isEnabled()
+                + "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed()
+                + "mIncludedUids=" + mIncludedUids.toString()
+                + "mExcludedUids=" + mExcludedUids.toString()
+                + "mNetworkId=" + mNetworkId
+                + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final PreferentialNetworkServiceConfig that = (PreferentialNetworkServiceConfig) o;
+        return mIsEnabled == that.mIsEnabled
+                && mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection
+                && mNetworkId == that.mNetworkId
+                && Objects.equals(mIncludedUids, that.mIncludedUids)
+                && Objects.equals(mExcludedUids, that.mExcludedUids);
+    }
+
+    @Override
+    public int hashCode() {
+        return ((Objects.hashCode(mIsEnabled) * 17)
+                + (Objects.hashCode(mAllowFallbackToDefaultConnection) * 19)
+                + (Objects.hashCode(mIncludedUids) * 23)
+                + (Objects.hashCode(mExcludedUids) * 29)
+                + mNetworkId * 31);
+    }
+
+    /**
+     * Builder used to create {@link PreferentialNetworkServiceConfig} objects.
+     * Specify the preferred Network preference
+     */
+    public static final class Builder {
+        boolean mIsEnabled = false;
+        int mNetworkId = 0;
+        boolean mAllowFallbackToDefaultConnection = true;
+        int[] mIncludedUids = new int[0];
+        int[] mExcludedUids = new int[0];
+
+        /**
+         * Constructs an empty Builder with preferential network disabled by default.
+         */
+        public Builder() {}
+
+        /**
+         * Set the preferential network service enabled state.
+         * Default value is false.
+         * @param isEnabled  the desired network preference to use, true to enable else false
+         * @return The builder to facilitate chaining.
+         */
+        @NonNull
+        public PreferentialNetworkServiceConfig.Builder setEnabled(boolean isEnabled) {
+            mIsEnabled = isEnabled;
+            return this;
+        }
+
+        /**
+         * Set whether the default connection should be used as fallback.
+         * This boolean configures whether the default connection (default internet or wifi)
+         * should be used if a preferential network service connection is not available.
+         * Default value is true
+         * @param allowFallbackToDefaultConnection  true if fallback is allowed else false
+         * @return The builder to facilitate chaining.
+         */
+        @NonNull
+        @SuppressLint("MissingGetterMatchingBuilder")
+        public PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(
+                boolean allowFallbackToDefaultConnection) {
+            mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
+            return this;
+        }
+
+        /**
+         * Set the array of uids whose network access will go through this preferential
+         * network service.
+         * {@see #setExcludedUids(int[])}
+         * Included UIDs and Excluded UIDs can't both be non-empty.
+         * if both are empty, it means this request applies to all uids in the user profile.
+         * if included is not empty, then only included UIDs are applied.
+         * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+         * @param uids  array of included uids
+         * @return The builder to facilitate chaining.
+         */
+        @NonNull
+        public PreferentialNetworkServiceConfig.Builder setIncludedUids(
+                @NonNull int[] uids) {
+            Objects.requireNonNull(uids);
+            mIncludedUids = uids;
+            return this;
+        }
+
+        /**
+         * Set the array of uids who are not allowed through this preferential
+         * network service.
+         * {@see #setIncludedUids(int[])}
+         * Included UIDs and Excluded UIDs can't both be non-empty.
+         * if both are empty, it means this request applies to all uids in the user profile.
+         * if included is not empty, then only included UIDs are applied.
+         * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+         * @param uids  array of excluded uids
+         * @return The builder to facilitate chaining.
+         */
+        @NonNull
+        public PreferentialNetworkServiceConfig.Builder setExcludedUids(
+                @NonNull int[] uids) {
+            Objects.requireNonNull(uids);
+            mExcludedUids = uids;
+            return this;
+        }
+
+        /**
+         * Returns an instance of {@link PreferentialNetworkServiceConfig} created from the
+         * fields set on this builder.
+         */
+        @NonNull
+        public PreferentialNetworkServiceConfig build() {
+            if (mIncludedUids.length > 0 && mExcludedUids.length > 0) {
+                throw new IllegalStateException("Both includedUids and excludedUids "
+                        + "cannot be nonempty");
+            }
+            return new PreferentialNetworkServiceConfig(mIsEnabled,
+                    mAllowFallbackToDefaultConnection, mIncludedUids, mExcludedUids, mNetworkId);
+        }
+
+        /**
+         * Set the preferential network identifier.
+         * Valid values starts from {@link #PREFERENTIAL_NETWORK_ID_1} to
+         * {@link #PREFERENTIAL_NETWORK_ID_5}.
+         * preference identifier is applicable only if preferential network service is enabled.
+         * @param preferenceId  preference Id
+         * @return The builder to facilitate chaining.
+         */
+        @NonNull
+        public PreferentialNetworkServiceConfig.Builder setNetworkId(
+                @PreferentialNetworkPreferenceId int preferenceId) {
+            if ((preferenceId < PREFERENTIAL_NETWORK_ID_1)
+                    || (preferenceId > PREFERENTIAL_NETWORK_ID_5)) {
+                throw new IllegalArgumentException("Invalid preference identifier");
+            }
+            mNetworkId = preferenceId;
+            return this;
+        }
+    }
+
+    @Override
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        dest.writeBoolean(mIsEnabled);
+        dest.writeBoolean(mAllowFallbackToDefaultConnection);
+        dest.writeInt(mNetworkId);
+        dest.writeIntArray(mIncludedUids);
+        dest.writeIntArray(mExcludedUids);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Creator<PreferentialNetworkServiceConfig> CREATOR =
+            new Creator<PreferentialNetworkServiceConfig>() {
+                @Override
+                public PreferentialNetworkServiceConfig[] newArray(int size) {
+                    return new PreferentialNetworkServiceConfig[size];
+                }
+
+                @Override
+                public PreferentialNetworkServiceConfig createFromParcel(
+                        @NonNull android.os.Parcel in) {
+                    return new PreferentialNetworkServiceConfig(in);
+                }
+            };
+}
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
index 46b5ea0..e857c72 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -1,7 +1,5 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
index 482abb2..cf54c2a 100644
--- a/core/java/android/app/contentsuggestions/OWNERS
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 643919
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/app/trust/OWNERS b/core/java/android/app/trust/OWNERS
new file mode 100644
index 0000000..e2c6ce1
--- /dev/null
+++ b/core/java/android/app/trust/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/trust/OWNERS
diff --git a/core/java/android/app/wallpapereffectsgeneration/OWNERS b/core/java/android/app/wallpapereffectsgeneration/OWNERS
new file mode 100644
index 0000000..2bc0154
--- /dev/null
+++ b/core/java/android/app/wallpapereffectsgeneration/OWNERS
@@ -0,0 +1,5 @@
+susharon@google.com
+shanh@google.com
+huiwu@google.com
+srazdan@google.com
+
diff --git a/core/java/android/bluetooth/Attributable.java b/core/java/android/bluetooth/Attributable.java
deleted file mode 100644
index d9acbe3..0000000
--- a/core/java/android/bluetooth/Attributable.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.AttributionSource;
-
-import java.util.List;
-
-/**
- * Marker interface for a class which can have an {@link AttributionSource}
- * assigned to it; these are typically {@link android.os.Parcelable} classes
- * which need to be updated after crossing Binder transaction boundaries.
- *
- * @hide
- */
-public interface Attributable {
-    void setAttributionSource(@NonNull AttributionSource attributionSource);
-
-    static @Nullable <T extends Attributable> T setAttributionSource(
-            @Nullable T attributable,
-            @NonNull AttributionSource attributionSource) {
-        if (attributable != null) {
-            attributable.setAttributionSource(attributionSource);
-        }
-        return attributable;
-    }
-
-    static @Nullable <T extends Attributable> List<T> setAttributionSource(
-            @Nullable List<T> attributableList,
-            @NonNull AttributionSource attributionSource) {
-        if (attributableList != null) {
-            final int size = attributableList.size();
-            for (int i = 0; i < size; i++) {
-                setAttributionSource(attributableList.get(i), attributionSource);
-            }
-        }
-        return attributableList;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
deleted file mode 100644
index 8b9cec1..0000000
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ /dev/null
@@ -1,1149 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-
-/**
- * This class provides the public APIs to control the Bluetooth A2DP
- * profile.
- *
- * <p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothA2dp proxy object.
- *
- * <p> Android only supports one connected Bluetooth A2dp device at a time.
- * Each method is protected with its appropriate permission.
- */
-public final class BluetoothA2dp implements BluetoothProfile {
-    private static final String TAG = "BluetoothA2dp";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the A2DP
-     * profile.
-     *
-     * <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}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the change in the Playing state of the A2DP
-     * profile.
-     *
-     * <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_PLAYING}, {@link #STATE_NOT_PLAYING},
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PLAYING_STATE_CHANGED =
-            "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the selection of a connected device as active.
-     *
-     * <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>
-     * </ul>
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage(trackingBug = 171933273)
-    public static final String ACTION_ACTIVE_DEVICE_CHANGED =
-            "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
-
-    /**
-     * Intent used to broadcast the change in the Audio Codec state of the
-     * A2DP Source profile.
-     *
-     * <p>This intent will have 2 extras:
-     * <ul>
-     * <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li>
-     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
-     * connected, otherwise it is not included.</li>
-     * </ul>
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage(trackingBug = 181103983)
-    public static final String ACTION_CODEC_CONFIG_CHANGED =
-            "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
-
-    /**
-     * A2DP sink device is streaming music. This state can be one of
-     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
-     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
-     */
-    public static final int STATE_PLAYING = 10;
-
-    /**
-     * A2DP sink device is NOT streaming music. This state can be one of
-     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
-     * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
-     */
-    public static final int STATE_NOT_PLAYING = 11;
-
-    /** @hide */
-    @IntDef(prefix = "OPTIONAL_CODECS_", value = {
-            OPTIONAL_CODECS_SUPPORT_UNKNOWN,
-            OPTIONAL_CODECS_NOT_SUPPORTED,
-            OPTIONAL_CODECS_SUPPORTED
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface OptionalCodecsSupportStatus {}
-
-    /**
-     * We don't have a stored preference for whether or not the given A2DP sink device supports
-     * optional codecs.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
-
-    /**
-     * The given A2DP sink device does not support optional codecs.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
-
-    /**
-     * The given A2DP sink device does support optional codecs.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int OPTIONAL_CODECS_SUPPORTED = 1;
-
-    /** @hide */
-    @IntDef(prefix = "OPTIONAL_CODECS_PREF_", value = {
-            OPTIONAL_CODECS_PREF_UNKNOWN,
-            OPTIONAL_CODECS_PREF_DISABLED,
-            OPTIONAL_CODECS_PREF_ENABLED
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface OptionalCodecsPreferenceStatus {}
-
-    /**
-     * We don't have a stored preference for whether optional codecs should be enabled or
-     * disabled for the given A2DP device.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
-
-    /**
-     * Optional codecs should be disabled for the given A2DP device.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
-
-    /**
-     * Optional codecs should be enabled for the given A2DP device.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
-
-    /** @hide */
-    @IntDef(prefix = "DYNAMIC_BUFFER_SUPPORT_", value = {
-            DYNAMIC_BUFFER_SUPPORT_NONE,
-            DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD,
-            DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Type {}
-
-    /**
-     * Indicates the supported type of Dynamic Audio Buffer is not supported.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int DYNAMIC_BUFFER_SUPPORT_NONE = 0;
-
-    /**
-     * Indicates the supported type of Dynamic Audio Buffer is A2DP offload.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1;
-
-    /**
-     * Indicates the supported type of Dynamic Audio Buffer is A2DP software encoding.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
-                    IBluetoothA2dp.class.getName()) {
-                @Override
-                public IBluetoothA2dp getServiceInterface(IBinder service) {
-                    return IBluetoothA2dp.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothA2dp proxy object for interacting with the local
-     * Bluetooth A2DP service.
-     */
-    /* package */ BluetoothA2dp(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    @UnsupportedAppUsage
-    /*package*/ void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothA2dp getService() {
-        return mProfileConnector.getService();
-    }
-
-    @Override
-    public void finalize() {
-        // The empty finalize needs to be kept or the
-        // cts signature tests would fail.
-    }
-
-    /**
-     * Initiate connection to a profile of the remote Bluetooth device.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @UnsupportedAppUsage
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connectWithAttribution(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @UnsupportedAppUsage
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnectWithAttribution(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothA2dp service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevicesWithAttribution(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothA2dp service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStatesWithAttribution(states,
-                        mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @BtProfileState int getConnectionState(BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        final IBluetoothA2dp service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionStateWithAttribution(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Select a connected device as active.
-     *
-     * The active device selection is per profile. An active device's
-     * purpose is profile-specific. For example, A2DP audio streaming
-     * is to the active A2DP Sink device. If a remote device is not
-     * connected, it cannot be selected as active.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is not connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that the
-     * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
-     * with the active device.
-     *
-     * @param device the remote Bluetooth device. Could be null to clear
-     * the active device and stop streaming audio to a Bluetooth device.
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @UnsupportedAppUsage(trackingBug = 171933273)
-    public boolean setActiveDevice(@Nullable BluetoothDevice device) {
-        if (DBG) log("setActiveDevice(" + device + ")");
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && ((device == null) || isValidDevice(device))) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setActiveDevice(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the connected device that is active.
-     *
-     * @return the connected device that is active or null if no device
-     * is active
-     * @hide
-     */
-    @UnsupportedAppUsage(trackingBug = 171933273)
-    @Nullable
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothDevice getActiveDevice() {
-        if (VDBG) log("getActiveDevice()");
-        final IBluetoothA2dp service = getService();
-        final BluetoothDevice defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<BluetoothDevice> recv =
-                        new SynchronousResultReceiver();
-                service.getActiveDevice(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                    && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                        || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothA2dp service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Checks if Avrcp device supports the absolute volume feature.
-     *
-     * @return true if device supports absolute volume
-     * @hide
-     */
-    @RequiresNoPermission
-    public boolean isAvrcpAbsoluteVolumeSupported() {
-        if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isAvrcpAbsoluteVolumeSupported(recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Tells remote device to set an absolute volume. Only if absolute volume is supported
-     *
-     * @param volume Absolute volume to be set on AVRCP side
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setAvrcpAbsoluteVolume(int volume) {
-        if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
-        final IBluetoothA2dp service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                service.setAvrcpAbsoluteVolume(volume, mAttributionSource);
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Check if A2DP profile is streaming music.
-     *
-     * @param device BluetoothDevice device
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isA2dpPlaying(BluetoothDevice device) {
-        if (DBG) log("isA2dpPlaying(" + device + ")");
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isA2dpPlaying(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * This function checks if the remote device is an AVCRP
-     * target and thus whether we should send volume keys
-     * changes or not.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean shouldSendVolumeKeys(BluetoothDevice device) {
-        if (isEnabled() && isValidDevice(device)) {
-            ParcelUuid[] uuids = device.getUuids();
-            if (uuids == null) return false;
-
-            for (ParcelUuid uuid : uuids) {
-                if (uuid.equals(BluetoothUuid.AVRCP_TARGET)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Gets the current codec status (configuration and capability).
-     *
-     * @param device the remote Bluetooth device.
-     * @return the current codec status
-     * @hide
-     */
-    @UnsupportedAppUsage(trackingBug = 181103983)
-    @Nullable
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
-        verifyDeviceNotNull(device, "getCodecStatus");
-        final IBluetoothA2dp service = getService();
-        final BluetoothCodecStatus defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<BluetoothCodecStatus> recv =
-                        new SynchronousResultReceiver();
-                service.getCodecStatus(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sets the codec configuration preference.
-     *
-     * @param device the remote Bluetooth device.
-     * @param codecConfig the codec configuration preference
-     * @hide
-     */
-    @UnsupportedAppUsage(trackingBug = 181103983)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setCodecConfigPreference(@NonNull BluetoothDevice device,
-                                         @NonNull BluetoothCodecConfig codecConfig) {
-        if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
-        verifyDeviceNotNull(device, "setCodecConfigPreference");
-        if (codecConfig == null) {
-            Log.e(TAG, "setCodecConfigPreference: Codec config can't be null");
-            throw new IllegalArgumentException("codecConfig cannot be null");
-        }
-        final IBluetoothA2dp service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                service.setCodecConfigPreference(device, codecConfig, mAttributionSource);
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Enables the optional codecs.
-     *
-     * @param device the remote Bluetooth device.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void enableOptionalCodecs(@NonNull BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
-        verifyDeviceNotNull(device, "enableOptionalCodecs");
-        enableDisableOptionalCodecs(device, true);
-    }
-
-    /**
-     * Disables the optional codecs.
-     *
-     * @param device the remote Bluetooth device.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void disableOptionalCodecs(@NonNull BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
-        verifyDeviceNotNull(device, "disableOptionalCodecs");
-        enableDisableOptionalCodecs(device, false);
-    }
-
-    /**
-     * Enables or disables the optional codecs.
-     *
-     * @param device the remote Bluetooth device.
-     * @param enable if true, enable the optional codecs, other disable them
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
-        final IBluetoothA2dp service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                if (enable) {
-                    service.enableOptionalCodecs(device, mAttributionSource);
-                } else {
-                    service.disableOptionalCodecs(device, mAttributionSource);
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Returns whether this device supports optional codecs.
-     *
-     * @param device The device to check
-     * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or
-     * OPTIONAL_CODECS_SUPPORTED.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @OptionalCodecsSupportStatus
-    public int isOptionalCodecsSupported(@NonNull BluetoothDevice device) {
-        if (DBG) log("isOptionalCodecsSupported(" + device + ")");
-        verifyDeviceNotNull(device, "isOptionalCodecsSupported");
-        final IBluetoothA2dp service = getService();
-        final int defaultValue = OPTIONAL_CODECS_SUPPORT_UNKNOWN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.supportsOptionalCodecs(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns whether this device should have optional codecs enabled.
-     *
-     * @param device The device in question.
-     * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
-     * OPTIONAL_CODECS_PREF_DISABLED.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @OptionalCodecsPreferenceStatus
-    public int isOptionalCodecsEnabled(@NonNull BluetoothDevice device) {
-        if (DBG) log("isOptionalCodecsEnabled(" + device + ")");
-        verifyDeviceNotNull(device, "isOptionalCodecsEnabled");
-        final IBluetoothA2dp service = getService();
-        final int defaultValue = OPTIONAL_CODECS_PREF_UNKNOWN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getOptionalCodecsEnabled(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sets a persistent preference for whether a given device should have optional codecs enabled.
-     *
-     * @param device The device to set this preference for.
-     * @param value Whether the optional codecs should be enabled for this device.  This should be
-     * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or
-     * OPTIONAL_CODECS_PREF_DISABLED.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setOptionalCodecsEnabled(@NonNull BluetoothDevice device,
-            @OptionalCodecsPreferenceStatus int value) {
-        if (DBG) log("setOptionalCodecsEnabled(" + device + ")");
-        verifyDeviceNotNull(device, "setOptionalCodecsEnabled");
-        if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
-                && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
-                && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
-            Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
-            return;
-        }
-        final IBluetoothA2dp service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                service.setOptionalCodecsEnabled(device, value, mAttributionSource);
-            } catch (RemoteException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Get the supported type of the Dynamic Audio Buffer.
-     * <p>Possible return values are
-     * {@link #DYNAMIC_BUFFER_SUPPORT_NONE},
-     * {@link #DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD},
-     * {@link #DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}.
-     *
-     * @return supported type of Dynamic Audio Buffer feature
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @Type int getDynamicBufferSupport() {
-        if (VDBG) log("getDynamicBufferSupport()");
-        final IBluetoothA2dp service = getService();
-        final int defaultValue = DYNAMIC_BUFFER_SUPPORT_NONE;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getDynamicBufferSupport(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Return the record of {@link BufferConstraints} object that
-     * has the default/maximum/minimum audio buffer. This can be used to inform what the controller
-     * has support for the audio buffer.
-     *
-     * @return a record with {@link BufferConstraints} or null if report is unavailable
-     * or unsupported
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @Nullable BufferConstraints getBufferConstraints() {
-        if (VDBG) log("getBufferConstraints()");
-        final IBluetoothA2dp service = getService();
-        final BufferConstraints defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<BufferConstraints> recv =
-                        new SynchronousResultReceiver();
-                service.getBufferConstraints(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set Dynamic Audio Buffer Size.
-     *
-     * @param codec audio codec
-     * @param value buffer millis
-     * @return true to indicate success, or false on immediate error
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    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;
-        }
-        final IBluetoothA2dp service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setBufferLengthMillis(codec, value, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Helper for converting a state to a string.
-     *
-     * For debug use only - strings are not internationalized.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public static String stateToString(int state) {
-        switch (state) {
-            case STATE_DISCONNECTED:
-                return "disconnected";
-            case STATE_CONNECTING:
-                return "connecting";
-            case STATE_CONNECTED:
-                return "connected";
-            case STATE_DISCONNECTING:
-                return "disconnecting";
-            case STATE_PLAYING:
-                return "playing";
-            case STATE_NOT_PLAYING:
-                return "not playing";
-            default:
-                return "<unknown state " + state + ">";
-        }
-    }
-
-    private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
-    }
-
-    private void verifyDeviceNotNull(BluetoothDevice device, String methodName) {
-        if (device == null) {
-            Log.e(TAG, methodName + ": device param is null");
-            throw new IllegalArgumentException("Device cannot be null");
-        }
-    }
-
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
deleted file mode 100755
index 5941681..0000000
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth A2DP Sink
- * profile.
- *
- * <p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothA2dpSink proxy object.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothA2dpSink implements BluetoothProfile {
-    private static final String TAG = "BluetoothA2dpSink";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the A2DP Sink
-     * profile.
-     *
-     * <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}.
-     *
-     * @hide
-     */
-    @SystemApi
-    @SuppressLint("ActionValue")
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
-                    "BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) {
-                @Override
-                public IBluetoothA2dpSink getServiceInterface(IBinder service) {
-                    return IBluetoothA2dpSink.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothA2dp proxy object for interacting with the local
-     * Bluetooth A2DP service.
-     */
-    /* package */ BluetoothA2dpSink(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /*package*/ void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothA2dpSink getService() {
-        return mProfileConnector.getService();
-    }
-
-    @Override
-    public void finalize() {
-        close();
-    }
-
-    /**
-     * Initiate connection to a profile of the remote bluetooth device.
-     *
-     * <p> Currently, the system supports only 1 connection to the
-     * A2DP profile. The API will automatically disconnect connected
-     * devices before connecting.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothA2dpSink service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothA2dpSink service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothA2dpSink service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothA2dpSink service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (VDBG) log("getConnectionState(" + device + ")");
-        final IBluetoothA2dpSink service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the current audio configuration for the A2DP source device,
-     * or null if the device has no audio configuration
-     *
-     * @param device Remote bluetooth device.
-     * @return audio configuration for the device, or null
-     *
-     * {@see BluetoothAudioConfig}
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
-        if (VDBG) log("getAudioConfig(" + device + ")");
-        final IBluetoothA2dpSink service = getService();
-        final BluetoothAudioConfig defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<BluetoothAudioConfig> recv =
-                        new SynchronousResultReceiver();
-                service.getAudioConfig(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothA2dpSink service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothA2dpSink service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Check if audio is playing on the bluetooth device (A2DP profile is streaming music).
-     *
-     * @param device BluetoothDevice device
-     * @return true if audio is playing (A2dp is streaming music), false otherwise
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean isAudioPlaying(@NonNull BluetoothDevice device) {
-        if (VDBG) log("isAudioPlaying(" + device + ")");
-        final IBluetoothA2dpSink service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isA2dpPlaying(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Helper for converting a state to a string.
-     *
-     * For debug use only - strings are not internationalized.
-     *
-     * @hide
-     */
-    public static String stateToString(int state) {
-        switch (state) {
-            case STATE_DISCONNECTED:
-                return "disconnected";
-            case STATE_CONNECTING:
-                return "connecting";
-            case STATE_CONNECTED:
-                return "connected";
-            case STATE_DISCONNECTING:
-                return "disconnecting";
-            case BluetoothA2dp.STATE_PLAYING:
-                return "playing";
-            case BluetoothA2dp.STATE_NOT_PLAYING:
-                return "not playing";
-            default:
-                return "<unknown state " + state + ">";
-        }
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    private static boolean isValidDevice(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/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
deleted file mode 100644
index c17a7b4..0000000
--- a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.ElapsedRealtimeLong;
-import android.annotation.IntDef;
-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.Collections;
-import java.util.List;
-
-/**
- * Record of energy and activity information from controller and
- * underlying bt stack state.Timestamp the record with system
- * time.
- *
- * @hide
- */
-@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
-public final class BluetoothActivityEnergyInfo implements Parcelable {
-    private final long mTimestamp;
-    private int mBluetoothStackState;
-    private long mControllerTxTimeMs;
-    private long mControllerRxTimeMs;
-    private long mControllerIdleTimeMs;
-    private long mControllerEnergyUsed;
-    private List<UidTraffic> mUidTraffic;
-
-    /** @hide */
-    @IntDef(prefix = { "BT_STACK_STATE_" }, value = {
-            BT_STACK_STATE_INVALID,
-            BT_STACK_STATE_STATE_ACTIVE,
-            BT_STACK_STATE_STATE_SCANNING,
-            BT_STACK_STATE_STATE_IDLE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface BluetoothStackState {}
-
-    public static final int BT_STACK_STATE_INVALID = 0;
-    public static final int BT_STACK_STATE_STATE_ACTIVE = 1;
-    public static final int BT_STACK_STATE_STATE_SCANNING = 2;
-    public static final int BT_STACK_STATE_STATE_IDLE = 3;
-
-    /** @hide */
-    public BluetoothActivityEnergyInfo(long timestamp, int stackState,
-            long txTime, long rxTime, long idleTime, long energyUsed) {
-        mTimestamp = timestamp;
-        mBluetoothStackState = stackState;
-        mControllerTxTimeMs = txTime;
-        mControllerRxTimeMs = rxTime;
-        mControllerIdleTimeMs = idleTime;
-        mControllerEnergyUsed = energyUsed;
-    }
-
-    /** @hide */
-    private BluetoothActivityEnergyInfo(Parcel in) {
-        mTimestamp = in.readLong();
-        mBluetoothStackState = in.readInt();
-        mControllerTxTimeMs = in.readLong();
-        mControllerRxTimeMs = in.readLong();
-        mControllerIdleTimeMs = in.readLong();
-        mControllerEnergyUsed = in.readLong();
-        mUidTraffic = in.createTypedArrayList(UidTraffic.CREATOR);
-    }
-
-    /** @hide */
-    @Override
-    public String toString() {
-        return "BluetoothActivityEnergyInfo{"
-                + " mTimestamp=" + mTimestamp
-                + " mBluetoothStackState=" + mBluetoothStackState
-                + " mControllerTxTimeMs=" + mControllerTxTimeMs
-                + " mControllerRxTimeMs=" + mControllerRxTimeMs
-                + " mControllerIdleTimeMs=" + mControllerIdleTimeMs
-                + " mControllerEnergyUsed=" + mControllerEnergyUsed
-                + " mUidTraffic=" + mUidTraffic
-                + " }";
-    }
-
-    public static final @NonNull Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR =
-            new Parcelable.Creator<BluetoothActivityEnergyInfo>() {
-                public BluetoothActivityEnergyInfo createFromParcel(Parcel in) {
-                    return new BluetoothActivityEnergyInfo(in);
-                }
-
-                public BluetoothActivityEnergyInfo[] newArray(int size) {
-                    return new BluetoothActivityEnergyInfo[size];
-                }
-            };
-
-    /** @hide */
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeLong(mTimestamp);
-        out.writeInt(mBluetoothStackState);
-        out.writeLong(mControllerTxTimeMs);
-        out.writeLong(mControllerRxTimeMs);
-        out.writeLong(mControllerIdleTimeMs);
-        out.writeLong(mControllerEnergyUsed);
-        out.writeTypedList(mUidTraffic);
-    }
-
-    /** @hide */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Get the Bluetooth stack state associated with the energy info.
-     *
-     * @return one of {@link #BluetoothStackState} states
-     */
-    @BluetoothStackState
-    public int getBluetoothStackState() {
-        return mBluetoothStackState;
-    }
-
-    /**
-     * @return tx time in ms
-     */
-    public long getControllerTxTimeMillis() {
-        return mControllerTxTimeMs;
-    }
-
-    /**
-     * @return rx time in ms
-     */
-    public long getControllerRxTimeMillis() {
-        return mControllerRxTimeMs;
-    }
-
-    /**
-     * @return idle time in ms
-     */
-    public long getControllerIdleTimeMillis() {
-        return mControllerIdleTimeMs;
-    }
-
-    /**
-     * Get the product of current (mA), voltage (V), and time (ms).
-     *
-     * @return energy used
-     */
-    public long getControllerEnergyUsed() {
-        return mControllerEnergyUsed;
-    }
-
-    /**
-     * @return timestamp (real time elapsed in milliseconds since boot) of record creation
-     */
-    public @ElapsedRealtimeLong long getTimestampMillis() {
-        return mTimestamp;
-    }
-
-    /**
-     * Get the {@link List} of each application {@link android.bluetooth.UidTraffic}.
-     *
-     * @return current {@link List} of {@link android.bluetooth.UidTraffic}
-     */
-    public @NonNull List<UidTraffic> getUidTraffic() {
-        if (mUidTraffic == null) {
-            return Collections.emptyList();
-        }
-        return mUidTraffic;
-    }
-
-    /** @hide */
-    public void setUidTraffic(List<UidTraffic> traffic) {
-        mUidTraffic = traffic;
-    }
-
-    /**
-     * @return true if the record Tx time, Rx time, and Idle time are more than 0.
-     */
-    public boolean isValid() {
-        return ((mControllerTxTimeMs >= 0) && (mControllerRxTimeMs >= 0)
-                && (mControllerIdleTimeMs >= 0));
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
deleted file mode 100644
index c6c64b0..0000000
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ /dev/null
@@ -1,4396 +0,0 @@
-/*
- * Copyright 2009-2016 The Android Open Source Project
- * Copyright 2015 Samsung LSI
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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 static java.util.Objects.requireNonNull;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.app.PropertyInvalidatedCache;
-import android.bluetooth.BluetoothDevice.Transport;
-import android.bluetooth.BluetoothProfile.ConnectionPolicy;
-import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.bluetooth.le.BluetoothLeAdvertiser;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.PeriodicAdvertisingManager;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanRecord;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.sysprop.BluetoothProperties;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.WeakHashMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
- * lets you perform fundamental Bluetooth tasks, such as initiate
- * device discovery, query a list of bonded (paired) devices,
- * instantiate a {@link BluetoothDevice} using a known MAC address, and create
- * a {@link BluetoothServerSocket} to listen for connection requests from other
- * devices, and start a scan for Bluetooth LE devices.
- *
- * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
- * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
- * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
- * method instead.
- * </p><p>
- * Fundamentally, this is your starting point for all
- * Bluetooth actions. Once you have the local adapter, you can get a set of
- * {@link BluetoothDevice} objects representing all paired devices with
- * {@link #getBondedDevices()}; start device discovery with
- * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
- * listen for incoming RFComm connection requests with {@link
- * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
- * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
- * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
- * </p>
- * <p>This class is thread safe.</p>
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about using Bluetooth, read the <a href=
- * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
- * guide.
- * </p>
- * </div>
- *
- * {@see BluetoothDevice}
- * {@see BluetoothServerSocket}
- */
-public final class BluetoothAdapter {
-    private static final String TAG = "BluetoothAdapter";
-    private static final String DESCRIPTOR = "android.bluetooth.BluetoothAdapter";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Default MAC address reported to a client that does not have the
-     * android.permission.LOCAL_MAC_ADDRESS permission.
-     *
-     * @hide
-     */
-    public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
-
-    /**
-     * Sentinel error value for this class. Guaranteed to not equal any other
-     * integer constant in this class. Provided as a convenience for functions
-     * that require a sentinel error value, for example:
-     * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-     * BluetoothAdapter.ERROR)</code>
-     */
-    public static final int ERROR = Integer.MIN_VALUE;
-
-    /**
-     * Broadcast Action: The state of the local Bluetooth adapter has been
-     * changed.
-     * <p>For example, Bluetooth has been turned on or off.
-     * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
-     * #EXTRA_PREVIOUS_STATE} containing the new and old states
-     * respectively.
-     */
-    @RequiresLegacyBluetoothPermission
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
-            ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
-     * intents to request the current power state. Possible values are:
-     * {@link #STATE_OFF},
-     * {@link #STATE_TURNING_ON},
-     * {@link #STATE_ON},
-     * {@link #STATE_TURNING_OFF},
-     */
-    public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
-    /**
-     * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
-     * intents to request the previous power state. Possible values are:
-     * {@link #STATE_OFF},
-     * {@link #STATE_TURNING_ON},
-     * {@link #STATE_ON},
-     * {@link #STATE_TURNING_OFF}
-     */
-    public static final String EXTRA_PREVIOUS_STATE =
-            "android.bluetooth.adapter.extra.PREVIOUS_STATE";
-
-    /** @hide */
-    @IntDef(prefix = { "STATE_" }, value = {
-            STATE_OFF,
-            STATE_TURNING_ON,
-            STATE_ON,
-            STATE_TURNING_OFF,
-            STATE_BLE_TURNING_ON,
-            STATE_BLE_ON,
-            STATE_BLE_TURNING_OFF
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AdapterState {}
-
-    /**
-     * Indicates the local Bluetooth adapter is off.
-     */
-    public static final int STATE_OFF = 10;
-    /**
-     * Indicates the local Bluetooth adapter is turning on. However local
-     * clients should wait for {@link #STATE_ON} before attempting to
-     * use the adapter.
-     */
-    public static final int STATE_TURNING_ON = 11;
-    /**
-     * Indicates the local Bluetooth adapter is on, and ready for use.
-     */
-    public static final int STATE_ON = 12;
-    /**
-     * Indicates the local Bluetooth adapter is turning off. Local clients
-     * should immediately attempt graceful disconnection of any remote links.
-     */
-    public static final int STATE_TURNING_OFF = 13;
-
-    /**
-     * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
-     *
-     * @hide
-     */
-    public static final int STATE_BLE_TURNING_ON = 14;
-
-    /**
-     * Indicates the local Bluetooth adapter is in LE only mode.
-     *
-     * @hide
-     */
-    public static final int STATE_BLE_ON = 15;
-
-    /**
-     * Indicates the local Bluetooth adapter is turning off LE only mode.
-     *
-     * @hide
-     */
-    public static final int STATE_BLE_TURNING_OFF = 16;
-
-    /**
-     * UUID of the GATT Read Characteristics for LE_PSM value.
-     *
-     * @hide
-     */
-    public static final UUID LE_PSM_CHARACTERISTIC_UUID =
-            UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
-
-    /**
-     * Human-readable string helper for AdapterState
-     *
-     * @hide
-     */
-    public static String nameForState(@AdapterState int state) {
-        switch (state) {
-            case STATE_OFF:
-                return "OFF";
-            case STATE_TURNING_ON:
-                return "TURNING_ON";
-            case STATE_ON:
-                return "ON";
-            case STATE_TURNING_OFF:
-                return "TURNING_OFF";
-            case STATE_BLE_TURNING_ON:
-                return "BLE_TURNING_ON";
-            case STATE_BLE_ON:
-                return "BLE_ON";
-            case STATE_BLE_TURNING_OFF:
-                return "BLE_TURNING_OFF";
-            default:
-                return "?!?!? (" + state + ")";
-        }
-    }
-
-    /**
-     * Activity Action: Show a system activity that requests discoverable mode.
-     * This activity will also request the user to turn on Bluetooth if it
-     * is not currently enabled.
-     * <p>Discoverable mode is equivalent to {@link
-     * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
-     * this Bluetooth adapter when they perform a discovery.
-     * <p>For privacy, Android is not discoverable by default.
-     * <p>The sender of this Intent can optionally use extra field {@link
-     * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
-     * discoverability. Currently the default duration is 120 seconds, and
-     * maximum duration is capped at 300 seconds for each request.
-     * <p>Notification of the result of this activity is posted using the
-     * {@link android.app.Activity#onActivityResult} callback. The
-     * <code>resultCode</code>
-     * will be the duration (in seconds) of discoverability or
-     * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
-     * discoverability or an error has occurred.
-     * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
-     * for global notification whenever the scan mode changes. For example, an
-     * application can be notified when the device has ended discoverability.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
-            ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
-
-    /**
-     * Used as an optional int extra field in {@link
-     * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
-     * for discoverability in seconds. The current default is 120 seconds, and
-     * requests over 300 seconds will be capped. These values could change.
-     */
-    public static final String EXTRA_DISCOVERABLE_DURATION =
-            "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
-
-    /**
-     * Activity Action: Show a system activity that allows the user to turn on
-     * Bluetooth.
-     * <p>This system activity will return once Bluetooth has completed turning
-     * on, or the user has decided not to turn Bluetooth on.
-     * <p>Notification of the result of this activity is posted using the
-     * {@link android.app.Activity#onActivityResult} callback. The
-     * <code>resultCode</code>
-     * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
-     * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
-     * has rejected the request or an error has occurred.
-     * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
-     * for global notification whenever Bluetooth is turned on or off.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
-            ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
-
-    /**
-     * Activity Action: Show a system activity that allows the user to turn off
-     * Bluetooth. This is used only if permission review is enabled which is for
-     * apps targeting API less than 23 require a permission review before any of
-     * the app's components can run.
-     * <p>This system activity will return once Bluetooth has completed turning
-     * off, or the user has decided not to turn Bluetooth off.
-     * <p>Notification of the result of this activity is posted using the
-     * {@link android.app.Activity#onActivityResult} callback. The
-     * <code>resultCode</code>
-     * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
-     * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
-     * has rejected the request or an error has occurred.
-     * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
-     * for global notification whenever Bluetooth is turned on or off.
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
-            ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
-
-    /**
-     * Activity Action: Show a system activity that allows user to enable BLE scans even when
-     * Bluetooth is turned off.<p>
-     *
-     * Notification of result of this activity is posted using
-     * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
-     * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
-     * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
-     * error occurred.
-     *
-     * @hide
-     */
-    @SystemApi
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
-            "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
-
-    /**
-     * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
-     * has changed.
-     * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
-     * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
-     * respectively.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
-            ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
-     * intents to request the current scan mode. Possible values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
-     */
-    public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
-    /**
-     * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
-     * intents to request the previous scan mode. Possible values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
-     */
-    public static final String EXTRA_PREVIOUS_SCAN_MODE =
-            "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
-
-    /** @hide */
-    @IntDef(prefix = { "SCAN_" }, value = {
-            SCAN_MODE_NONE,
-            SCAN_MODE_CONNECTABLE,
-            SCAN_MODE_CONNECTABLE_DISCOVERABLE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ScanMode {}
-
-    /**
-     * Indicates that both inquiry scan and page scan are disabled on the local
-     * Bluetooth adapter. Therefore this device is neither discoverable
-     * nor connectable from remote Bluetooth devices.
-     */
-    public static final int SCAN_MODE_NONE = 20;
-    /**
-     * Indicates that inquiry scan is disabled, but page scan is enabled on the
-     * local Bluetooth adapter. Therefore this device is not discoverable from
-     * remote Bluetooth devices, but is connectable from remote devices that
-     * have previously discovered this device.
-     */
-    public static final int SCAN_MODE_CONNECTABLE = 21;
-    /**
-     * Indicates that both inquiry scan and page scan are enabled on the local
-     * Bluetooth adapter. Therefore this device is both discoverable and
-     * connectable from remote Bluetooth devices.
-     */
-    public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
-
-    /**
-     * Device only has a display.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_OUT = 0;
-
-    /**
-     * Device has a display and the ability to input Yes/No.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_IO = 1;
-
-    /**
-     * Device only has a keyboard for entry but no display.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_IN = 2;
-
-    /**
-     * Device has no Input or Output capability.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_NONE = 3;
-
-    /**
-     * Device has a display and a full keyboard.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_KBDISP = 4;
-
-    /**
-     * Maximum range value for Input/Output capabilities.
-     *
-     * <p>This should be updated when adding a new Input/Output capability. Other code
-     * like validation depends on this being accurate.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_MAX = 5;
-
-    /**
-     * The Input/Output capability of the device is unknown.
-     *
-     * @hide
-     */
-    public static final int IO_CAPABILITY_UNKNOWN = 255;
-
-    /** @hide */
-    @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
-            IO_CAPABILITY_KBDISP})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface IoCapability {}
-
-    /** @hide */
-    @IntDef(prefix = "ACTIVE_DEVICE_", value = {ACTIVE_DEVICE_AUDIO,
-            ACTIVE_DEVICE_PHONE_CALL, ACTIVE_DEVICE_ALL})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ActiveDeviceUse {}
-
-    /**
-     * Use the specified device for audio (a2dp and hearing aid profile)
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ACTIVE_DEVICE_AUDIO = 0;
-
-    /**
-     * Use the specified device for phone calls (headset profile and hearing
-     * aid profile)
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ACTIVE_DEVICE_PHONE_CALL = 1;
-
-    /**
-     * Use the specified device for a2dp, hearing aid profile, and headset profile
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ACTIVE_DEVICE_ALL = 2;
-
-    /** @hide */
-    @IntDef({BluetoothProfile.HEADSET, BluetoothProfile.A2DP,
-            BluetoothProfile.HEARING_AID})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ActiveDeviceProfile {}
-
-    /**
-     * Broadcast Action: The local Bluetooth adapter has started the remote
-     * device discovery process.
-     * <p>This usually involves an inquiry scan of about 12 seconds, followed
-     * by a page scan of each new device to retrieve its Bluetooth name.
-     * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
-     * remote Bluetooth devices are found.
-     * <p>Device discovery is a heavyweight procedure. New connections to
-     * remote Bluetooth devices should not be attempted while discovery is in
-     * progress, and existing connections will experience limited bandwidth
-     * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
-     * discovery.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
-            ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
-    /**
-     * Broadcast Action: The local Bluetooth adapter has finished the device
-     * discovery process.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
-            ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
-
-    /**
-     * Broadcast Action: The local Bluetooth adapter has changed its friendly
-     * Bluetooth name.
-     * <p>This name is visible to remote Bluetooth devices.
-     * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
-     * the name.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
-            ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
-    /**
-     * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
-     * intents to request the local Bluetooth name.
-     */
-    public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
-
-    /**
-     * Intent used to broadcast the change in connection state of the local
-     * Bluetooth adapter to a profile of the remote device. When the adapter is
-     * not connected to any profiles of any remote devices and it attempts a
-     * connection to a profile this intent will be sent. Once connected, this intent
-     * will not be sent for any more connection attempts to any profiles of any
-     * remote device. When the adapter disconnects from the last profile its
-     * connected to of any remote device, this intent will be sent.
-     *
-     * <p> This intent is useful for applications that are only concerned about
-     * whether the local adapter is connected to any profile of any device and
-     * are not really concerned about which profile. For example, an application
-     * which displays an icon to display whether Bluetooth is connected or not
-     * can use this intent.
-     *
-     * <p>This intent will have 3 extras:
-     * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
-     * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
-     * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
-     *
-     * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
-     * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
-     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
-            ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
-     *
-     * This extra represents the current connection state.
-     */
-    public static final String EXTRA_CONNECTION_STATE =
-            "android.bluetooth.adapter.extra.CONNECTION_STATE";
-
-    /**
-     * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
-     *
-     * This extra represents the previous connection state.
-     */
-    public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
-            "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
-
-    /**
-     * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
-     *
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
-            "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the change in the Bluetooth address
-     * of the local Bluetooth adapter.
-     * <p>Always contains the extra field {@link
-     * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
-     *
-     * Note: only system level processes are allowed to send this
-     * defined broadcast.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
-            "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
-
-    /**
-     * Used as a String extra field in {@link
-     * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
-     * Bluetooth address.
-     *
-     * @hide
-     */
-    public static final String EXTRA_BLUETOOTH_ADDRESS =
-            "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
-
-    /**
-     * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
-     * by BLE Always on enabled application to know the ACL_CONNECTED event
-     * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
-     * as Bluetooth LE is the only feature available in STATE_BLE_ON
-     *
-     * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
-     * works in Bluetooth state STATE_ON
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_BLE_ACL_CONNECTED =
-            "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
-
-    /**
-     * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
-     * by BLE Always on enabled application to know the ACL_DISCONNECTED event
-     * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
-     * LE is the only feature available in STATE_BLE_ON
-     *
-     * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
-     * works in Bluetooth state STATE_ON
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_BLE_ACL_DISCONNECTED =
-            "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
-
-    /** The profile is in disconnected state */
-    public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
-    /** The profile is in connecting state */
-    public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
-    /** The profile is in connected state */
-    public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
-    /** The profile is in disconnecting state */
-    public static final int STATE_DISCONNECTING =
-            BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
-
-    /** @hide */
-    public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
-    private final IBinder mToken;
-
-
-    /**
-     * When creating a ServerSocket using listenUsingRfcommOn() or
-     * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
-     * a ServerSocket that auto assigns a channel number to the first
-     * bluetooth socket.
-     * The channel number assigned to this first Bluetooth Socket will
-     * be stored in the ServerSocket, and reused for subsequent Bluetooth
-     * sockets.
-     *
-     * @hide
-     */
-    public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
-
-
-    private static final int ADDRESS_LENGTH = 17;
-
-    /**
-     * Lazily initialized singleton. Guaranteed final after first object
-     * constructed.
-     */
-    private static BluetoothAdapter sAdapter;
-
-    private BluetoothLeScanner mBluetoothLeScanner;
-    private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
-    private PeriodicAdvertisingManager mPeriodicAdvertisingManager;
-
-    private final IBluetoothManager mManagerService;
-    private final AttributionSource mAttributionSource;
-
-    // Yeah, keeping both mService and sService isn't pretty, but it's too late
-    // in the current release for a major refactoring, so we leave them both
-    // intact until this can be cleaned up in a future release
-
-    @UnsupportedAppUsage
-    @GuardedBy("mServiceLock")
-    private IBluetooth mService;
-    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
-
-    @GuardedBy("sServiceLock")
-    private static boolean sServiceRegistered;
-    @GuardedBy("sServiceLock")
-    private static IBluetooth sService;
-    private static final Object sServiceLock = new Object();
-
-    private final Object mLock = new Object();
-    private final Map<LeScanCallback, ScanCallback> mLeScanClients;
-    private final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
-                mMetadataListeners = new HashMap<>();
-    private final Map<BluetoothConnectionCallback, Executor>
-            mBluetoothConnectionCallbackExecutorMap = new HashMap<>();
-
-    /**
-     * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
-     * implementation.
-     */
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final IBluetoothMetadataListener mBluetoothMetadataListener =
-            new IBluetoothMetadataListener.Stub() {
-        @Override
-        public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            synchronized (mMetadataListeners) {
-                if (mMetadataListeners.containsKey(device)) {
-                    List<Pair<OnMetadataChangedListener, Executor>> list =
-                            mMetadataListeners.get(device);
-                    for (Pair<OnMetadataChangedListener, Executor> pair : list) {
-                        OnMetadataChangedListener listener = pair.first;
-                        Executor executor = pair.second;
-                        executor.execute(() -> {
-                            listener.onMetadataChanged(device, key, value);
-                        });
-                    }
-                }
-            }
-            return;
-        }
-    };
-
-    /**
-     * Get a handle to the default local Bluetooth adapter.
-     * <p>
-     * Currently Android only supports one Bluetooth adapter, but the API could
-     * be extended to support more. This will always return the default adapter.
-     * </p>
-     *
-     * @return the default local adapter, or null if Bluetooth is not supported
-     *         on this hardware platform
-     * @deprecated this method will continue to work, but developers are
-     *             strongly encouraged to migrate to using
-     *             {@link BluetoothManager#getAdapter()}, since that approach
-     *             enables support for {@link Context#createAttributionContext}.
-     */
-    @Deprecated
-    @RequiresNoPermission
-    public static synchronized BluetoothAdapter getDefaultAdapter() {
-        if (sAdapter == null) {
-            sAdapter = createAdapter(AttributionSource.myAttributionSource());
-        }
-        return sAdapter;
-    }
-
-    /** {@hide} */
-    public static BluetoothAdapter createAdapter(AttributionSource attributionSource) {
-        IBinder binder = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
-        if (binder != null) {
-            return new BluetoothAdapter(IBluetoothManager.Stub.asInterface(binder),
-                    attributionSource);
-        } else {
-            Log.e(TAG, "Bluetooth binder is null");
-            return null;
-        }
-    }
-
-    /**
-     * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
-     */
-    BluetoothAdapter(IBluetoothManager managerService, AttributionSource attributionSource) {
-        mManagerService = Objects.requireNonNull(managerService);
-        mAttributionSource = Objects.requireNonNull(attributionSource);
-        synchronized (mServiceLock.writeLock()) {
-            mService = getBluetoothService(mManagerCallback);
-        }
-        mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
-        mToken = new Binder(DESCRIPTOR);
-    }
-
-    /**
-     * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
-     * address.
-     * <p>Valid Bluetooth hardware addresses must be upper case, in a format
-     * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
-     * available to validate a Bluetooth address.
-     * <p>A {@link BluetoothDevice} will always be returned for a valid
-     * hardware address, even if this adapter has never seen that device.
-     *
-     * @param address valid Bluetooth MAC address
-     * @throws IllegalArgumentException if address is invalid
-     */
-    @RequiresNoPermission
-    public BluetoothDevice getRemoteDevice(String address) {
-        final BluetoothDevice res = new BluetoothDevice(address);
-        res.setAttributionSource(mAttributionSource);
-        return res;
-    }
-
-    /**
-     * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
-     * address.
-     * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
-     * expects the address in network byte order (MSB first).
-     * <p>A {@link BluetoothDevice} will always be returned for a valid
-     * hardware address, even if this adapter has never seen that device.
-     *
-     * @param address Bluetooth MAC address (6 bytes)
-     * @throws IllegalArgumentException if address is invalid
-     */
-    @RequiresNoPermission
-    public BluetoothDevice getRemoteDevice(byte[] address) {
-        if (address == null || address.length != 6) {
-            throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
-        }
-        final BluetoothDevice res = new BluetoothDevice(
-                String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
-                        address[2], address[3], address[4], address[5]));
-        res.setAttributionSource(mAttributionSource);
-        return res;
-    }
-
-    /**
-     * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
-     * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
-     * supported on this device.
-     * <p>
-     * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
-     * on this device before calling this method.
-     */
-    @RequiresNoPermission
-    public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
-        if (!getLeAccess()) {
-            return null;
-        }
-        synchronized (mLock) {
-            if (mBluetoothLeAdvertiser == null) {
-                mBluetoothLeAdvertiser = new BluetoothLeAdvertiser(this);
-            }
-            return mBluetoothLeAdvertiser;
-        }
-    }
-
-    /**
-     * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
-     * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
-     * Advertising is not supported on this device.
-     * <p>
-     * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
-     * supported on this device before calling this method.
-     *
-     * @hide
-     */
-    @RequiresNoPermission
-    public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
-        if (!getLeAccess()) {
-            return null;
-        }
-
-        if (!isLePeriodicAdvertisingSupported()) {
-            return null;
-        }
-
-        synchronized (mLock) {
-            if (mPeriodicAdvertisingManager == null) {
-                mPeriodicAdvertisingManager = new PeriodicAdvertisingManager(this);
-            }
-            return mPeriodicAdvertisingManager;
-        }
-    }
-
-    /**
-     * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
-     */
-    @RequiresNoPermission
-    public BluetoothLeScanner getBluetoothLeScanner() {
-        if (!getLeAccess()) {
-            return null;
-        }
-        synchronized (mLock) {
-            if (mBluetoothLeScanner == null) {
-                mBluetoothLeScanner = new BluetoothLeScanner(this);
-            }
-            return mBluetoothLeScanner;
-        }
-    }
-
-    /**
-     * Return true if Bluetooth is currently enabled and ready for use.
-     * <p>Equivalent to:
-     * <code>getBluetoothState() == STATE_ON</code>
-     *
-     * @return true if the local adapter is turned on
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isEnabled() {
-        return getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    /**
-     * Return true if Bluetooth LE(Always BLE On feature) is currently
-     * enabled and ready for use
-     * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
-     *
-     * @return true if the local Bluetooth LE adapter is turned on
-     * @hide
-     */
-    @SystemApi
-    @RequiresNoPermission
-    public boolean isLeEnabled() {
-        final int state = getLeState();
-        if (DBG) {
-            Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
-        }
-        return (state == BluetoothAdapter.STATE_ON
-                || state == BluetoothAdapter.STATE_BLE_ON
-                || state == BluetoothAdapter.STATE_TURNING_ON
-                || state == BluetoothAdapter.STATE_TURNING_OFF);
-    }
-
-    /**
-     * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
-     *
-     * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
-     * to STATE_OFF and completely shut-down Bluetooth
-     *
-     * <p> If the Adapter state is STATE_ON, This would unregister the existance of
-     * special Bluetooth LE application and hence the further turning off of Bluetooth
-     * from UI would ensure the complete turn-off of Bluetooth rather than staying back
-     * BLE only state
-     *
-     * <p>This is an asynchronous call: it will return immediately, and
-     * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
-     * to be notified of subsequent adapter state changes If this call returns
-     * true, then the adapter state will immediately transition from {@link
-     * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
-     * later transition to either {@link #STATE_BLE_ON} or {@link
-     * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
-     * If this call returns false then there was an
-     * immediate problem that will prevent the QAdapter from being turned off -
-     * such as the QAadapter already being turned off.
-     *
-     * @return true to indicate success, or false on immediate error
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disableBLE() {
-        if (!isBleScanAlwaysAvailable()) {
-            return false;
-        }
-        try {
-            return mManagerService.disableBle(mAttributionSource, mToken);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
-     *
-     * enableBLE registers the existence of an app using only LE functions.
-     *
-     * enableBLE may enable Bluetooth to an LE only mode so that an app can use
-     * LE related features (BluetoothGatt or BluetoothGattServer classes)
-     *
-     * If the user disables Bluetooth while an app is registered to use LE only features,
-     * Bluetooth will remain on in LE only mode for the app.
-     *
-     * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
-     *
-     * <p>This is an asynchronous call: it returns immediately, and
-     * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
-     * to be notified of adapter state changes.
-     *
-     * If this call returns * true, then the adapter state is either in a mode where
-     * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
-     * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
-     *
-     * If this call returns false then there was an immediate problem that prevents the
-     * adapter from being turned on - such as Airplane mode.
-     *
-     * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
-     * states, It includes all the classic Bluetooth Adapter states along with
-     * internal BLE only states
-     *
-     * @return true to indicate Bluetooth LE will be available, or false on immediate error
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean enableBLE() {
-        if (!isBleScanAlwaysAvailable()) {
-            return false;
-        }
-        try {
-            return mManagerService.enableBle(mAttributionSource, mToken);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-
-        return false;
-    }
-
-    private static final String BLUETOOTH_GET_STATE_CACHE_PROPERTY = "cache_key.bluetooth.get_state";
-
-    private final PropertyInvalidatedCache<Void, Integer> mBluetoothGetStateCache =
-            new PropertyInvalidatedCache<Void, Integer>(
-                8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) {
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                protected Integer recompute(Void query) {
-                    try {
-                        return mService.getState();
-                    } catch (RemoteException e) {
-                        throw e.rethrowFromSystemServer();
-                    }
-                }
-            };
-
-    /** @hide */
-    @RequiresNoPermission
-    public void disableBluetoothGetStateCache() {
-        mBluetoothGetStateCache.disableLocal();
-    }
-
-    /** @hide */
-    public static void invalidateBluetoothGetStateCache() {
-        PropertyInvalidatedCache.invalidateCache(BLUETOOTH_GET_STATE_CACHE_PROPERTY);
-    }
-
-    /**
-     * Fetch the current bluetooth state.  If the service is down, return
-     * OFF.
-     */
-    @AdapterState
-    private int getStateInternal() {
-        int state = BluetoothAdapter.STATE_OFF;
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                state = mBluetoothGetStateCache.query(null);
-            }
-        } catch (RuntimeException e) {
-            if (e.getCause() instanceof RemoteException) {
-                Log.e(TAG, "", e.getCause());
-            } else {
-                throw e;
-            }
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return state;
-    }
-
-    /**
-     * Get the current state of the local Bluetooth adapter.
-     * <p>Possible return values are
-     * {@link #STATE_OFF},
-     * {@link #STATE_TURNING_ON},
-     * {@link #STATE_ON},
-     * {@link #STATE_TURNING_OFF}.
-     *
-     * @return current state of Bluetooth adapter
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    @AdapterState
-    public int getState() {
-        int state = getStateInternal();
-
-        // Consider all internal states as OFF
-        if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
-                || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
-            if (VDBG) {
-                Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
-            }
-            state = BluetoothAdapter.STATE_OFF;
-        }
-        if (VDBG) {
-            Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
-                    state));
-        }
-        return state;
-    }
-
-    /**
-     * Get the current state of the local Bluetooth adapter
-     * <p>This returns current internal state of Adapter including LE ON/OFF
-     *
-     * <p>Possible return values are
-     * {@link #STATE_OFF},
-     * {@link #STATE_BLE_TURNING_ON},
-     * {@link #STATE_BLE_ON},
-     * {@link #STATE_TURNING_ON},
-     * {@link #STATE_ON},
-     * {@link #STATE_TURNING_OFF},
-     * {@link #STATE_BLE_TURNING_OFF}.
-     *
-     * @return current state of Bluetooth adapter
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    @AdapterState
-    @UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine "
-            + "whether you can use BLE & BT classic.")
-    public int getLeState() {
-        int state = getStateInternal();
-
-        if (VDBG) {
-            Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
-        }
-        return state;
-    }
-
-    boolean getLeAccess() {
-        if (getLeState() == STATE_ON) {
-            return true;
-        } else if (getLeState() == STATE_BLE_ON) {
-            return true; // TODO: FILTER SYSTEM APPS HERE <--
-        }
-
-        return false;
-    }
-
-    /**
-     * Turn on the local Bluetooth adapter&mdash;do not use without explicit
-     * user action to turn on Bluetooth.
-     * <p>This powers on the underlying Bluetooth hardware, and starts all
-     * Bluetooth system services.
-     * <p class="caution"><strong>Bluetooth should never be enabled without
-     * direct user consent</strong>. If you want to turn on Bluetooth in order
-     * to create a wireless connection, you should use the {@link
-     * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
-     * user permission to turn on Bluetooth. The {@link #enable()} method is
-     * provided only for applications that include a user interface for changing
-     * system settings, such as a "power manager" app.</p>
-     * <p>This is an asynchronous call: it will return immediately, and
-     * clients should listen for {@link #ACTION_STATE_CHANGED}
-     * to be notified of subsequent adapter state changes. If this call returns
-     * true, then the adapter state will immediately transition from {@link
-     * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
-     * later transition to either {@link #STATE_OFF} or {@link
-     * #STATE_ON}. If this call returns false then there was an
-     * immediate problem that will prevent the adapter from being turned on -
-     * such as Airplane mode, or the adapter is already turned on.
-     *
-     * @return true to indicate adapter startup has begun, or false on immediate error
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean enable() {
-        if (isEnabled()) {
-            if (DBG) {
-                Log.d(TAG, "enable(): BT already enabled!");
-            }
-            return true;
-        }
-        try {
-            return mManagerService.enable(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Turn off the local Bluetooth adapter&mdash;do not use without explicit
-     * user action to turn off Bluetooth.
-     * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
-     * system services, and powers down the underlying Bluetooth hardware.
-     * <p class="caution"><strong>Bluetooth should never be disabled without
-     * direct user consent</strong>. The {@link #disable()} method is
-     * provided only for applications that include a user interface for changing
-     * system settings, such as a "power manager" app.</p>
-     * <p>This is an asynchronous call: it will return immediately, and
-     * clients should listen for {@link #ACTION_STATE_CHANGED}
-     * to be notified of subsequent adapter state changes. If this call returns
-     * true, then the adapter state will immediately transition from {@link
-     * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
-     * later transition to either {@link #STATE_OFF} or {@link
-     * #STATE_ON}. If this call returns false then there was an
-     * immediate problem that will prevent the adapter from being turned off -
-     * such as the adapter already being turned off.
-     *
-     * @return true to indicate adapter shutdown has begun, or false on immediate error
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disable() {
-        try {
-            return mManagerService.disable(mAttributionSource, true);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Turn off the local Bluetooth adapter and don't persist the setting.
-     *
-     * @param persist Indicate whether the off state should be persisted following the next reboot
-     * @return true to indicate adapter shutdown has begun, or false on immediate error
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean disable(boolean persist) {
-
-        try {
-            return mManagerService.disable(mAttributionSource, persist);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Returns the hardware address of the local Bluetooth adapter.
-     * <p>For example, "00:11:22:AA:BB:CC".
-     *
-     * @return Bluetooth hardware address as string
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.LOCAL_MAC_ADDRESS,
-    })
-    public String getAddress() {
-        try {
-            return mManagerService.getAddress(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /**
-     * Get the friendly Bluetooth name of the local Bluetooth adapter.
-     * <p>This name is visible to remote Bluetooth devices.
-     *
-     * @return the Bluetooth name, or null on error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public String getName() {
-        try {
-            return mManagerService.getName(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /** {@hide} */
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public int getNameLengthForAdvertise() {
-        try {
-            return mService.getNameLengthForAdvertise(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return -1;
-    }
-
-    /**
-     * Factory reset bluetooth settings.
-     *
-     * @return true to indicate that the config file was successfully cleared
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean factoryReset() {
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null && mService.factoryReset(mAttributionSource)
-                    && mManagerService != null
-                    && mManagerService.onFactoryReset(mAttributionSource)) {
-                return true;
-            }
-            Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later");
-            BluetoothProperties.factory_reset(true);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Get the UUIDs supported by the local Bluetooth adapter.
-     *
-     * @return the UUIDs supported by the local Bluetooth Adapter.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @Nullable ParcelUuid[] getUuids() {
-        if (getState() != STATE_ON) {
-            return null;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getUuids(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return null;
-    }
-
-    /**
-     * Set the friendly Bluetooth name of the local Bluetooth adapter.
-     * <p>This name is visible to remote Bluetooth devices.
-     * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
-     * encoding, although many remote devices can only display the first
-     * 40 characters, and some may be limited to just 20.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     *
-     * @param name a valid Bluetooth name
-     * @return true if the name was set, false otherwise
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setName(String name) {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.setName(name, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
-     * adapter.
-     *
-     * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothClass getBluetoothClass() {
-        if (getState() != STATE_ON) {
-            return null;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getBluetoothClass(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return null;
-    }
-
-    /**
-     * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
-     * adapter.
-     *
-     * <p>Note: This value persists across system reboot.
-     *
-     * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
-     * @return true if successful, false if unsuccessful.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.setBluetoothClass(bluetoothClass, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Returns the Input/Output capability of the device for classic Bluetooth.
-     *
-     * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
-     *         {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
-     *         {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @IoCapability
-    public int getIoCapability() {
-        if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) return mService.getIoCapability(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.getMessage(), e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
-    }
-
-    /**
-     * Sets the Input/Output capability of the device for classic Bluetooth.
-     *
-     * <p>Changing the Input/Output capability of a device only takes effect on restarting the
-     * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
-     * and {@link BluetoothAdapter#enable()} to see the changes.
-     *
-     * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
-     *                   {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
-     *                   {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setIoCapability(@IoCapability int capability) {
-        if (getState() != STATE_ON) return false;
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) return mService.setIoCapability(capability, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.getMessage(), e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Returns the Input/Output capability of the device for BLE operations.
-     *
-     * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
-     *         {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
-     *         {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @IoCapability
-    public int getLeIoCapability() {
-        if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) return mService.getLeIoCapability(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.getMessage(), e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
-    }
-
-    /**
-     * Sets the Input/Output capability of the device for BLE operations.
-     *
-     * <p>Changing the Input/Output capability of a device only takes effect on restarting the
-     * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
-     * and {@link BluetoothAdapter#enable()} to see the changes.
-     *
-     * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
-     *                   {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
-     *                   {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setLeIoCapability(@IoCapability int capability) {
-        if (getState() != STATE_ON) return false;
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) return mService.setLeIoCapability(capability, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.getMessage(), e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Get the current Bluetooth scan mode of the local Bluetooth adapter.
-     * <p>The Bluetooth scan mode determines if the local adapter is
-     * connectable and/or discoverable from remote Bluetooth devices.
-     * <p>Possible values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     *
-     * @return scan mode
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    @ScanMode
-    public int getScanMode() {
-        if (getState() != STATE_ON) {
-            return SCAN_MODE_NONE;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getScanMode(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return SCAN_MODE_NONE;
-    }
-
-    /**
-     * Set the Bluetooth scan mode of the local Bluetooth adapter.
-     * <p>The Bluetooth scan mode determines if the local adapter is
-     * connectable and/or discoverable from remote Bluetooth devices.
-     * <p>For privacy reasons, discoverable mode is automatically turned off
-     * after <code>durationMillis</code> milliseconds. For example, 120000 milliseconds should be
-     * enough for a remote device to initiate and complete its discovery process.
-     * <p>Valid scan mode values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     * <p>Applications cannot set the scan mode. They should use
-     * <code>startActivityForResult(
-     * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
-     * </code>instead.
-     *
-     * @param mode valid scan mode
-     * @param durationMillis time in milliseconds to apply scan mode, only used for {@link
-     * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
-     * @return true if the scan mode was set, false otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which "
-            + "shows UI that confirms the user wants to go into discoverable mode.")
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean setScanMode(@ScanMode int mode, long durationMillis) {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                int durationSeconds = Math.toIntExact(durationMillis / 1000);
-                return mService.setScanMode(mode, durationSeconds, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } catch (ArithmeticException ex) {
-            Log.e(TAG, "setScanMode: Duration in seconds outside of the bounds of an int");
-            throw new IllegalArgumentException("Duration not in bounds. In seconds, the "
-                    + "durationMillis must be in the range of an int");
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Set the Bluetooth scan mode of the local Bluetooth adapter.
-     * <p>The Bluetooth scan mode determines if the local adapter is
-     * connectable and/or discoverable from remote Bluetooth devices.
-     * <p>For privacy reasons, discoverable mode is automatically turned off
-     * after <code>duration</code> seconds. For example, 120 seconds should be
-     * enough for a remote device to initiate and complete its discovery
-     * process.
-     * <p>Valid scan mode values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     * <p>Applications cannot set the scan mode. They should use
-     * <code>startActivityForResult(
-     * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
-     * </code>instead.
-     *
-     * @param mode valid scan mode
-     * @return true if the scan mode was set, false otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean setScanMode(@ScanMode int mode) {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.setScanMode(mode, getDiscoverableTimeout(), mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public int getDiscoverableTimeout() {
-        if (getState() != STATE_ON) {
-            return -1;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getDiscoverableTimeout(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return -1;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void setDiscoverableTimeout(int timeout) {
-        if (getState() != STATE_ON) {
-            return;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                mService.setDiscoverableTimeout(timeout, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-    }
-
-    /**
-     * Get the end time of the latest remote device discovery process.
-     *
-     * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
-     * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
-     * been called recently.
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public long getDiscoveryEndMillis() {
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getDiscoveryEndMillis(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return -1;
-    }
-
-    /**
-     * Start the remote device discovery process.
-     * <p>The discovery process usually involves an inquiry scan of about 12
-     * seconds, followed by a page scan of each new device to retrieve its
-     * Bluetooth name.
-     * <p>This is an asynchronous call, it will return immediately. Register
-     * for {@link #ACTION_DISCOVERY_STARTED} and {@link
-     * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
-     * discovery starts and completes. Register for {@link
-     * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
-     * are found.
-     * <p>Device discovery is a heavyweight procedure. New connections to
-     * remote Bluetooth devices should not be attempted while discovery is in
-     * progress, and existing connections will experience limited bandwidth
-     * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
-     * discovery. Discovery is not managed by the Activity,
-     * but is run as a system service, so an application should always call
-     * {@link BluetoothAdapter#cancelDiscovery()} even if it
-     * did not directly request a discovery, just to be sure.
-     * <p>Device discovery will only find remote devices that are currently
-     * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
-     * not discoverable by default, and need to be entered into a special mode.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth, wait for {@link #ACTION_STATE_CHANGED}
-     * with {@link #STATE_ON} to get the updated value.
-     * <p>If a device is currently bonding, this request will be queued and executed once that
-     * device has finished bonding. If a request is already queued, this request will be ignored.
-     *
-     * @return true on success, false on error
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean startDiscovery() {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.startDiscovery(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Cancel the current device discovery process.
-     * <p>Because discovery is a heavyweight procedure for the Bluetooth
-     * adapter, this method should always be called before attempting to connect
-     * to a remote device with {@link
-     * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
-     * the  Activity, but is run as a system service, so an application should
-     * always call cancel discovery even if it did not directly request a
-     * discovery, just to be sure.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     *
-     * @return true on success, false on error
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean cancelDiscovery() {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.cancelDiscovery(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Return true if the local Bluetooth adapter is currently in the device
-     * discovery process.
-     * <p>Device discovery is a heavyweight procedure. New connections to
-     * remote Bluetooth devices should not be attempted while discovery is in
-     * progress, and existing connections will experience limited bandwidth
-     * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
-     * discovery.
-     * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
-     * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
-     * starts or completes.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     *
-     * @return true if discovering
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean isDiscovering() {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isDiscovering(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Removes the active device for the grouping of @ActiveDeviceUse specified
-     *
-     * @param profiles represents the purpose for which we are setting this as the active device.
-     *                 Possible values are:
-     *                 {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO},
-     *                 {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL},
-     *                 {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
-     * @return false on immediate error, true otherwise
-     * @throws IllegalArgumentException if device is null or profiles is not one of
-     * {@link ActiveDeviceUse}
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean removeActiveDevice(@ActiveDeviceUse int profiles) {
-        if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
-                && profiles != ACTIVE_DEVICE_ALL) {
-            Log.e(TAG, "Invalid profiles param value in removeActiveDevice");
-            throw new IllegalArgumentException("Profiles must be one of "
-                    + "BluetoothAdapter.ACTIVE_DEVICE_AUDIO, "
-                    + "BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL, or "
-                    + "BluetoothAdapter.ACTIVE_DEVICE_ALL");
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                if (DBG) Log.d(TAG, "removeActiveDevice, profiles: " + profiles);
-                return mService.removeActiveDevice(profiles, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-
-        return false;
-    }
-
-    /**
-     * Sets device as the active devices for the profiles passed into the function
-     *
-     * @param device is the remote bluetooth device
-     * @param profiles represents the purpose for which we are setting this as the active device.
-     *                 Possible values are:
-     *                 {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO},
-     *                 {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL},
-     *                 {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
-     * @return false on immediate error, true otherwise
-     * @throws IllegalArgumentException if device is null or profiles is not one of
-     * {@link ActiveDeviceUse}
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean setActiveDevice(@NonNull BluetoothDevice device,
-            @ActiveDeviceUse int profiles) {
-        if (device == null) {
-            Log.e(TAG, "setActiveDevice: Null device passed as parameter");
-            throw new IllegalArgumentException("device cannot be null");
-        }
-        if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
-                && profiles != ACTIVE_DEVICE_ALL) {
-            Log.e(TAG, "Invalid profiles param value in setActiveDevice");
-            throw new IllegalArgumentException("Profiles must be one of "
-                    + "BluetoothAdapter.ACTIVE_DEVICE_AUDIO, "
-                    + "BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL, or "
-                    + "BluetoothAdapter.ACTIVE_DEVICE_ALL");
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                if (DBG) {
-                    Log.d(TAG, "setActiveDevice, device: " + device + ", profiles: " + profiles);
-                }
-                return mService.setActiveDevice(device, profiles, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-
-        return false;
-    }
-
-    /**
-     * Get the active devices for the BluetoothProfile specified
-     *
-     * @param profile is the profile from which we want the active devices.
-     *                Possible values are:
-     *                {@link BluetoothProfile#HEADSET},
-     *                {@link BluetoothProfile#A2DP},
-     *                {@link BluetoothProfile#HEARING_AID}
-     *                {@link BluetoothProfile#LE_AUDIO}
-     * @return A list of active bluetooth devices
-     * @throws IllegalArgumentException If profile is not one of {@link ActiveDeviceProfile}
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @NonNull List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) {
-        if (profile != BluetoothProfile.HEADSET
-                && profile != BluetoothProfile.A2DP
-                && profile != BluetoothProfile.HEARING_AID
-                && profile != BluetoothProfile.LE_AUDIO) {
-            Log.e(TAG, "Invalid profile param value in getActiveDevices");
-            throw new IllegalArgumentException("Profiles must be one of "
-                    + "BluetoothProfile.A2DP, "
-                    + "BluetoothProfile.HEARING_AID, or"
-                    + "BluetoothProfile.HEARING_AID"
-                    + "BluetoothProfile.LE_AUDIO");
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                if (DBG) {
-                    Log.d(TAG, "getActiveDevices(profile= "
-                            + BluetoothProfile.getProfileName(profile) + ")");
-                }
-                return mService.getActiveDevices(profile, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-
-        return new ArrayList<>();
-    }
-
-    /**
-     * Return true if the multi advertisement is supported by the chipset
-     *
-     * @return true if Multiple Advertisement feature is supported
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isMultipleAdvertisementSupported() {
-        if (getState() != STATE_ON) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isMultiAdvertisementSupported();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
-     *
-     * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
-     * fetch scan results even when Bluetooth is turned off.<p>
-     *
-     * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresNoPermission
-    public boolean isBleScanAlwaysAvailable() {
-        try {
-            return mManagerService.isBleScanAlwaysAvailable();
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception when calling isBleScanAlwaysAvailable", e);
-            return false;
-        }
-    }
-
-    private static final String BLUETOOTH_FILTERING_CACHE_PROPERTY =
-            "cache_key.bluetooth.is_offloaded_filtering_supported";
-    private final PropertyInvalidatedCache<Void, Boolean> mBluetoothFilteringCache =
-            new PropertyInvalidatedCache<Void, Boolean>(
-                8, BLUETOOTH_FILTERING_CACHE_PROPERTY) {
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                protected Boolean recompute(Void query) {
-                    try {
-                        mServiceLock.readLock().lock();
-                        if (mService != null) {
-                            return mService.isOffloadedFilteringSupported();
-                        }
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
-                    } finally {
-                        mServiceLock.readLock().unlock();
-                    }
-                    return false;
-
-                }
-            };
-
-    /** @hide */
-    @RequiresNoPermission
-    public void disableIsOffloadedFilteringSupportedCache() {
-        mBluetoothFilteringCache.disableLocal();
-    }
-
-    /** @hide */
-    public static void invalidateIsOffloadedFilteringSupportedCache() {
-        PropertyInvalidatedCache.invalidateCache(BLUETOOTH_FILTERING_CACHE_PROPERTY);
-    }
-
-    /**
-     * Return true if offloaded filters are supported
-     *
-     * @return true if chipset supports on-chip filtering
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isOffloadedFilteringSupported() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        return mBluetoothFilteringCache.query(null);
-    }
-
-    /**
-     * Return true if offloaded scan batching is supported
-     *
-     * @return true if chipset supports on-chip scan batching
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isOffloadedScanBatchingSupported() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isOffloadedScanBatchingSupported();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Return true if LE 2M PHY feature is supported.
-     *
-     * @return true if chipset supports LE 2M PHY feature
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isLe2MPhySupported() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLe2MPhySupported();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Return true if LE Coded PHY feature is supported.
-     *
-     * @return true if chipset supports LE Coded PHY feature
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isLeCodedPhySupported() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLeCodedPhySupported();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Return true if LE Extended Advertising feature is supported.
-     *
-     * @return true if chipset supports LE Extended Advertising feature
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isLeExtendedAdvertisingSupported() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLeExtendedAdvertisingSupported();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /**
-     * Return true if LE Periodic Advertising feature is supported.
-     *
-     * @return true if chipset supports LE Periodic Advertising feature
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public boolean isLePeriodicAdvertisingSupported() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLePeriodicAdvertisingSupported();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            BluetoothStatusCodes.SUCCESS,
-            BluetoothStatusCodes.ERROR_UNKNOWN,
-            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
-            BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED,
-    })
-    public @interface LeFeatureReturnValues {}
-
-    /**
-     * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is
-     * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
-     * the feature is not supported or an error code.
-     *
-     * @return whether the LE audio is supported
-     */
-    @RequiresNoPermission
-    public @LeFeatureReturnValues int isLeAudioSupported() {
-        if (!getLeAccess()) {
-            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLeAudioSupported();
-            }
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return BluetoothStatusCodes.ERROR_UNKNOWN;
-    }
-
-    /**
-     * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
-     * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
-     * feature is not supported or an error code
-     *
-     * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
-     */
-    @RequiresNoPermission
-    public @LeFeatureReturnValues int isLePeriodicAdvertisingSyncTransferSenderSupported() {
-        if (!getLeAccess()) {
-            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLePeriodicAdvertisingSyncTransferSenderSupported();
-            }
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return BluetoothStatusCodes.ERROR_UNKNOWN;
-    }
-
-    /**
-     * Return the maximum LE advertising data length in bytes,
-     * if LE Extended Advertising feature is supported, 0 otherwise.
-     *
-     * @return the maximum LE advertising data length.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public int getLeMaximumAdvertisingDataLength() {
-        if (!getLeAccess()) {
-            return 0;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getLeMaximumAdvertisingDataLength();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return 0;
-    }
-
-    /**
-     * Return true if Hearing Aid Profile is supported.
-     *
-     * @return true if phone supports Hearing Aid Profile
-     */
-    @RequiresNoPermission
-    private boolean isHearingAidProfileSupported() {
-        try {
-            return mManagerService.isHearingAidProfileSupported();
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception when calling isHearingAidProfileSupported", e);
-            return false;
-        }
-    }
-
-    /**
-     * Get the maximum number of connected audio devices.
-     *
-     * @return the maximum number of connected audio devices
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getMaxConnectedAudioDevices() {
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getMaxConnectedAudioDevices(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return 1;
-    }
-
-    /**
-     * Return true if hardware has entries available for matching beacons
-     *
-     * @return true if there are hw entries available for matching beacons
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isHardwareTrackingFiltersAvailable() {
-        if (!getLeAccess()) {
-            return false;
-        }
-        try {
-            IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
-            if (iGatt == null) {
-                // BLE is not supported
-                return false;
-            }
-            return (iGatt.numHwTrackFiltersAvailable(mAttributionSource) != 0);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Request the record of {@link BluetoothActivityEnergyInfo} object that
-     * has the activity and energy info. This can be used to ascertain what
-     * the controller has been up to, since the last sample.
-     *
-     * A null value for the activity info object may be sent if the bluetooth service is
-     * unreachable or the device does not support reporting such information.
-     *
-     * @param result The callback to which to send the activity info.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public void requestControllerActivityEnergyInfo(ResultReceiver result) {
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                mService.requestActivityInfo(result, mAttributionSource);
-                result = null;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
-        } finally {
-            mServiceLock.readLock().unlock();
-            if (result != null) {
-                // Only send an immediate result if we failed.
-                result.send(0, null);
-            }
-        }
-    }
-
-    /**
-     * Fetches a list of the most recently connected bluetooth devices ordered by how recently they
-     * were connected with most recently first and least recently last
-     *
-     * @return {@link List} of bonded {@link BluetoothDevice} ordered by how recently they were
-     * connected
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getMostRecentlyConnectedDevices() {
-        if (getState() != STATE_ON) {
-            return new ArrayList<>();
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return Attributable.setAttributionSource(
-                        mService.getMostRecentlyConnectedDevices(mAttributionSource),
-                        mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return new ArrayList<>();
-    }
-
-    /**
-     * Return the set of {@link BluetoothDevice} objects that are bonded
-     * (paired) to the local adapter.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return an empty set. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     *
-     * @return unmodifiable set of {@link BluetoothDevice}, or null on error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public Set<BluetoothDevice> getBondedDevices() {
-        if (getState() != STATE_ON) {
-            return toDeviceSet(Arrays.asList());
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return toDeviceSet(Attributable.setAttributionSource(
-                        Arrays.asList(mService.getBondedDevices(mAttributionSource)),
-                        mAttributionSource));
-            }
-            return toDeviceSet(Arrays.asList());
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return null;
-    }
-
-    /**
-     * Gets the currently supported profiles by the adapter.
-     *
-     * <p> This can be used to check whether a profile is supported before attempting
-     * to connect to its respective proxy.
-     *
-     * @return a list of integers indicating the ids of supported profiles as defined in {@link
-     * BluetoothProfile}.
-     * @hide
-     */
-    @RequiresNoPermission
-    public @NonNull List<Integer> getSupportedProfiles() {
-        final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
-
-        try {
-            synchronized (mManagerCallback) {
-                if (mService != null) {
-                    final long supportedProfilesBitMask = mService.getSupportedProfiles();
-
-                    for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
-                        if ((supportedProfilesBitMask & (1 << i)) != 0) {
-                            supportedProfiles.add(i);
-                        }
-                    }
-                } else {
-                    // Bluetooth is disabled. Just fill in known supported Profiles
-                    if (isHearingAidProfileSupported()) {
-                        supportedProfiles.add(BluetoothProfile.HEARING_AID);
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "getSupportedProfiles:", e);
-        }
-        return supportedProfiles;
-    }
-
-    private static final String BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY =
-            "cache_key.bluetooth.get_adapter_connection_state";
-    private final PropertyInvalidatedCache<Void, Integer>
-            mBluetoothGetAdapterConnectionStateCache =
-            new PropertyInvalidatedCache<Void, Integer> (
-                8, BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY) {
-                /**
-                 * This method must not be called when mService is null.
-                 */
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                protected Integer recompute(Void query) {
-                    try {
-                        return mService.getAdapterConnectionState();
-                    } catch (RemoteException e) {
-                        throw e.rethrowAsRuntimeException();
-                    }
-                }
-            };
-
-    /** @hide */
-    @RequiresNoPermission
-    public void disableGetAdapterConnectionStateCache() {
-        mBluetoothGetAdapterConnectionStateCache.disableLocal();
-    }
-
-    /** @hide */
-    public static void invalidateGetAdapterConnectionStateCache() {
-        PropertyInvalidatedCache.invalidateCache(
-            BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY);
-    }
-
-    /**
-     * Get the current connection state of the local Bluetooth adapter.
-     * This can be used to check whether the local Bluetooth adapter is connected
-     * to any profile of any other remote Bluetooth Device.
-     *
-     * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
-     * intent to get the connection state of the adapter.
-     *
-     * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
-     * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public int getConnectionState() {
-        if (getState() != STATE_ON) {
-            return BluetoothAdapter.STATE_DISCONNECTED;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mBluetoothGetAdapterConnectionStateCache.query(null);
-            }
-        } catch (RuntimeException e) {
-            if (e.getCause() instanceof RemoteException) {
-                Log.e(TAG, "getConnectionState:", e.getCause());
-            } else {
-                throw e;
-            }
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return BluetoothAdapter.STATE_DISCONNECTED;
-    }
-
-    private static final String BLUETOOTH_PROFILE_CACHE_PROPERTY =
-            "cache_key.bluetooth.get_profile_connection_state";
-    private final PropertyInvalidatedCache<Integer, Integer>
-            mGetProfileConnectionStateCache =
-            new PropertyInvalidatedCache<Integer, Integer>(
-                8, BLUETOOTH_PROFILE_CACHE_PROPERTY) {
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                protected Integer recompute(Integer query) {
-                    try {
-                        mServiceLock.readLock().lock();
-                        if (mService != null) {
-                            return mService.getProfileConnectionState(query);
-                        }
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "getProfileConnectionState:", e);
-                    } finally {
-                        mServiceLock.readLock().unlock();
-                    }
-                    return BluetoothProfile.STATE_DISCONNECTED;
-                }
-                @Override
-                public String queryToString(Integer query) {
-                    return String.format("getProfileConnectionState(profile=\"%d\")",
-                                         query);
-                }
-            };
-
-    /** @hide */
-    @RequiresNoPermission
-    public void disableGetProfileConnectionStateCache() {
-        mGetProfileConnectionStateCache.disableLocal();
-    }
-
-    /** @hide */
-    public static void invalidateGetProfileConnectionStateCache() {
-        PropertyInvalidatedCache.invalidateCache(BLUETOOTH_PROFILE_CACHE_PROPERTY);
-    }
-
-    /**
-     * Get the current connection state of a profile.
-     * This function can be used to check whether the local Bluetooth adapter
-     * is connected to any remote device for a specific profile.
-     * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
-     *
-     * <p> Return value can be one of
-     * {@link BluetoothProfile#STATE_DISCONNECTED},
-     * {@link BluetoothProfile#STATE_CONNECTING},
-     * {@link BluetoothProfile#STATE_CONNECTED},
-     * {@link BluetoothProfile#STATE_DISCONNECTING}
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public int getProfileConnectionState(int profile) {
-        if (getState() != STATE_ON) {
-            return BluetoothProfile.STATE_DISCONNECTED;
-        }
-        return mGetProfileConnectionStateCache.query(new Integer(profile));
-    }
-
-    /**
-     * Create a listening, secure RFCOMM Bluetooth socket.
-     * <p>A remote device connecting to this socket will be authenticated and
-     * communication on this socket will be encrypted.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
-     * connections from a listening {@link BluetoothServerSocket}.
-     * <p>Valid RFCOMM channels are in range 1 to 30.
-     *
-     * @param channel RFCOMM channel to listen on
-     * @return a listening RFCOMM BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or channel in use.
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
-        return listenUsingRfcommOn(channel, false, false);
-    }
-
-    /**
-     * Create a listening, secure RFCOMM Bluetooth socket.
-     * <p>A remote device connecting to this socket will be authenticated and
-     * communication on this socket will be encrypted.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
-     * connections from a listening {@link BluetoothServerSocket}.
-     * <p>Valid RFCOMM channels are in range 1 to 30.
-     * <p>To auto assign a channel without creating a SDP record use
-     * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
-     *
-     * @param channel RFCOMM channel to listen on
-     * @param mitm enforce person-in-the-middle protection for authentication.
-     * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
-     * connections.
-     * @return a listening RFCOMM BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or channel in use.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
-            boolean min16DigitPin) throws IOException {
-        BluetoothServerSocket socket =
-                new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
-                        min16DigitPin);
-        int errno = socket.mSocket.bindListen();
-        if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            socket.setChannel(socket.mSocket.getPort());
-        }
-        if (errno != 0) {
-            //TODO(BT): Throw the same exception error code
-            // that the previous code was using.
-            //socket.mSocket.throwErrnoNative(errno);
-            throw new IOException("Error: " + errno);
-        }
-        return socket;
-    }
-
-    /**
-     * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
-     * <p>A remote device connecting to this socket will be authenticated and
-     * communication on this socket will be encrypted.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
-     * connections from a listening {@link BluetoothServerSocket}.
-     * <p>The system will assign an unused RFCOMM channel to listen on.
-     * <p>The system will also register a Service Discovery
-     * Protocol (SDP) record with the local SDP server containing the specified
-     * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
-     * can use the same UUID to query our SDP server and discover which channel
-     * to connect to. This SDP record will be removed when this socket is
-     * closed, or if this application closes unexpectedly.
-     * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
-     * connect to this socket from another device using the same {@link UUID}.
-     *
-     * @param name service name for SDP record
-     * @param uuid uuid for SDP record
-     * @return a listening RFCOMM BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or channel in use.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
-            throws IOException {
-        return createNewRfcommSocketAndRecord(name, uuid, true, true);
-    }
-
-    /**
-     * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
-     * <p>The link key is not required to be authenticated, i.e the communication may be
-     * vulnerable to Person In the Middle attacks. For Bluetooth 2.1 devices,
-     * the link will be encrypted, as encryption is mandatory.
-     * For legacy devices (pre Bluetooth 2.1 devices) the link will not
-     * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
-     * encrypted and authenticated communication channel is desired.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
-     * connections from a listening {@link BluetoothServerSocket}.
-     * <p>The system will assign an unused RFCOMM channel to listen on.
-     * <p>The system will also register a Service Discovery
-     * Protocol (SDP) record with the local SDP server containing the specified
-     * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
-     * can use the same UUID to query our SDP server and discover which channel
-     * to connect to. This SDP record will be removed when this socket is
-     * closed, or if this application closes unexpectedly.
-     * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
-     * connect to this socket from another device using the same {@link UUID}.
-     *
-     * @param name service name for SDP record
-     * @param uuid uuid for SDP record
-     * @return a listening RFCOMM BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or channel in use.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
-            throws IOException {
-        return createNewRfcommSocketAndRecord(name, uuid, false, false);
-    }
-
-    /**
-     * Create a listening, encrypted,
-     * RFCOMM Bluetooth socket with Service Record.
-     * <p>The link will be encrypted, but the link key is not required to be authenticated
-     * i.e the communication is vulnerable to Person In the Middle attacks. Use
-     * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
-     * <p> Use this socket if authentication of link key is not possible.
-     * For example, for Bluetooth 2.1 devices, if any of the devices does not have
-     * an input and output capability or just has the ability to display a numeric key,
-     * a secure socket connection is not possible and this socket can be used.
-     * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
-     * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandatory.
-     * For more details, refer to the Security Model section 5.2 (vol 3) of
-     * Bluetooth Core Specification version 2.1 + EDR.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
-     * connections from a listening {@link BluetoothServerSocket}.
-     * <p>The system will assign an unused RFCOMM channel to listen on.
-     * <p>The system will also register a Service Discovery
-     * Protocol (SDP) record with the local SDP server containing the specified
-     * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
-     * can use the same UUID to query our SDP server and discover which channel
-     * to connect to. This SDP record will be removed when this socket is
-     * closed, or if this application closes unexpectedly.
-     * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
-     * connect to this socket from another device using the same {@link UUID}.
-     *
-     * @param name service name for SDP record
-     * @param uuid uuid for SDP record
-     * @return a listening RFCOMM BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or channel in use.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
-            throws IOException {
-        return createNewRfcommSocketAndRecord(name, uuid, false, true);
-    }
-
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
-            boolean auth, boolean encrypt) throws IOException {
-        BluetoothServerSocket socket;
-        socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
-                new ParcelUuid(uuid));
-        socket.setServiceName(name);
-        int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            //TODO(BT): Throw the same exception error code
-            // that the previous code was using.
-            //socket.mSocket.throwErrnoNative(errno);
-            throw new IOException("Error: " + errno);
-        }
-        return socket;
-    }
-
-    /**
-     * Construct an unencrypted, unauthenticated, RFCOMM server socket.
-     * Call #accept to retrieve connections to this socket.
-     *
-     * @return An RFCOMM BluetoothServerSocket
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * permissions.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
-        BluetoothServerSocket socket =
-                new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
-        int errno = socket.mSocket.bindListen();
-        if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            socket.setChannel(socket.mSocket.getPort());
-        }
-        if (errno != 0) {
-            //TODO(BT): Throw the same exception error code
-            // that the previous code was using.
-            //socket.mSocket.throwErrnoNative(errno);
-            throw new IOException("Error: " + errno);
-        }
-        return socket;
-    }
-
-    /**
-     * Construct an encrypted, authenticated, L2CAP server socket.
-     * Call #accept to retrieve connections to this socket.
-     * <p>To auto assign a port without creating a SDP record use
-     * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
-     *
-     * @param port the PSM to listen on
-     * @param mitm enforce person-in-the-middle protection for authentication.
-     * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
-     * connections.
-     * @return An L2CAP BluetoothServerSocket
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * permissions.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
-            throws IOException {
-        BluetoothServerSocket socket =
-                new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
-                        min16DigitPin);
-        int errno = socket.mSocket.bindListen();
-        if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            int assignedChannel = socket.mSocket.getPort();
-            if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
-            socket.setChannel(assignedChannel);
-        }
-        if (errno != 0) {
-            //TODO(BT): Throw the same exception error code
-            // that the previous code was using.
-            //socket.mSocket.throwErrnoNative(errno);
-            throw new IOException("Error: " + errno);
-        }
-        return socket;
-    }
-
-    /**
-     * Construct an encrypted, authenticated, L2CAP server socket.
-     * Call #accept to retrieve connections to this socket.
-     * <p>To auto assign a port without creating a SDP record use
-     * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
-     *
-     * @param port the PSM to listen on
-     * @return An L2CAP BluetoothServerSocket
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * permissions.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
-        return listenUsingL2capOn(port, false, false);
-    }
-
-    /**
-     * Construct an insecure L2CAP server socket.
-     * Call #accept to retrieve connections to this socket.
-     * <p>To auto assign a port without creating a SDP record use
-     * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
-     *
-     * @param port the PSM to listen on
-     * @return An L2CAP BluetoothServerSocket
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * permissions.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
-        Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
-        BluetoothServerSocket socket =
-                new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
-                                          false);
-        int errno = socket.mSocket.bindListen();
-        if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            int assignedChannel = socket.mSocket.getPort();
-            if (DBG) {
-                Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
-                        + assignedChannel);
-            }
-            socket.setChannel(assignedChannel);
-        }
-        if (errno != 0) {
-            //TODO(BT): Throw the same exception error code
-            // that the previous code was using.
-            //socket.mSocket.throwErrnoNative(errno);
-            throw new IOException("Error: " + errno);
-        }
-        return socket;
-
-    }
-
-    /**
-     * Read the local Out of Band Pairing Data
-     *
-     * @return Pair<byte[], byte[]> of Hash and Randomizer
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public Pair<byte[], byte[]> readOutOfBandData() {
-        return null;
-    }
-
-    /**
-     * Get the profile proxy object associated with the profile.
-     *
-     * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
-     * {@link BluetoothProfile#GATT}, {@link BluetoothProfile#HEARING_AID}, or {@link
-     * BluetoothProfile#GATT_SERVER}. Clients must implement {@link
-     * BluetoothProfile.ServiceListener} to get notified of the connection status and to get the
-     * proxy object.
-     *
-     * @param context Context of the application
-     * @param listener The service Listener for connection callbacks.
-     * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
-     * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, {@link
-     * BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
-     * @return true on success, false on error
-     */
-    @SuppressLint({
-        "AndroidFrameworkRequiresPermission",
-        "AndroidFrameworkBluetoothPermission"
-    })
-    public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
-            int profile) {
-        if (context == null || listener == null) {
-            return false;
-        }
-
-        if (profile == BluetoothProfile.HEADSET) {
-            BluetoothHeadset headset = new BluetoothHeadset(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.A2DP) {
-            BluetoothA2dp a2dp = new BluetoothA2dp(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.A2DP_SINK) {
-            BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
-            BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.HID_HOST) {
-            BluetoothHidHost iDev = new BluetoothHidHost(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.PAN) {
-            BluetoothPan pan = new BluetoothPan(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.PBAP) {
-            BluetoothPbap pbap = new BluetoothPbap(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.HEALTH) {
-            Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
-            return false;
-        } else if (profile == BluetoothProfile.MAP) {
-            BluetoothMap map = new BluetoothMap(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
-            BluetoothHeadsetClient headsetClient =
-                    new BluetoothHeadsetClient(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.SAP) {
-            BluetoothSap sap = new BluetoothSap(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.PBAP_CLIENT) {
-            BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.MAP_CLIENT) {
-            BluetoothMapClient mapClient = new BluetoothMapClient(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.HID_DEVICE) {
-            BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener, this);
-            return true;
-        } else if (profile == BluetoothProfile.HEARING_AID) {
-            if (isHearingAidProfileSupported()) {
-                BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener, this);
-                return true;
-            }
-            return false;
-        } else if (profile == BluetoothProfile.LE_AUDIO) {
-            BluetoothLeAudio leAudio = new BluetoothLeAudio(context, listener, this);
-            return true;
-        } 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, this);
-            return true;
-        } else if (profile == BluetoothProfile.LE_CALL_CONTROL) {
-            BluetoothLeCallControl tbs = new BluetoothLeCallControl(context, listener);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Close the connection of the profile proxy to the Service.
-     *
-     * <p> Clients should call this when they are no longer using
-     * the proxy obtained from {@link #getProfileProxy}.
-     * Profile can be one of  {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
-     *
-     * @param profile
-     * @param proxy Profile proxy object
-     */
-    @SuppressLint({
-            "AndroidFrameworkRequiresPermission",
-            "AndroidFrameworkBluetoothPermission"
-    })
-    public void closeProfileProxy(int profile, BluetoothProfile proxy) {
-        if (proxy == null) {
-            return;
-        }
-
-        switch (profile) {
-            case BluetoothProfile.HEADSET:
-                BluetoothHeadset headset = (BluetoothHeadset) proxy;
-                headset.close();
-                break;
-            case BluetoothProfile.A2DP:
-                BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
-                a2dp.close();
-                break;
-            case BluetoothProfile.A2DP_SINK:
-                BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
-                a2dpSink.close();
-                break;
-            case BluetoothProfile.AVRCP_CONTROLLER:
-                BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
-                avrcp.close();
-                break;
-            case BluetoothProfile.HID_HOST:
-                BluetoothHidHost iDev = (BluetoothHidHost) proxy;
-                iDev.close();
-                break;
-            case BluetoothProfile.PAN:
-                BluetoothPan pan = (BluetoothPan) proxy;
-                pan.close();
-                break;
-            case BluetoothProfile.PBAP:
-                BluetoothPbap pbap = (BluetoothPbap) proxy;
-                pbap.close();
-                break;
-            case BluetoothProfile.GATT:
-                BluetoothGatt gatt = (BluetoothGatt) proxy;
-                gatt.close();
-                break;
-            case BluetoothProfile.GATT_SERVER:
-                BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
-                gattServer.close();
-                break;
-            case BluetoothProfile.MAP:
-                BluetoothMap map = (BluetoothMap) proxy;
-                map.close();
-                break;
-            case BluetoothProfile.HEADSET_CLIENT:
-                BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
-                headsetClient.close();
-                break;
-            case BluetoothProfile.SAP:
-                BluetoothSap sap = (BluetoothSap) proxy;
-                sap.close();
-                break;
-            case BluetoothProfile.PBAP_CLIENT:
-                BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
-                pbapClient.close();
-                break;
-            case BluetoothProfile.MAP_CLIENT:
-                BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
-                mapClient.close();
-                break;
-            case BluetoothProfile.HID_DEVICE:
-                BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
-                hidDevice.close();
-                break;
-            case BluetoothProfile.HEARING_AID:
-                BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
-                hearingAid.close();
-                break;
-            case BluetoothProfile.LE_AUDIO:
-                BluetoothLeAudio leAudio = (BluetoothLeAudio) proxy;
-                leAudio.close();
-                break;
-            case BluetoothProfile.VOLUME_CONTROL:
-                BluetoothVolumeControl vcs = (BluetoothVolumeControl) proxy;
-                vcs.close();
-                break;
-            case BluetoothProfile.CSIP_SET_COORDINATOR:
-                BluetoothCsipSetCoordinator csipSetCoordinator =
-                        (BluetoothCsipSetCoordinator) proxy;
-                csipSetCoordinator.close();
-                break;
-            case BluetoothProfile.LE_CALL_CONTROL:
-                BluetoothLeCallControl tbs = (BluetoothLeCallControl) proxy;
-                tbs.close();
-                break;
-        }
-    }
-
-    private static final IBluetoothManagerCallback sManagerCallback =
-            new IBluetoothManagerCallback.Stub() {
-                public void onBluetoothServiceUp(IBluetooth bluetoothService) {
-                    if (DBG) {
-                        Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
-                    }
-
-                    synchronized (sServiceLock) {
-                        sService = bluetoothService;
-                        for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
-                            try {
-                                if (cb != null) {
-                                    cb.onBluetoothServiceUp(bluetoothService);
-                                } else {
-                                    Log.d(TAG, "onBluetoothServiceUp: cb is null!");
-                                }
-                            } catch (Exception e) {
-                                Log.e(TAG, "", e);
-                            }
-                        }
-                    }
-                }
-
-                public void onBluetoothServiceDown() {
-                    if (DBG) {
-                        Log.d(TAG, "onBluetoothServiceDown");
-                    }
-
-                    synchronized (sServiceLock) {
-                        sService = null;
-                        for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
-                            try {
-                                if (cb != null) {
-                                    cb.onBluetoothServiceDown();
-                                } else {
-                                    Log.d(TAG, "onBluetoothServiceDown: cb is null!");
-                                }
-                            } catch (Exception e) {
-                                Log.e(TAG, "", e);
-                            }
-                        }
-                    }
-                }
-
-                public void onBrEdrDown() {
-                    if (VDBG) {
-                        Log.i(TAG, "onBrEdrDown");
-                    }
-
-                    synchronized (sServiceLock) {
-                        for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) {
-                            try {
-                                if (cb != null) {
-                                    cb.onBrEdrDown();
-                                } else {
-                                    Log.d(TAG, "onBrEdrDown: cb is null!");
-                                }
-                            } catch (Exception e) {
-                                Log.e(TAG, "", e);
-                            }
-                        }
-                    }
-                }
-            };
-
-    private final IBluetoothManagerCallback mManagerCallback =
-            new IBluetoothManagerCallback.Stub() {
-                public void onBluetoothServiceUp(IBluetooth bluetoothService) {
-                    synchronized (mServiceLock.writeLock()) {
-                        mService = bluetoothService;
-                    }
-                    synchronized (mMetadataListeners) {
-                        mMetadataListeners.forEach((device, pair) -> {
-                            try {
-                                mService.registerMetadataListener(mBluetoothMetadataListener,
-                                        device, mAttributionSource);
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "Failed to register metadata listener", e);
-                            }
-                        });
-                    }
-                    synchronized (mBluetoothConnectionCallbackExecutorMap) {
-                        if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
-                            try {
-                                mService.registerBluetoothConnectionCallback(mConnectionCallback,
-                                        mAttributionSource);
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "onBluetoothServiceUp: Failed to register bluetooth"
-                                        + "connection callback", e);
-                            }
-                        }
-                    }
-                }
-
-                public void onBluetoothServiceDown() {
-                    synchronized (mServiceLock.writeLock()) {
-                        mService = null;
-                        if (mLeScanClients != null) {
-                            mLeScanClients.clear();
-                        }
-                        if (mBluetoothLeAdvertiser != null) {
-                            mBluetoothLeAdvertiser.cleanup();
-                        }
-                        if (mBluetoothLeScanner != null) {
-                            mBluetoothLeScanner.cleanup();
-                        }
-                    }
-                }
-
-                public void onBrEdrDown() {
-                }
-            };
-
-    /**
-     * Enable the Bluetooth Adapter, but don't auto-connect devices
-     * and don't persist state. Only for use by system applications.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean enableNoAutoConnect() {
-        if (isEnabled()) {
-            if (DBG) {
-                Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
-            }
-            return true;
-        }
-        try {
-            return mManagerService.enableNoAutoConnect(mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            BluetoothStatusCodes.ERROR_UNKNOWN,
-            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
-            BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST,
-    })
-    public @interface OobError {}
-
-    /**
-     * Provides callback methods for receiving {@link OobData} from the host stack, as well as an
-     * error interface in order to allow the caller to determine next steps based on the {@code
-     * ErrorCode}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface OobDataCallback {
-        /**
-         * Handles the {@link OobData} received from the host stack.
-         *
-         * @param transport - whether the {@link OobData} is generated for LE or Classic.
-         * @param oobData - data generated in the host stack(LE) or controller (Classic)
-         */
-        void onOobData(@Transport int transport, @NonNull OobData oobData);
-
-        /**
-         * Provides feedback when things don't go as expected.
-         *
-         * @param errorCode - the code describing the type of error that occurred.
-         */
-        void onError(@OobError int errorCode);
-    }
-
-    /**
-     * Wraps an AIDL interface around an {@link OobDataCallback} interface.
-     *
-     * @see {@link IBluetoothOobDataCallback} for interface definition.
-     *
-     * @hide
-     */
-    public class WrappedOobDataCallback extends IBluetoothOobDataCallback.Stub {
-        private final OobDataCallback mCallback;
-        private final Executor mExecutor;
-
-        /**
-         * @param callback - object to receive {@link OobData} must be a non null argument
-         *
-         * @throws NullPointerException if the callback is null.
-         */
-        WrappedOobDataCallback(@NonNull OobDataCallback callback,
-                @NonNull @CallbackExecutor Executor executor) {
-            requireNonNull(callback);
-            requireNonNull(executor);
-            mCallback = callback;
-            mExecutor = executor;
-        }
-        /**
-         * Wrapper function to relay to the {@link OobDataCallback#onOobData}
-         *
-         * @param transport - whether the {@link OobData} is generated for LE or Classic.
-         * @param oobData - data generated in the host stack(LE) or controller (Classic)
-         *
-         * @hide
-         */
-        public void onOobData(@Transport int transport, @NonNull OobData oobData) {
-            mExecutor.execute(new Runnable() {
-                public void run() {
-                    mCallback.onOobData(transport, oobData);
-                }
-            });
-        }
-        /**
-         * Wrapper function to relay to the {@link OobDataCallback#onError}
-         *
-         * @param errorCode - the code descibing the type of error that occurred.
-         *
-         * @hide
-         */
-        public void onError(@OobError int errorCode) {
-            mExecutor.execute(new Runnable() {
-                public void run() {
-                    mCallback.onError(errorCode);
-                }
-            });
-        }
-    }
-
-    /**
-     * Fetches a secret data value that can be used for a secure and simple pairing experience.
-     *
-     * <p>This is the Local Out of Band data the comes from the
-     *
-     * <p>This secret is the local Out of Band data.  This data is used to securely and quickly
-     * pair two devices with minimal user interaction.
-     *
-     * <p>For example, this secret can be transferred to a remote device out of band (meaning any
-     * other way besides using bluetooth).  Once the remote device finds this device using the
-     * information given in the data, such as the PUBLIC ADDRESS, the remote device could then
-     * connect to this device using this secret when the pairing sequenece asks for the secret.
-     * This device will respond by automatically accepting the pairing due to the secret being so
-     * trustworthy.
-     *
-     * @param transport - provide type of transport (e.g. LE or Classic).
-     * @param callback - target object to receive the {@link OobData} value.
-     *
-     * @throws NullPointerException if callback is null.
-     * @throws IllegalArgumentException if the transport is not valid.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public void generateLocalOobData(@Transport int transport,
-            @NonNull @CallbackExecutor Executor executor, @NonNull OobDataCallback callback) {
-        if (transport != BluetoothDevice.TRANSPORT_BREDR && transport
-                != BluetoothDevice.TRANSPORT_LE) {
-            throw new IllegalArgumentException("Invalid transport '" + transport + "'!");
-        }
-        requireNonNull(callback);
-        if (!isEnabled()) {
-            Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
-            callback.onError(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED);
-        } else {
-            try {
-                mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback,
-                        executor), mAttributionSource);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-    }
-
-    /**
-     * Enable control of the Bluetooth Adapter for a single application.
-     *
-     * <p>Some applications need to use Bluetooth for short periods of time to
-     * transfer data but don't want all the associated implications like
-     * automatic connection to headsets etc.
-     *
-     * <p> Multiple applications can call this. This is reference counted and
-     * Bluetooth disabled only when no one else is using it. There will be no UI
-     * shown to the user while bluetooth is being enabled. Any user action will
-     * override this call. For example, if user wants Bluetooth on and the last
-     * user of this API wanted to disable Bluetooth, Bluetooth will not be
-     * turned off.
-     *
-     * <p> This API is only meant to be used by internal applications. Third
-     * party applications but use {@link #enable} and {@link #disable} APIs.
-     *
-     * <p> If this API returns true, it means the callback will be called.
-     * The callback will be called with the current state of Bluetooth.
-     * If the state is not what was requested, an internal error would be the
-     * reason. If Bluetooth is already on and if this function is called to turn
-     * it on, the api will return true and a callback will be called.
-     *
-     * @param on True for on, false for off.
-     * @param callback The callback to notify changes to the state.
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public boolean changeApplicationBluetoothState(boolean on,
-            BluetoothStateChangeCallback callback) {
-        return false;
-    }
-
-    /**
-     * @hide
-     */
-    public interface BluetoothStateChangeCallback {
-        /**
-         * @hide
-         */
-        void onBluetoothStateChange(boolean on);
-    }
-
-    /**
-     * @hide
-     */
-    public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
-        private BluetoothStateChangeCallback mCallback;
-
-        StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void onBluetoothStateChange(boolean on) {
-            mCallback.onBluetoothStateChange(on);
-        }
-    }
-
-    private Set<BluetoothDevice> toDeviceSet(List<BluetoothDevice> devices) {
-        Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(devices);
-        return Collections.unmodifiableSet(deviceSet);
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            removeServiceStateCallback(mManagerCallback);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /**
-     * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
-     * <p>Alphabetic characters must be uppercase to be valid.
-     *
-     * @param address Bluetooth address as string
-     * @return true if the address is valid, false otherwise
-     */
-    public static boolean checkBluetoothAddress(String address) {
-        if (address == null || address.length() != ADDRESS_LENGTH) {
-            return false;
-        }
-        for (int i = 0; i < ADDRESS_LENGTH; i++) {
-            char c = address.charAt(i);
-            switch (i % 3) {
-                case 0:
-                case 1:
-                    if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
-                        // hex character, OK
-                        break;
-                    }
-                    return false;
-                case 2:
-                    if (c == ':') {
-                        break;  // OK
-                    }
-                    return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Determines whether a String Bluetooth address, such as "F0:43:A8:23:10:00"
-     * is a RANDOM STATIC address.
-     *
-     * 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 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(":")[0], 16) & 0xC0) == 0xC0;
-    }
-
-    /** {@hide} */
-    @UnsupportedAppUsage
-    @RequiresNoPermission
-    public IBluetoothManager getBluetoothManager() {
-        return mManagerService;
-    }
-
-    /** {@hide} */
-    @RequiresNoPermission
-    public AttributionSource getAttributionSource() {
-        return mAttributionSource;
-    }
-
-    @GuardedBy("sServiceLock")
-    private static final WeakHashMap<IBluetoothManagerCallback, Void> sProxyServiceStateCallbacks =
-            new WeakHashMap<>();
-
-    /*package*/ IBluetooth getBluetoothService() {
-        synchronized (sServiceLock) {
-            if (sProxyServiceStateCallbacks.isEmpty()) {
-                throw new IllegalStateException(
-                        "Anonymous service access requires at least one lifecycle in process");
-            }
-            return sService;
-        }
-    }
-
-    @UnsupportedAppUsage
-    /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
-        Objects.requireNonNull(cb);
-        synchronized (sServiceLock) {
-            sProxyServiceStateCallbacks.put(cb, null);
-            registerOrUnregisterAdapterLocked();
-            return sService;
-        }
-    }
-
-    /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
-        Objects.requireNonNull(cb);
-        synchronized (sServiceLock) {
-            sProxyServiceStateCallbacks.remove(cb);
-            registerOrUnregisterAdapterLocked();
-        }
-    }
-
-    /**
-     * Handle registering (or unregistering) a single process-wide
-     * {@link IBluetoothManagerCallback} based on the presence of local
-     * {@link #sProxyServiceStateCallbacks} clients.
-     */
-    @GuardedBy("sServiceLock")
-    private void registerOrUnregisterAdapterLocked() {
-        final boolean isRegistered = sServiceRegistered;
-        final boolean wantRegistered = !sProxyServiceStateCallbacks.isEmpty();
-
-        if (isRegistered != wantRegistered) {
-            if (wantRegistered) {
-                try {
-                    sService = mManagerService.registerAdapter(sManagerCallback);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            } else {
-                try {
-                    mManagerService.unregisterAdapter(sManagerCallback);
-                    sService = null;
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-            sServiceRegistered = wantRegistered;
-        }
-    }
-
-    /**
-     * Callback interface used to deliver LE scan results.
-     *
-     * @see #startLeScan(LeScanCallback)
-     * @see #startLeScan(UUID[], LeScanCallback)
-     */
-    public interface LeScanCallback {
-        /**
-         * Callback reporting an LE device found during a device scan initiated
-         * by the {@link BluetoothAdapter#startLeScan} function.
-         *
-         * @param device Identifies the remote device
-         * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
-         * if no RSSI value is available.
-         * @param scanRecord The content of the advertisement record offered by the remote device.
-         */
-        void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
-    }
-
-    /**
-     * Register a callback to receive events whenever the bluetooth stack goes down and back up,
-     * e.g. in the event the bluetooth is turned off/on via settings.
-     *
-     * If the bluetooth stack is currently up, there will not be an initial callback call.
-     * You can use the return value as an indication of this being the case.
-     *
-     * Callbacks will be delivered on a binder thread.
-     *
-     * @return whether bluetooth is already up currently
-     *
-     * @hide
-     */
-    public boolean registerServiceLifecycleCallback(ServiceLifecycleCallback callback) {
-        return getBluetoothService(callback.mRemote) != null;
-    }
-
-    /**
-     * Unregister a callback registered via {@link #registerServiceLifecycleCallback}
-     *
-     * @hide
-     */
-    public void unregisterServiceLifecycleCallback(ServiceLifecycleCallback callback) {
-        removeServiceStateCallback(callback.mRemote);
-    }
-
-    /**
-     * A callback for {@link #registerServiceLifecycleCallback}
-     *
-     * @hide
-     */
-    public abstract static class ServiceLifecycleCallback {
-
-        /** Called when the bluetooth stack is up */
-        public abstract void onBluetoothServiceUp();
-
-        /** Called when the bluetooth stack is down */
-        public abstract void onBluetoothServiceDown();
-
-        IBluetoothManagerCallback mRemote = new IBluetoothManagerCallback.Stub() {
-            @Override
-            public void onBluetoothServiceUp(IBluetooth bluetoothService) {
-                ServiceLifecycleCallback.this.onBluetoothServiceUp();
-            }
-
-            @Override
-            public void onBluetoothServiceDown() {
-                ServiceLifecycleCallback.this.onBluetoothServiceDown();
-            }
-
-            @Override
-            public void onBrEdrDown() {}
-        };
-    }
-
-    /**
-     * Starts a scan for Bluetooth LE devices.
-     *
-     * <p>Results of the scan are reported using the
-     * {@link LeScanCallback#onLeScan} callback.
-     *
-     * @param callback the callback LE scan results are delivered
-     * @return true, if the scan was started successfully
-     * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
-     * instead.
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean startLeScan(LeScanCallback callback) {
-        return startLeScan(null, callback);
-    }
-
-    /**
-     * Starts a scan for Bluetooth LE devices, looking for devices that
-     * advertise given services.
-     *
-     * <p>Devices which advertise all specified services are reported using the
-     * {@link LeScanCallback#onLeScan} callback.
-     *
-     * @param serviceUuids Array of services to look for
-     * @param callback the callback LE scan results are delivered
-     * @return true, if the scan was started successfully
-     * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
-     * instead.
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
-        if (DBG) {
-            Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
-        }
-        if (callback == null) {
-            if (DBG) {
-                Log.e(TAG, "startLeScan: null callback");
-            }
-            return false;
-        }
-        BluetoothLeScanner scanner = getBluetoothLeScanner();
-        if (scanner == null) {
-            if (DBG) {
-                Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
-            }
-            return false;
-        }
-
-        synchronized (mLeScanClients) {
-            if (mLeScanClients.containsKey(callback)) {
-                if (DBG) {
-                    Log.e(TAG, "LE Scan has already started");
-                }
-                return false;
-            }
-
-            try {
-                IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
-                if (iGatt == null) {
-                    // BLE is not supported
-                    return false;
-                }
-
-                @SuppressLint("AndroidFrameworkBluetoothPermission")
-                ScanCallback scanCallback = new ScanCallback() {
-                    @Override
-                    public void onScanResult(int callbackType, ScanResult result) {
-                        if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
-                            // Should not happen.
-                            Log.e(TAG, "LE Scan has already started");
-                            return;
-                        }
-                        ScanRecord scanRecord = result.getScanRecord();
-                        if (scanRecord == null) {
-                            return;
-                        }
-                        if (serviceUuids != null) {
-                            List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
-                            for (UUID uuid : serviceUuids) {
-                                uuids.add(new ParcelUuid(uuid));
-                            }
-                            List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
-                            if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
-                                if (DBG) {
-                                    Log.d(TAG, "uuids does not match");
-                                }
-                                return;
-                            }
-                        }
-                        callback.onLeScan(result.getDevice(), result.getRssi(),
-                                scanRecord.getBytes());
-                    }
-                };
-                ScanSettings settings = new ScanSettings.Builder().setCallbackType(
-                        ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
-                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
-                        .build();
-
-                List<ScanFilter> filters = new ArrayList<ScanFilter>();
-                if (serviceUuids != null && serviceUuids.length > 0) {
-                    // Note scan filter does not support matching an UUID array so we put one
-                    // UUID to hardware and match the whole array in callback.
-                    ScanFilter filter =
-                            new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
-                                    .build();
-                    filters.add(filter);
-                }
-                scanner.startScan(filters, settings, scanCallback);
-
-                mLeScanClients.put(callback, scanCallback);
-                return true;
-
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Stops an ongoing Bluetooth LE device scan.
-     *
-     * @param callback used to identify which scan to stop must be the same handle used to start the
-     * scan
-     * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void stopLeScan(LeScanCallback callback) {
-        if (DBG) {
-            Log.d(TAG, "stopLeScan()");
-        }
-        BluetoothLeScanner scanner = getBluetoothLeScanner();
-        if (scanner == null) {
-            return;
-        }
-        synchronized (mLeScanClients) {
-            ScanCallback scanCallback = mLeScanClients.remove(callback);
-            if (scanCallback == null) {
-                if (DBG) {
-                    Log.d(TAG, "scan not started yet");
-                }
-                return;
-            }
-            scanner.stopScan(scanCallback);
-        }
-    }
-
-    /**
-     * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
-     * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
-     * for incoming connections. The supported Bluetooth transport is LE only.
-     * <p>A remote device connecting to this socket will be authenticated and communication on this
-     * socket will be encrypted.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
-     * {@link BluetoothServerSocket}.
-     * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {@link
-     * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
-     * closed, Bluetooth is turned off, or the application exits unexpectedly.
-     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
-     * defined and performed by the application.
-     * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
-     * socket from another Android device that is given the PSM value.
-     *
-     * @return an L2CAP CoC BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or unable to start this CoC
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull BluetoothServerSocket listenUsingL2capChannel()
-            throws IOException {
-        BluetoothServerSocket socket =
-                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
-                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
-        int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            throw new IOException("Error: " + errno);
-        }
-
-        int assignedPsm = socket.mSocket.getPort();
-        if (assignedPsm == 0) {
-            throw new IOException("Error: Unable to assign PSM value");
-        }
-        if (DBG) {
-            Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
-                    + assignedPsm);
-        }
-        socket.setChannel(assignedPsm);
-
-        return socket;
-    }
-
-    /**
-     * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
-     * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
-     * supported Bluetooth transport is LE only.
-     * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
-     * to person-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
-     * authenticated communication channel is desired.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
-     * {@link BluetoothServerSocket}.
-     * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
-     * can be read from the {@link BluetoothServerSocket#getPsm()} and this value will be released
-     * when this server socket is closed, Bluetooth is turned off, or the application exits
-     * unexpectedly.
-     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
-     * defined and performed by the application.
-     * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
-     * socket from another Android device that is given the PSM value.
-     *
-     * @return an L2CAP CoC BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions, or unable to start this CoC
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
-            throws IOException {
-        BluetoothServerSocket socket =
-                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
-                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
-        int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            throw new IOException("Error: " + errno);
-        }
-
-        int assignedPsm = socket.mSocket.getPort();
-        if (assignedPsm == 0) {
-            throw new IOException("Error: Unable to assign PSM value");
-        }
-        if (DBG) {
-            Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
-                    + assignedPsm);
-        }
-        socket.setChannel(assignedPsm);
-
-        return socket;
-    }
-
-    /**
-     * Register a {@link #OnMetadataChangedListener} to receive update about metadata
-     * changes for this {@link BluetoothDevice}.
-     * Registration must be done when Bluetooth is ON and will last until
-     * {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when Bluetooth
-     * restarted in the middle.
-     * All input parameters should not be null or {@link NullPointerException} will be triggered.
-     * The same {@link BluetoothDevice} and {@link #OnMetadataChangedListener} pair can only be
-     * registered once, double registration would cause {@link IllegalArgumentException}.
-     *
-     * @param device {@link BluetoothDevice} that will be registered
-     * @param executor the executor for listener callback
-     * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks
-     * @return true on success, false on error
-     * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor}
-     * is null.
-     * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and
-     * {@link BluetoothDevice} are registered twice.
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device,
-            @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) {
-        if (DBG) Log.d(TAG, "addOnMetadataChangedListener()");
-
-        final IBluetooth service = mService;
-        if (service == null) {
-            Log.e(TAG, "Bluetooth is not enabled. Cannot register metadata listener");
-            return false;
-        }
-        if (listener == null) {
-            throw new NullPointerException("listener is null");
-        }
-        if (device == null) {
-            throw new NullPointerException("device is null");
-        }
-        if (executor == null) {
-            throw new NullPointerException("executor is null");
-        }
-
-        synchronized (mMetadataListeners) {
-            List<Pair<OnMetadataChangedListener, Executor>> listenerList =
-                    mMetadataListeners.get(device);
-            if (listenerList == null) {
-                // Create new listener/executor list for registeration
-                listenerList = new ArrayList<>();
-                mMetadataListeners.put(device, listenerList);
-            } else {
-                // Check whether this device was already registed by the lisenter
-                if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
-                    throw new IllegalArgumentException("listener was already regestered"
-                            + " for the device");
-                }
-            }
-
-            Pair<OnMetadataChangedListener, Executor> listenerPair = new Pair(listener, executor);
-            listenerList.add(listenerPair);
-
-            boolean ret = false;
-            try {
-                ret = service.registerMetadataListener(mBluetoothMetadataListener, device,
-                        mAttributionSource);
-            } catch (RemoteException e) {
-                Log.e(TAG, "registerMetadataListener fail", e);
-            } finally {
-                if (!ret) {
-                    // Remove listener registered earlier when fail.
-                    listenerList.remove(listenerPair);
-                    if (listenerList.isEmpty()) {
-                        // Remove the device if its listener list is empty
-                        mMetadataListeners.remove(device);
-                    }
-                }
-            }
-            return ret;
-        }
-    }
-
-    /**
-     * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}.
-     * Unregistration can be done when Bluetooth is either ON or OFF.
-     * {@link #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)}
-     * must be called before unregisteration.
-     *
-     * @param device {@link BluetoothDevice} that will be unregistered. It
-     * should not be null or {@link NullPointerException} will be triggered.
-     * @param listener {@link OnMetadataChangedListener} that will be unregistered. It
-     * should not be null or {@link NullPointerException} will be triggered.
-     * @return true on success, false on error
-     * @throws NullPointerException If {@code listener} or {@code device} is null.
-     * @throws IllegalArgumentException If {@code device} has not been registered before.
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device,
-            @NonNull OnMetadataChangedListener listener) {
-        if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()");
-        if (device == null) {
-            throw new NullPointerException("device is null");
-        }
-        if (listener == null) {
-            throw new NullPointerException("listener is null");
-        }
-
-        synchronized (mMetadataListeners) {
-            if (!mMetadataListeners.containsKey(device)) {
-                throw new IllegalArgumentException("device was not registered");
-            }
-            // Remove issued listener from the registered device
-            mMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));
-
-            if (mMetadataListeners.get(device).isEmpty()) {
-                // Unregister to Bluetooth service if all listeners are removed from
-                // the registered device
-                mMetadataListeners.remove(device);
-                final IBluetooth service = mService;
-                if (service == null) {
-                    // Bluetooth is OFF, do nothing to Bluetooth service.
-                    return true;
-                }
-                try {
-                    return service.unregisterMetadataListener(device, mAttributionSource);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "unregisterMetadataListener fail", e);
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * This interface is used to implement {@link BluetoothAdapter} metadata listener.
-     * @hide
-     */
-    @SystemApi
-    public interface OnMetadataChangedListener {
-        /**
-         * Callback triggered if the metadata of {@link BluetoothDevice} registered in
-         * {@link #addOnMetadataChangedListener}.
-         *
-         * @param device changed {@link BluetoothDevice}.
-         * @param key changed metadata key, one of BluetoothDevice.METADATA_*.
-         * @param value the new value of metadata as byte array.
-         */
-        void onMetadataChanged(@NonNull BluetoothDevice device, int key,
-                @Nullable byte[] value);
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final IBluetoothConnectionCallback mConnectionCallback =
-            new IBluetoothConnectionCallback.Stub() {
-        @Override
-        public void onDeviceConnected(BluetoothDevice device) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
-                    mBluetoothConnectionCallbackExecutorMap.entrySet()) {
-                BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
-                Executor executor = callbackExecutorEntry.getValue();
-                executor.execute(() -> callback.onDeviceConnected(device));
-            }
-        }
-
-        @Override
-        public void onDeviceDisconnected(BluetoothDevice device, int hciReason) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
-                    mBluetoothConnectionCallbackExecutorMap.entrySet()) {
-                BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
-                Executor executor = callbackExecutorEntry.getValue();
-                executor.execute(() -> callback.onDeviceDisconnected(device, hciReason));
-            }
-        }
-    };
-
-    /**
-     * Registers the BluetoothConnectionCallback to receive callback events when a bluetooth device
-     * (classic or low energy) is connected or disconnected.
-     *
-     * @param executor is the callback executor
-     * @param callback is the connection callback you wish to register
-     * @return true if the callback was registered successfully, false otherwise
-     * @throws IllegalArgumentException if the callback is already registered
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull BluetoothConnectionCallback callback) {
-        if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()");
-        if (callback == null) {
-            return false;
-        }
-
-        synchronized (mBluetoothConnectionCallbackExecutorMap) {
-            // If the callback map is empty, we register the service-to-app callback
-            if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
-                try {
-                    mServiceLock.readLock().lock();
-                    if (mService != null) {
-                        if (!mService.registerBluetoothConnectionCallback(mConnectionCallback,
-                                mAttributionSource)) {
-                            return false;
-                        }
-                    }
-                } catch (RemoteException e) {
-                    Log.e(TAG, "", e);
-                    mBluetoothConnectionCallbackExecutorMap.remove(callback);
-                } finally {
-                    mServiceLock.readLock().unlock();
-                }
-            }
-
-            // Adds the passed in callback to our map of callbacks to executors
-            if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
-                throw new IllegalArgumentException("This callback has already been registered");
-            }
-            mBluetoothConnectionCallbackExecutorMap.put(callback, executor);
-        }
-
-        return true;
-    }
-
-    /**
-     * Unregisters the BluetoothConnectionCallback that was previously registered by the application
-     *
-     * @param callback is the connection callback you wish to unregister
-     * @return true if the callback was unregistered successfully, false otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean unregisterBluetoothConnectionCallback(
-            @NonNull BluetoothConnectionCallback callback) {
-        if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()");
-        if (callback == null) {
-            return false;
-        }
-
-        synchronized (mBluetoothConnectionCallbackExecutorMap) {
-            if (mBluetoothConnectionCallbackExecutorMap.remove(callback) != null) {
-                return false;
-            }
-        }
-
-        if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
-            return true;
-        }
-
-        // If the callback map is empty, we unregister the service-to-app callback
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.unregisterBluetoothConnectionCallback(mConnectionCallback,
-                        mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-
-        return false;
-    }
-
-    /**
-     * This abstract class is used to implement callbacks for when a bluetooth classic or Bluetooth
-     * Low Energy (BLE) device is either connected or disconnected.
-     *
-     * @hide
-     */
-    public abstract static class BluetoothConnectionCallback {
-        /**
-         * Callback triggered when a bluetooth device (classic or BLE) is connected
-         * @param device is the connected bluetooth device
-         */
-        public void onDeviceConnected(BluetoothDevice device) {}
-
-        /**
-         * Callback triggered when a bluetooth device (classic or BLE) is disconnected
-         * @param device is the disconnected bluetooth device
-         * @param reason is the disconnect reason
-         */
-        public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {}
-
-        /**
-         * @hide
-         */
-        @Retention(RetentionPolicy.SOURCE)
-        @IntDef(prefix = { "REASON_" }, value = {
-                BluetoothStatusCodes.ERROR_UNKNOWN,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS,
-                BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS})
-        public @interface DisconnectReason {}
-
-        /**
-         * Returns human-readable strings corresponding to {@link DisconnectReason}.
-         */
-        public static String disconnectReasonText(@DisconnectReason int reason) {
-            switch (reason) {
-                case BluetoothStatusCodes.ERROR_UNKNOWN:
-                    return "Reason unknown";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST:
-                    return "Local request";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST:
-                    return "Remote request";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL:
-                    return "Local error";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE:
-                    return "Remote error";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT:
-                    return "Timeout";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY:
-                    return "Security";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY:
-                    return "System policy";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED:
-                    return "Resource constrained";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS:
-                    return "Connection already exists";
-                case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS:
-                    return "Bad parameters";
-                default:
-                    return "Unrecognized disconnect reason: " + reason;
-            }
-        }
-    }
-
-    /**
-     * Converts old constant of priority to the new for connection policy
-     *
-     * @param priority is the priority to convert to connection policy
-     * @return the equivalent connection policy constant to the priority
-     *
-     * @hide
-     */
-    public static @ConnectionPolicy int priorityToConnectionPolicy(int priority) {
-        switch(priority) {
-            case BluetoothProfile.PRIORITY_AUTO_CONNECT:
-                return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
-            case BluetoothProfile.PRIORITY_ON:
-                return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
-            case BluetoothProfile.PRIORITY_OFF:
-                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-            case BluetoothProfile.PRIORITY_UNDEFINED:
-                return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
-            default:
-                Log.e(TAG, "setPriority: Invalid priority: " + priority);
-                return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
-        }
-    }
-
-    /**
-     * Converts new constant of connection policy to the old for priority
-     *
-     * @param connectionPolicy is the connection policy to convert to priority
-     * @return the equivalent priority constant to the connectionPolicy
-     *
-     * @hide
-     */
-    public static int connectionPolicyToPriority(@ConnectionPolicy int connectionPolicy) {
-        switch(connectionPolicy) {
-            case BluetoothProfile.CONNECTION_POLICY_ALLOWED:
-                return BluetoothProfile.PRIORITY_ON;
-            case BluetoothProfile.CONNECTION_POLICY_FORBIDDEN:
-                return BluetoothProfile.PRIORITY_OFF;
-            case BluetoothProfile.CONNECTION_POLICY_UNKNOWN:
-                return BluetoothProfile.PRIORITY_UNDEFINED;
-        }
-        return BluetoothProfile.PRIORITY_UNDEFINED;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothAssignedNumbers.java b/core/java/android/bluetooth/BluetoothAssignedNumbers.java
deleted file mode 100644
index 41a34e0..0000000
--- a/core/java/android/bluetooth/BluetoothAssignedNumbers.java
+++ /dev/null
@@ -1,1171 +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.
- */
-
-package android.bluetooth;
-
-/**
- * Bluetooth Assigned Numbers.
- * <p>
- * For now we only include Company ID values.
- *
- * @see <a href="https://www.bluetooth.org/technical/assignednumbers/identifiers.htm"> The Official
- * Bluetooth SIG Member Website | Company Identifiers</a>
- */
-public class BluetoothAssignedNumbers {
-
-    // Bluetooth SIG Company ID values
-    /*
-     * Ericsson Technology Licensing.
-     */
-    public static final int ERICSSON_TECHNOLOGY = 0x0000;
-
-    /*
-     * Nokia Mobile Phones.
-     */
-    public static final int NOKIA_MOBILE_PHONES = 0x0001;
-
-    /*
-     * Intel Corp.
-     */
-    public static final int INTEL = 0x0002;
-
-    /*
-     * IBM Corp.
-     */
-    public static final int IBM = 0x0003;
-
-    /*
-     * Toshiba Corp.
-     */
-    public static final int TOSHIBA = 0x0004;
-
-    /*
-     * 3Com.
-     */
-    public static final int THREECOM = 0x0005;
-
-    /*
-     * Microsoft.
-     */
-    public static final int MICROSOFT = 0x0006;
-
-    /*
-     * Lucent.
-     */
-    public static final int LUCENT = 0x0007;
-
-    /*
-     * Motorola.
-     */
-    public static final int MOTOROLA = 0x0008;
-
-    /*
-     * Infineon Technologies AG.
-     */
-    public static final int INFINEON_TECHNOLOGIES = 0x0009;
-
-    /*
-     * Cambridge Silicon Radio.
-     */
-    public static final int CAMBRIDGE_SILICON_RADIO = 0x000A;
-
-    /*
-     * Silicon Wave.
-     */
-    public static final int SILICON_WAVE = 0x000B;
-
-    /*
-     * Digianswer A/S.
-     */
-    public static final int DIGIANSWER = 0x000C;
-
-    /*
-     * Texas Instruments Inc.
-     */
-    public static final int TEXAS_INSTRUMENTS = 0x000D;
-
-    /*
-     * Parthus Technologies Inc.
-     */
-    public static final int PARTHUS_TECHNOLOGIES = 0x000E;
-
-    /*
-     * Broadcom Corporation.
-     */
-    public static final int BROADCOM = 0x000F;
-
-    /*
-     * Mitel Semiconductor.
-     */
-    public static final int MITEL_SEMICONDUCTOR = 0x0010;
-
-    /*
-     * Widcomm, Inc.
-     */
-    public static final int WIDCOMM = 0x0011;
-
-    /*
-     * Zeevo, Inc.
-     */
-    public static final int ZEEVO = 0x0012;
-
-    /*
-     * Atmel Corporation.
-     */
-    public static final int ATMEL = 0x0013;
-
-    /*
-     * Mitsubishi Electric Corporation.
-     */
-    public static final int MITSUBISHI_ELECTRIC = 0x0014;
-
-    /*
-     * RTX Telecom A/S.
-     */
-    public static final int RTX_TELECOM = 0x0015;
-
-    /*
-     * KC Technology Inc.
-     */
-    public static final int KC_TECHNOLOGY = 0x0016;
-
-    /*
-     * Newlogic.
-     */
-    public static final int NEWLOGIC = 0x0017;
-
-    /*
-     * Transilica, Inc.
-     */
-    public static final int TRANSILICA = 0x0018;
-
-    /*
-     * Rohde & Schwarz GmbH & Co. KG.
-     */
-    public static final int ROHDE_AND_SCHWARZ = 0x0019;
-
-    /*
-     * TTPCom Limited.
-     */
-    public static final int TTPCOM = 0x001A;
-
-    /*
-     * Signia Technologies, Inc.
-     */
-    public static final int SIGNIA_TECHNOLOGIES = 0x001B;
-
-    /*
-     * Conexant Systems Inc.
-     */
-    public static final int CONEXANT_SYSTEMS = 0x001C;
-
-    /*
-     * Qualcomm.
-     */
-    public static final int QUALCOMM = 0x001D;
-
-    /*
-     * Inventel.
-     */
-    public static final int INVENTEL = 0x001E;
-
-    /*
-     * AVM Berlin.
-     */
-    public static final int AVM_BERLIN = 0x001F;
-
-    /*
-     * BandSpeed, Inc.
-     */
-    public static final int BANDSPEED = 0x0020;
-
-    /*
-     * Mansella Ltd.
-     */
-    public static final int MANSELLA = 0x0021;
-
-    /*
-     * NEC Corporation.
-     */
-    public static final int NEC = 0x0022;
-
-    /*
-     * WavePlus Technology Co., Ltd.
-     */
-    public static final int WAVEPLUS_TECHNOLOGY = 0x0023;
-
-    /*
-     * Alcatel.
-     */
-    public static final int ALCATEL = 0x0024;
-
-    /*
-     * Philips Semiconductors.
-     */
-    public static final int PHILIPS_SEMICONDUCTORS = 0x0025;
-
-    /*
-     * C Technologies.
-     */
-    public static final int C_TECHNOLOGIES = 0x0026;
-
-    /*
-     * Open Interface.
-     */
-    public static final int OPEN_INTERFACE = 0x0027;
-
-    /*
-     * R F Micro Devices.
-     */
-    public static final int RF_MICRO_DEVICES = 0x0028;
-
-    /*
-     * Hitachi Ltd.
-     */
-    public static final int HITACHI = 0x0029;
-
-    /*
-     * Symbol Technologies, Inc.
-     */
-    public static final int SYMBOL_TECHNOLOGIES = 0x002A;
-
-    /*
-     * Tenovis.
-     */
-    public static final int TENOVIS = 0x002B;
-
-    /*
-     * Macronix International Co. Ltd.
-     */
-    public static final int MACRONIX = 0x002C;
-
-    /*
-     * GCT Semiconductor.
-     */
-    public static final int GCT_SEMICONDUCTOR = 0x002D;
-
-    /*
-     * Norwood Systems.
-     */
-    public static final int NORWOOD_SYSTEMS = 0x002E;
-
-    /*
-     * MewTel Technology Inc.
-     */
-    public static final int MEWTEL_TECHNOLOGY = 0x002F;
-
-    /*
-     * ST Microelectronics.
-     */
-    public static final int ST_MICROELECTRONICS = 0x0030;
-
-    /*
-     * Synopsys.
-     */
-    public static final int SYNOPSYS = 0x0031;
-
-    /*
-     * Red-M (Communications) Ltd.
-     */
-    public static final int RED_M = 0x0032;
-
-    /*
-     * Commil Ltd.
-     */
-    public static final int COMMIL = 0x0033;
-
-    /*
-     * Computer Access Technology Corporation (CATC).
-     */
-    public static final int CATC = 0x0034;
-
-    /*
-     * Eclipse (HQ Espana) S.L.
-     */
-    public static final int ECLIPSE = 0x0035;
-
-    /*
-     * Renesas Technology Corp.
-     */
-    public static final int RENESAS_TECHNOLOGY = 0x0036;
-
-    /*
-     * Mobilian Corporation.
-     */
-    public static final int MOBILIAN_CORPORATION = 0x0037;
-
-    /*
-     * Terax.
-     */
-    public static final int TERAX = 0x0038;
-
-    /*
-     * Integrated System Solution Corp.
-     */
-    public static final int INTEGRATED_SYSTEM_SOLUTION = 0x0039;
-
-    /*
-     * Matsushita Electric Industrial Co., Ltd.
-     */
-    public static final int MATSUSHITA_ELECTRIC = 0x003A;
-
-    /*
-     * Gennum Corporation.
-     */
-    public static final int GENNUM = 0x003B;
-
-    /*
-     * Research In Motion.
-     */
-    public static final int RESEARCH_IN_MOTION = 0x003C;
-
-    /*
-     * IPextreme, Inc.
-     */
-    public static final int IPEXTREME = 0x003D;
-
-    /*
-     * Systems and Chips, Inc.
-     */
-    public static final int SYSTEMS_AND_CHIPS = 0x003E;
-
-    /*
-     * Bluetooth SIG, Inc.
-     */
-    public static final int BLUETOOTH_SIG = 0x003F;
-
-    /*
-     * Seiko Epson Corporation.
-     */
-    public static final int SEIKO_EPSON = 0x0040;
-
-    /*
-     * Integrated Silicon Solution Taiwan, Inc.
-     */
-    public static final int INTEGRATED_SILICON_SOLUTION = 0x0041;
-
-    /*
-     * CONWISE Technology Corporation Ltd.
-     */
-    public static final int CONWISE_TECHNOLOGY = 0x0042;
-
-    /*
-     * PARROT SA.
-     */
-    public static final int PARROT = 0x0043;
-
-    /*
-     * Socket Mobile.
-     */
-    public static final int SOCKET_MOBILE = 0x0044;
-
-    /*
-     * Atheros Communications, Inc.
-     */
-    public static final int ATHEROS_COMMUNICATIONS = 0x0045;
-
-    /*
-     * MediaTek, Inc.
-     */
-    public static final int MEDIATEK = 0x0046;
-
-    /*
-     * Bluegiga.
-     */
-    public static final int BLUEGIGA = 0x0047;
-
-    /*
-     * Marvell Technology Group Ltd.
-     */
-    public static final int MARVELL = 0x0048;
-
-    /*
-     * 3DSP Corporation.
-     */
-    public static final int THREE_DSP = 0x0049;
-
-    /*
-     * Accel Semiconductor Ltd.
-     */
-    public static final int ACCEL_SEMICONDUCTOR = 0x004A;
-
-    /*
-     * Continental Automotive Systems.
-     */
-    public static final int CONTINENTAL_AUTOMOTIVE = 0x004B;
-
-    /*
-     * Apple, Inc.
-     */
-    public static final int APPLE = 0x004C;
-
-    /*
-     * Staccato Communications, Inc.
-     */
-    public static final int STACCATO_COMMUNICATIONS = 0x004D;
-
-    /*
-     * Avago Technologies.
-     */
-    public static final int AVAGO = 0x004E;
-
-    /*
-     * APT Licensing Ltd.
-     */
-    public static final int APT_LICENSING = 0x004F;
-
-    /*
-     * SiRF Technology, Inc.
-     */
-    public static final int SIRF_TECHNOLOGY = 0x0050;
-
-    /*
-     * Tzero Technologies, Inc.
-     */
-    public static final int TZERO_TECHNOLOGIES = 0x0051;
-
-    /*
-     * J&M Corporation.
-     */
-    public static final int J_AND_M = 0x0052;
-
-    /*
-     * Free2move AB.
-     */
-    public static final int FREE2MOVE = 0x0053;
-
-    /*
-     * 3DiJoy Corporation.
-     */
-    public static final int THREE_DIJOY = 0x0054;
-
-    /*
-     * Plantronics, Inc.
-     */
-    public static final int PLANTRONICS = 0x0055;
-
-    /*
-     * Sony Ericsson Mobile Communications.
-     */
-    public static final int SONY_ERICSSON = 0x0056;
-
-    /*
-     * Harman International Industries, Inc.
-     */
-    public static final int HARMAN_INTERNATIONAL = 0x0057;
-
-    /*
-     * Vizio, Inc.
-     */
-    public static final int VIZIO = 0x0058;
-
-    /*
-     * Nordic Semiconductor ASA.
-     */
-    public static final int NORDIC_SEMICONDUCTOR = 0x0059;
-
-    /*
-     * EM Microelectronic-Marin SA.
-     */
-    public static final int EM_MICROELECTRONIC_MARIN = 0x005A;
-
-    /*
-     * Ralink Technology Corporation.
-     */
-    public static final int RALINK_TECHNOLOGY = 0x005B;
-
-    /*
-     * Belkin International, Inc.
-     */
-    public static final int BELKIN_INTERNATIONAL = 0x005C;
-
-    /*
-     * Realtek Semiconductor Corporation.
-     */
-    public static final int REALTEK_SEMICONDUCTOR = 0x005D;
-
-    /*
-     * Stonestreet One, LLC.
-     */
-    public static final int STONESTREET_ONE = 0x005E;
-
-    /*
-     * Wicentric, Inc.
-     */
-    public static final int WICENTRIC = 0x005F;
-
-    /*
-     * RivieraWaves S.A.S.
-     */
-    public static final int RIVIERAWAVES = 0x0060;
-
-    /*
-     * RDA Microelectronics.
-     */
-    public static final int RDA_MICROELECTRONICS = 0x0061;
-
-    /*
-     * Gibson Guitars.
-     */
-    public static final int GIBSON_GUITARS = 0x0062;
-
-    /*
-     * MiCommand Inc.
-     */
-    public static final int MICOMMAND = 0x0063;
-
-    /*
-     * Band XI International, LLC.
-     */
-    public static final int BAND_XI_INTERNATIONAL = 0x0064;
-
-    /*
-     * Hewlett-Packard Company.
-     */
-    public static final int HEWLETT_PACKARD = 0x0065;
-
-    /*
-     * 9Solutions Oy.
-     */
-    public static final int NINE_SOLUTIONS = 0x0066;
-
-    /*
-     * GN Netcom A/S.
-     */
-    public static final int GN_NETCOM = 0x0067;
-
-    /*
-     * General Motors.
-     */
-    public static final int GENERAL_MOTORS = 0x0068;
-
-    /*
-     * A&D Engineering, Inc.
-     */
-    public static final int A_AND_D_ENGINEERING = 0x0069;
-
-    /*
-     * MindTree Ltd.
-     */
-    public static final int MINDTREE = 0x006A;
-
-    /*
-     * Polar Electro OY.
-     */
-    public static final int POLAR_ELECTRO = 0x006B;
-
-    /*
-     * Beautiful Enterprise Co., Ltd.
-     */
-    public static final int BEAUTIFUL_ENTERPRISE = 0x006C;
-
-    /*
-     * BriarTek, Inc.
-     */
-    public static final int BRIARTEK = 0x006D;
-
-    /*
-     * Summit Data Communications, Inc.
-     */
-    public static final int SUMMIT_DATA_COMMUNICATIONS = 0x006E;
-
-    /*
-     * Sound ID.
-     */
-    public static final int SOUND_ID = 0x006F;
-
-    /*
-     * Monster, LLC.
-     */
-    public static final int MONSTER = 0x0070;
-
-    /*
-     * connectBlue AB.
-     */
-    public static final int CONNECTBLUE = 0x0071;
-
-    /*
-     * ShangHai Super Smart Electronics Co. Ltd.
-     */
-    public static final int SHANGHAI_SUPER_SMART_ELECTRONICS = 0x0072;
-
-    /*
-     * Group Sense Ltd.
-     */
-    public static final int GROUP_SENSE = 0x0073;
-
-    /*
-     * Zomm, LLC.
-     */
-    public static final int ZOMM = 0x0074;
-
-    /*
-     * Samsung Electronics Co. Ltd.
-     */
-    public static final int SAMSUNG_ELECTRONICS = 0x0075;
-
-    /*
-     * Creative Technology Ltd.
-     */
-    public static final int CREATIVE_TECHNOLOGY = 0x0076;
-
-    /*
-     * Laird Technologies.
-     */
-    public static final int LAIRD_TECHNOLOGIES = 0x0077;
-
-    /*
-     * Nike, Inc.
-     */
-    public static final int NIKE = 0x0078;
-
-    /*
-     * lesswire AG.
-     */
-    public static final int LESSWIRE = 0x0079;
-
-    /*
-     * MStar Semiconductor, Inc.
-     */
-    public static final int MSTAR_SEMICONDUCTOR = 0x007A;
-
-    /*
-     * Hanlynn Technologies.
-     */
-    public static final int HANLYNN_TECHNOLOGIES = 0x007B;
-
-    /*
-     * A & R Cambridge.
-     */
-    public static final int A_AND_R_CAMBRIDGE = 0x007C;
-
-    /*
-     * Seers Technology Co. Ltd.
-     */
-    public static final int SEERS_TECHNOLOGY = 0x007D;
-
-    /*
-     * Sports Tracking Technologies Ltd.
-     */
-    public static final int SPORTS_TRACKING_TECHNOLOGIES = 0x007E;
-
-    /*
-     * Autonet Mobile.
-     */
-    public static final int AUTONET_MOBILE = 0x007F;
-
-    /*
-     * DeLorme Publishing Company, Inc.
-     */
-    public static final int DELORME_PUBLISHING_COMPANY = 0x0080;
-
-    /*
-     * WuXi Vimicro.
-     */
-    public static final int WUXI_VIMICRO = 0x0081;
-
-    /*
-     * Sennheiser Communications A/S.
-     */
-    public static final int SENNHEISER_COMMUNICATIONS = 0x0082;
-
-    /*
-     * TimeKeeping Systems, Inc.
-     */
-    public static final int TIMEKEEPING_SYSTEMS = 0x0083;
-
-    /*
-     * Ludus Helsinki Ltd.
-     */
-    public static final int LUDUS_HELSINKI = 0x0084;
-
-    /*
-     * BlueRadios, Inc.
-     */
-    public static final int BLUERADIOS = 0x0085;
-
-    /*
-     * equinox AG.
-     */
-    public static final int EQUINOX_AG = 0x0086;
-
-    /*
-     * Garmin International, Inc.
-     */
-    public static final int GARMIN_INTERNATIONAL = 0x0087;
-
-    /*
-     * Ecotest.
-     */
-    public static final int ECOTEST = 0x0088;
-
-    /*
-     * GN ReSound A/S.
-     */
-    public static final int GN_RESOUND = 0x0089;
-
-    /*
-     * Jawbone.
-     */
-    public static final int JAWBONE = 0x008A;
-
-    /*
-     * Topcorn Positioning Systems, LLC.
-     */
-    public static final int TOPCORN_POSITIONING_SYSTEMS = 0x008B;
-
-    /*
-     * Qualcomm Labs, Inc.
-     */
-    public static final int QUALCOMM_LABS = 0x008C;
-
-    /*
-     * Zscan Software.
-     */
-    public static final int ZSCAN_SOFTWARE = 0x008D;
-
-    /*
-     * Quintic Corp.
-     */
-    public static final int QUINTIC = 0x008E;
-
-    /*
-     * Stollman E+V GmbH.
-     */
-    public static final int STOLLMAN_E_PLUS_V = 0x008F;
-
-    /*
-     * Funai Electric Co., Ltd.
-     */
-    public static final int FUNAI_ELECTRIC = 0x0090;
-
-    /*
-     * Advanced PANMOBIL Systems GmbH & Co. KG.
-     */
-    public static final int ADVANCED_PANMOBIL_SYSTEMS = 0x0091;
-
-    /*
-     * ThinkOptics, Inc.
-     */
-    public static final int THINKOPTICS = 0x0092;
-
-    /*
-     * Universal Electronics, Inc.
-     */
-    public static final int UNIVERSAL_ELECTRONICS = 0x0093;
-
-    /*
-     * Airoha Technology Corp.
-     */
-    public static final int AIROHA_TECHNOLOGY = 0x0094;
-
-    /*
-     * NEC Lighting, Ltd.
-     */
-    public static final int NEC_LIGHTING = 0x0095;
-
-    /*
-     * ODM Technology, Inc.
-     */
-    public static final int ODM_TECHNOLOGY = 0x0096;
-
-    /*
-     * Bluetrek Technologies Limited.
-     */
-    public static final int BLUETREK_TECHNOLOGIES = 0x0097;
-
-    /*
-     * zer01.tv GmbH.
-     */
-    public static final int ZER01_TV = 0x0098;
-
-    /*
-     * i.Tech Dynamic Global Distribution Ltd.
-     */
-    public static final int I_TECH_DYNAMIC_GLOBAL_DISTRIBUTION = 0x0099;
-
-    /*
-     * Alpwise.
-     */
-    public static final int ALPWISE = 0x009A;
-
-    /*
-     * Jiangsu Toppower Automotive Electronics Co., Ltd.
-     */
-    public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS = 0x009B;
-
-    /*
-     * Colorfy, Inc.
-     */
-    public static final int COLORFY = 0x009C;
-
-    /*
-     * Geoforce Inc.
-     */
-    public static final int GEOFORCE = 0x009D;
-
-    /*
-     * Bose Corporation.
-     */
-    public static final int BOSE = 0x009E;
-
-    /*
-     * Suunto Oy.
-     */
-    public static final int SUUNTO = 0x009F;
-
-    /*
-     * Kensington Computer Products Group.
-     */
-    public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 0x00A0;
-
-    /*
-     * SR-Medizinelektronik.
-     */
-    public static final int SR_MEDIZINELEKTRONIK = 0x00A1;
-
-    /*
-     * Vertu Corporation Limited.
-     */
-    public static final int VERTU = 0x00A2;
-
-    /*
-     * Meta Watch Ltd.
-     */
-    public static final int META_WATCH = 0x00A3;
-
-    /*
-     * LINAK A/S.
-     */
-    public static final int LINAK = 0x00A4;
-
-    /*
-     * OTL Dynamics LLC.
-     */
-    public static final int OTL_DYNAMICS = 0x00A5;
-
-    /*
-     * Panda Ocean Inc.
-     */
-    public static final int PANDA_OCEAN = 0x00A6;
-
-    /*
-     * Visteon Corporation.
-     */
-    public static final int VISTEON = 0x00A7;
-
-    /*
-     * ARP Devices Limited.
-     */
-    public static final int ARP_DEVICES = 0x00A8;
-
-    /*
-     * Magneti Marelli S.p.A.
-     */
-    public static final int MAGNETI_MARELLI = 0x00A9;
-
-    /*
-     * CAEN RFID srl.
-     */
-    public static final int CAEN_RFID = 0x00AA;
-
-    /*
-     * Ingenieur-Systemgruppe Zahn GmbH.
-     */
-    public static final int INGENIEUR_SYSTEMGRUPPE_ZAHN = 0x00AB;
-
-    /*
-     * Green Throttle Games.
-     */
-    public static final int GREEN_THROTTLE_GAMES = 0x00AC;
-
-    /*
-     * Peter Systemtechnik GmbH.
-     */
-    public static final int PETER_SYSTEMTECHNIK = 0x00AD;
-
-    /*
-     * Omegawave Oy.
-     */
-    public static final int OMEGAWAVE = 0x00AE;
-
-    /*
-     * Cinetix.
-     */
-    public static final int CINETIX = 0x00AF;
-
-    /*
-     * Passif Semiconductor Corp.
-     */
-    public static final int PASSIF_SEMICONDUCTOR = 0x00B0;
-
-    /*
-     * Saris Cycling Group, Inc.
-     */
-    public static final int SARIS_CYCLING_GROUP = 0x00B1;
-
-    /*
-     * Bekey A/S.
-     */
-    public static final int BEKEY = 0x00B2;
-
-    /*
-     * Clarinox Technologies Pty. Ltd.
-     */
-    public static final int CLARINOX_TECHNOLOGIES = 0x00B3;
-
-    /*
-     * BDE Technology Co., Ltd.
-     */
-    public static final int BDE_TECHNOLOGY = 0x00B4;
-
-    /*
-     * Swirl Networks.
-     */
-    public static final int SWIRL_NETWORKS = 0x00B5;
-
-    /*
-     * Meso international.
-     */
-    public static final int MESO_INTERNATIONAL = 0x00B6;
-
-    /*
-     * TreLab Ltd.
-     */
-    public static final int TRELAB = 0x00B7;
-
-    /*
-     * Qualcomm Innovation Center, Inc. (QuIC).
-     */
-    public static final int QUALCOMM_INNOVATION_CENTER = 0x00B8;
-
-    /*
-     * Johnson Controls, Inc.
-     */
-    public static final int JOHNSON_CONTROLS = 0x00B9;
-
-    /*
-     * Starkey Laboratories Inc.
-     */
-    public static final int STARKEY_LABORATORIES = 0x00BA;
-
-    /*
-     * S-Power Electronics Limited.
-     */
-    public static final int S_POWER_ELECTRONICS = 0x00BB;
-
-    /*
-     * Ace Sensor Inc.
-     */
-    public static final int ACE_SENSOR = 0x00BC;
-
-    /*
-     * Aplix Corporation.
-     */
-    public static final int APLIX = 0x00BD;
-
-    /*
-     * AAMP of America.
-     */
-    public static final int AAMP_OF_AMERICA = 0x00BE;
-
-    /*
-     * Stalmart Technology Limited.
-     */
-    public static final int STALMART_TECHNOLOGY = 0x00BF;
-
-    /*
-     * AMICCOM Electronics Corporation.
-     */
-    public static final int AMICCOM_ELECTRONICS = 0x00C0;
-
-    /*
-     * Shenzhen Excelsecu Data Technology Co.,Ltd.
-     */
-    public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY = 0x00C1;
-
-    /*
-     * Geneq Inc.
-     */
-    public static final int GENEQ = 0x00C2;
-
-    /*
-     * adidas AG.
-     */
-    public static final int ADIDAS = 0x00C3;
-
-    /*
-     * LG Electronics.
-     */
-    public static final int LG_ELECTRONICS = 0x00C4;
-
-    /*
-     * Onset Computer Corporation.
-     */
-    public static final int ONSET_COMPUTER = 0x00C5;
-
-    /*
-     * Selfly BV.
-     */
-    public static final int SELFLY = 0x00C6;
-
-    /*
-     * Quuppa Oy.
-     */
-    public static final int QUUPPA = 0x00C7;
-
-    /*
-     * GeLo Inc.
-     */
-    public static final int GELO = 0x00C8;
-
-    /*
-     * Evluma.
-     */
-    public static final int EVLUMA = 0x00C9;
-
-    /*
-     * MC10.
-     */
-    public static final int MC10 = 0x00CA;
-
-    /*
-     * Binauric SE.
-     */
-    public static final int BINAURIC = 0x00CB;
-
-    /*
-     * Beats Electronics.
-     */
-    public static final int BEATS_ELECTRONICS = 0x00CC;
-
-    /*
-     * Microchip Technology Inc.
-     */
-    public static final int MICROCHIP_TECHNOLOGY = 0x00CD;
-
-    /*
-     * Elgato Systems GmbH.
-     */
-    public static final int ELGATO_SYSTEMS = 0x00CE;
-
-    /*
-     * ARCHOS SA.
-     */
-    public static final int ARCHOS = 0x00CF;
-
-    /*
-     * Dexcom, Inc.
-     */
-    public static final int DEXCOM = 0x00D0;
-
-    /*
-     * Polar Electro Europe B.V.
-     */
-    public static final int POLAR_ELECTRO_EUROPE = 0x00D1;
-
-    /*
-     * Dialog Semiconductor B.V.
-     */
-    public static final int DIALOG_SEMICONDUCTOR = 0x00D2;
-
-    /*
-     * Taixingbang Technology (HK) Co,. LTD.
-     */
-    public static final int TAIXINGBANG_TECHNOLOGY = 0x00D3;
-
-    /*
-     * Kawantech.
-     */
-    public static final int KAWANTECH = 0x00D4;
-
-    /*
-     * Austco Communication Systems.
-     */
-    public static final int AUSTCO_COMMUNICATION_SYSTEMS = 0x00D5;
-
-    /*
-     * Timex Group USA, Inc.
-     */
-    public static final int TIMEX_GROUP_USA = 0x00D6;
-
-    /*
-     * Qualcomm Technologies, Inc.
-     */
-    public static final int QUALCOMM_TECHNOLOGIES = 0x00D7;
-
-    /*
-     * Qualcomm Connected Experiences, Inc.
-     */
-    public static final int QUALCOMM_CONNECTED_EXPERIENCES = 0x00D8;
-
-    /*
-     * Voyetra Turtle Beach.
-     */
-    public static final int VOYETRA_TURTLE_BEACH = 0x00D9;
-
-    /*
-     * txtr GmbH.
-     */
-    public static final int TXTR = 0x00DA;
-
-    /*
-     * Biosentronics.
-     */
-    public static final int BIOSENTRONICS = 0x00DB;
-
-    /*
-     * Procter & Gamble.
-     */
-    public static final int PROCTER_AND_GAMBLE = 0x00DC;
-
-    /*
-     * Hosiden Corporation.
-     */
-    public static final int HOSIDEN = 0x00DD;
-
-    /*
-     * Muzik LLC.
-     */
-    public static final int MUZIK = 0x00DE;
-
-    /*
-     * Misfit Wearables Corp.
-     */
-    public static final int MISFIT_WEARABLES = 0x00DF;
-
-    /*
-     * Google.
-     */
-    public static final int GOOGLE = 0x00E0;
-
-    /*
-     * Danlers Ltd.
-     */
-    public static final int DANLERS = 0x00E1;
-
-    /*
-     * Semilink Inc.
-     */
-    public static final int SEMILINK = 0x00E2;
-
-    /*
-     * You can't instantiate one of these.
-     */
-    private BluetoothAssignedNumbers() {
-    }
-
-}
diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.java b/core/java/android/bluetooth/BluetoothAudioConfig.java
deleted file mode 100644
index 4c8b8c1..0000000
--- a/core/java/android/bluetooth/BluetoothAudioConfig.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents the audio configuration for a Bluetooth A2DP source device.
- *
- * {@see BluetoothA2dpSink}
- *
- * {@hide}
- */
-public final class BluetoothAudioConfig implements Parcelable {
-
-    private final int mSampleRate;
-    private final int mChannelConfig;
-    private final int mAudioFormat;
-
-    public BluetoothAudioConfig(int sampleRate, int channelConfig, int audioFormat) {
-        mSampleRate = sampleRate;
-        mChannelConfig = channelConfig;
-        mAudioFormat = audioFormat;
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (o instanceof BluetoothAudioConfig) {
-            BluetoothAudioConfig bac = (BluetoothAudioConfig) o;
-            return (bac.mSampleRate == mSampleRate && bac.mChannelConfig == mChannelConfig
-                    && bac.mAudioFormat == mAudioFormat);
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return mSampleRate | (mChannelConfig << 24) | (mAudioFormat << 28);
-    }
-
-    @Override
-    public String toString() {
-        return "{mSampleRate:" + mSampleRate + ",mChannelConfig:" + mChannelConfig
-                + ",mAudioFormat:" + mAudioFormat + "}";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothAudioConfig> CREATOR =
-            new Parcelable.Creator<BluetoothAudioConfig>() {
-                public BluetoothAudioConfig createFromParcel(Parcel in) {
-                    int sampleRate = in.readInt();
-                    int channelConfig = in.readInt();
-                    int audioFormat = in.readInt();
-                    return new BluetoothAudioConfig(sampleRate, channelConfig, audioFormat);
-                }
-
-                public BluetoothAudioConfig[] newArray(int size) {
-                    return new BluetoothAudioConfig[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mSampleRate);
-        out.writeInt(mChannelConfig);
-        out.writeInt(mAudioFormat);
-    }
-
-    /**
-     * Returns the sample rate in samples per second
-     *
-     * @return sample rate
-     */
-    public int getSampleRate() {
-        return mSampleRate;
-    }
-
-    /**
-     * Returns the channel configuration (either {@link android.media.AudioFormat#CHANNEL_IN_MONO}
-     * or {@link android.media.AudioFormat#CHANNEL_IN_STEREO})
-     *
-     * @return channel configuration
-     */
-    public int getChannelConfig() {
-        return mChannelConfig;
-    }
-
-    /**
-     * Returns the channel audio format (either {@link android.media.AudioFormat#ENCODING_PCM_16BIT}
-     * or {@link android.media.AudioFormat#ENCODING_PCM_8BIT}
-     *
-     * @return audio format
-     */
-    public int getAudioFormat() {
-        return mAudioFormat;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothAvrcp.java b/core/java/android/bluetooth/BluetoothAvrcp.java
deleted file mode 100644
index 1a4c759..0000000
--- a/core/java/android/bluetooth/BluetoothAvrcp.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * This class contains constants for Bluetooth AVRCP profile.
- *
- * {@hide}
- */
-public final class BluetoothAvrcp {
-
-    /*
-     * State flags for Passthrough commands
-    */
-    public static final int PASSTHROUGH_STATE_PRESS = 0;
-    public static final int PASSTHROUGH_STATE_RELEASE = 1;
-
-    /*
-     * Operation IDs for Passthrough commands
-    */
-    public static final int PASSTHROUGH_ID_SELECT = 0x00;    /* select */
-    public static final int PASSTHROUGH_ID_UP = 0x01;    /* up */
-    public static final int PASSTHROUGH_ID_DOWN = 0x02;    /* down */
-    public static final int PASSTHROUGH_ID_LEFT = 0x03;    /* left */
-    public static final int PASSTHROUGH_ID_RIGHT = 0x04;    /* right */
-    public static final int PASSTHROUGH_ID_RIGHT_UP = 0x05;    /* right-up */
-    public static final int PASSTHROUGH_ID_RIGHT_DOWN = 0x06;    /* right-down */
-    public static final int PASSTHROUGH_ID_LEFT_UP = 0x07;    /* left-up */
-    public static final int PASSTHROUGH_ID_LEFT_DOWN = 0x08;    /* left-down */
-    public static final int PASSTHROUGH_ID_ROOT_MENU = 0x09;    /* root menu */
-    public static final int PASSTHROUGH_ID_SETUP_MENU = 0x0A;    /* setup menu */
-    public static final int PASSTHROUGH_ID_CONT_MENU = 0x0B;    /* contents menu */
-    public static final int PASSTHROUGH_ID_FAV_MENU = 0x0C;    /* favorite menu */
-    public static final int PASSTHROUGH_ID_EXIT = 0x0D;    /* exit */
-    public static final int PASSTHROUGH_ID_0 = 0x20;    /* 0 */
-    public static final int PASSTHROUGH_ID_1 = 0x21;    /* 1 */
-    public static final int PASSTHROUGH_ID_2 = 0x22;    /* 2 */
-    public static final int PASSTHROUGH_ID_3 = 0x23;    /* 3 */
-    public static final int PASSTHROUGH_ID_4 = 0x24;    /* 4 */
-    public static final int PASSTHROUGH_ID_5 = 0x25;    /* 5 */
-    public static final int PASSTHROUGH_ID_6 = 0x26;    /* 6 */
-    public static final int PASSTHROUGH_ID_7 = 0x27;    /* 7 */
-    public static final int PASSTHROUGH_ID_8 = 0x28;    /* 8 */
-    public static final int PASSTHROUGH_ID_9 = 0x29;    /* 9 */
-    public static final int PASSTHROUGH_ID_DOT = 0x2A;    /* dot */
-    public static final int PASSTHROUGH_ID_ENTER = 0x2B;    /* enter */
-    public static final int PASSTHROUGH_ID_CLEAR = 0x2C;    /* clear */
-    public static final int PASSTHROUGH_ID_CHAN_UP = 0x30;    /* channel up */
-    public static final int PASSTHROUGH_ID_CHAN_DOWN = 0x31;    /* channel down */
-    public static final int PASSTHROUGH_ID_PREV_CHAN = 0x32;    /* previous channel */
-    public static final int PASSTHROUGH_ID_SOUND_SEL = 0x33;    /* sound select */
-    public static final int PASSTHROUGH_ID_INPUT_SEL = 0x34;    /* input select */
-    public static final int PASSTHROUGH_ID_DISP_INFO = 0x35;    /* display information */
-    public static final int PASSTHROUGH_ID_HELP = 0x36;    /* help */
-    public static final int PASSTHROUGH_ID_PAGE_UP = 0x37;    /* page up */
-    public static final int PASSTHROUGH_ID_PAGE_DOWN = 0x38;    /* page down */
-    public static final int PASSTHROUGH_ID_POWER = 0x40;    /* power */
-    public static final int PASSTHROUGH_ID_VOL_UP = 0x41;    /* volume up */
-    public static final int PASSTHROUGH_ID_VOL_DOWN = 0x42;    /* volume down */
-    public static final int PASSTHROUGH_ID_MUTE = 0x43;    /* mute */
-    public static final int PASSTHROUGH_ID_PLAY = 0x44;    /* play */
-    public static final int PASSTHROUGH_ID_STOP = 0x45;    /* stop */
-    public static final int PASSTHROUGH_ID_PAUSE = 0x46;    /* pause */
-    public static final int PASSTHROUGH_ID_RECORD = 0x47;    /* record */
-    public static final int PASSTHROUGH_ID_REWIND = 0x48;    /* rewind */
-    public static final int PASSTHROUGH_ID_FAST_FOR = 0x49;    /* fast forward */
-    public static final int PASSTHROUGH_ID_EJECT = 0x4A;    /* eject */
-    public static final int PASSTHROUGH_ID_FORWARD = 0x4B;    /* forward */
-    public static final int PASSTHROUGH_ID_BACKWARD = 0x4C;    /* backward */
-    public static final int PASSTHROUGH_ID_ANGLE = 0x50;    /* angle */
-    public static final int PASSTHROUGH_ID_SUBPICT = 0x51;    /* subpicture */
-    public static final int PASSTHROUGH_ID_F1 = 0x71;    /* F1 */
-    public static final int PASSTHROUGH_ID_F2 = 0x72;    /* F2 */
-    public static final int PASSTHROUGH_ID_F3 = 0x73;    /* F3 */
-    public static final int PASSTHROUGH_ID_F4 = 0x74;    /* F4 */
-    public static final int PASSTHROUGH_ID_F5 = 0x75;    /* F5 */
-    public static final int PASSTHROUGH_ID_VENDOR = 0x7E;    /* vendor unique */
-    public static final int PASSTHROUGH_KEYPRESSED_RELEASE = 0x80;
-}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
deleted file mode 100644
index 81fc3e1..0000000
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth AVRCP Controller. It currently
- * supports player information, playback support and track metadata.
- *
- * <p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothAvrcpController proxy object.
- *
- * {@hide}
- */
-public final class BluetoothAvrcpController implements BluetoothProfile {
-    private static final String TAG = "BluetoothAvrcpController";
-    private static final boolean DBG = false;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the AVRCP Controller
-     * profile.
-     *
-     * <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}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the change in player application setting state on AVRCP AG.
-     *
-     * <p>This intent will have the following extras:
-     * <ul>
-     * <li> {@link #EXTRA_PLAYER_SETTING} - {@link BluetoothAvrcpPlayerSettings} containing the
-     * most recent player setting. </li>
-     * </ul>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PLAYER_SETTING =
-            "android.bluetooth.avrcp-controller.profile.action.PLAYER_SETTING";
-
-    public static final String EXTRA_PLAYER_SETTING =
-            "android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
-                    "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
-                @Override
-                public IBluetoothAvrcpController getServiceInterface(IBinder service) {
-                    return IBluetoothAvrcpController.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothAvrcpController proxy object for interacting with the local
-     * Bluetooth AVRCP service.
-     */
-    /* package */ BluetoothAvrcpController(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /*package*/ void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothAvrcpController getService() {
-        return mProfileConnector.getService();
-    }
-
-    @Override
-    public void finalize() {
-        close();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothAvrcpController service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothAvrcpController service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        final IBluetoothAvrcpController service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Gets the player application settings.
-     *
-     * @return the {@link BluetoothAvrcpPlayerSettings} or {@link null} if there is an error.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "getPlayerSettings");
-        BluetoothAvrcpPlayerSettings settings = null;
-        final IBluetoothAvrcpController service = getService();
-        final BluetoothAvrcpPlayerSettings defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<BluetoothAvrcpPlayerSettings> recv =
-                        new SynchronousResultReceiver();
-                service.getPlayerSettings(device, mAttributionSource, recv);
-                settings = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sets the player app setting for current player.
-     * returns true in case setting is supported by remote, false otherwise
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
-        if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
-        final IBluetoothAvrcpController service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setPlayerApplicationSetting(plAppSetting, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Group Navigation Command to Remote.
-     * possible keycode values: next_grp, previous_grp defined above
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
-        Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
-                + keyState);
-        final IBluetoothAvrcpController service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.sendGroupNavigationCmd(device, keyCode, keyState, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-                return;
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    private static boolean isValidDevice(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/BluetoothAvrcpPlayerSettings.java b/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java
deleted file mode 100644
index 30aea1a..0000000
--- a/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class used to identify settings associated with the player on AG.
- *
- * {@hide}
- */
-public final class BluetoothAvrcpPlayerSettings implements Parcelable {
-    public static final String TAG = "BluetoothAvrcpPlayerSettings";
-
-    /**
-     * Equalizer setting.
-     */
-    public static final int SETTING_EQUALIZER = 0x01;
-
-    /**
-     * Repeat setting.
-     */
-    public static final int SETTING_REPEAT = 0x02;
-
-    /**
-     * Shuffle setting.
-     */
-    public static final int SETTING_SHUFFLE = 0x04;
-
-    /**
-     * Scan mode setting.
-     */
-    public static final int SETTING_SCAN = 0x08;
-
-    /**
-     * Invalid state.
-     *
-     * Used for returning error codes.
-     */
-    public static final int STATE_INVALID = -1;
-
-    /**
-     * OFF state.
-     *
-     * Denotes a general OFF state. Applies to all settings.
-     */
-    public static final int STATE_OFF = 0x00;
-
-    /**
-     * ON state.
-     *
-     * Applies to {@link SETTING_EQUALIZER}.
-     */
-    public static final int STATE_ON = 0x01;
-
-    /**
-     * Single track repeat.
-     *
-     * Applies only to {@link SETTING_REPEAT}.
-     */
-    public static final int STATE_SINGLE_TRACK = 0x02;
-
-    /**
-     * All track repeat/shuffle.
-     *
-     * Applies to {@link #SETTING_REPEAT}, {@link #SETTING_SHUFFLE} and {@link #SETTING_SCAN}.
-     */
-    public static final int STATE_ALL_TRACK = 0x03;
-
-    /**
-     * Group repeat/shuffle.
-     *
-     * Applies to {@link #SETTING_REPEAT}, {@link #SETTING_SHUFFLE} and {@link #SETTING_SCAN}.
-     */
-    public static final int STATE_GROUP = 0x04;
-
-    /**
-     * List of supported settings ORed.
-     */
-    private int mSettings;
-
-    /**
-     * Hash map of current capability values.
-     */
-    private Map<Integer, Integer> mSettingsValue = new HashMap<Integer, Integer>();
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mSettings);
-        out.writeInt(mSettingsValue.size());
-        for (int k : mSettingsValue.keySet()) {
-            out.writeInt(k);
-            out.writeInt(mSettingsValue.get(k));
-        }
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothAvrcpPlayerSettings> CREATOR =
-            new Parcelable.Creator<BluetoothAvrcpPlayerSettings>() {
-        public BluetoothAvrcpPlayerSettings createFromParcel(Parcel in) {
-            return new BluetoothAvrcpPlayerSettings(in);
-        }
-
-        public BluetoothAvrcpPlayerSettings[] newArray(int size) {
-            return new BluetoothAvrcpPlayerSettings[size];
-        }
-    };
-
-    private BluetoothAvrcpPlayerSettings(Parcel in) {
-        mSettings = in.readInt();
-        int numSettings = in.readInt();
-        for (int i = 0; i < numSettings; i++) {
-            mSettingsValue.put(in.readInt(), in.readInt());
-        }
-    }
-
-    /**
-     * Create a new player settings object.
-     *
-     * @param settings a ORed value of SETTINGS_* defined above.
-     */
-    public BluetoothAvrcpPlayerSettings(int settings) {
-        mSettings = settings;
-    }
-
-    /**
-     * Get the supported settings.
-     *
-     * @return int ORed value of supported settings.
-     */
-    public int getSettings() {
-        return mSettings;
-    }
-
-    /**
-     * Add a setting value.
-     *
-     * The setting must be part of possible settings in {@link getSettings()}.
-     *
-     * @param setting setting config.
-     * @param value value for the setting.
-     * @throws IllegalStateException if the setting is not supported.
-     */
-    public void addSettingValue(int setting, int value) {
-        if ((setting & mSettings) == 0) {
-            Log.e(TAG, "Setting not supported: " + setting + " " + mSettings);
-            throw new IllegalStateException("Setting not supported: " + setting);
-        }
-        mSettingsValue.put(setting, value);
-    }
-
-    /**
-     * Get a setting value.
-     *
-     * The setting must be part of possible settings in {@link getSettings()}.
-     *
-     * @param setting setting config.
-     * @return value value for the setting.
-     * @throws IllegalStateException if the setting is not supported.
-     */
-    public int getSettingValue(int setting) {
-        if ((setting & mSettings) == 0) {
-            Log.e(TAG, "Setting not supported: " + setting + " " + mSettings);
-            throw new IllegalStateException("Setting not supported: " + setting);
-        }
-        Integer i = mSettingsValue.get(setting);
-        if (i == null) return -1;
-        return i;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
deleted file mode 100755
index 8535b4f..0000000
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.Nullable;
-import android.annotation.TestApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-/**
- * Represents a Bluetooth class, which describes general characteristics
- * and capabilities of a device. For example, a Bluetooth class will
- * specify the general device type such as a phone, a computer, or
- * headset, and whether it's capable of services such as audio or telephony.
- *
- * <p>Every Bluetooth class is composed of zero or more service classes, and
- * exactly one device class. The device class is further broken down into major
- * and minor device class components.
- *
- * <p>{@link BluetoothClass} is useful as a hint to roughly describe a device
- * (for example to show an icon in the UI), but does not reliably describe which
- * Bluetooth profiles or services are actually supported by a device. Accurate
- * service discovery is done through SDP requests, which are automatically
- * performed when creating an RFCOMM socket with {@link
- * BluetoothDevice#createRfcommSocketToServiceRecord} and {@link
- * BluetoothAdapter#listenUsingRfcommWithServiceRecord}</p>
- *
- * <p>Use {@link BluetoothDevice#getBluetoothClass} to retrieve the class for
- * a remote device.
- *
- * <!--
- * The Bluetooth class is a 32 bit field. The format of these bits is defined at
- * http://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
- * (login required). This class contains that 32 bit field, and provides
- * constants and methods to determine which Service Class(es) and Device Class
- * are encoded in that field.
- * -->
- */
-public final class BluetoothClass implements Parcelable {
-    /**
-     * Legacy error value. Applications should use null instead.
-     *
-     * @hide
-     */
-    public static final int ERROR = 0xFF000000;
-
-    private final int mClass;
-
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public BluetoothClass(int classInt) {
-        mClass = classInt;
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (o instanceof BluetoothClass) {
-            return mClass == ((BluetoothClass) o).mClass;
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return mClass;
-    }
-
-    @Override
-    public String toString() {
-        return Integer.toHexString(mClass);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothClass> CREATOR =
-            new Parcelable.Creator<BluetoothClass>() {
-                public BluetoothClass createFromParcel(Parcel in) {
-                    return new BluetoothClass(in.readInt());
-                }
-
-                public BluetoothClass[] newArray(int size) {
-                    return new BluetoothClass[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mClass);
-    }
-
-    /**
-     * Defines all service class constants.
-     * <p>Each {@link BluetoothClass} encodes zero or more service classes.
-     */
-    public static final class Service {
-        private static final int BITMASK = 0xFFE000;
-
-        public static final int LIMITED_DISCOVERABILITY = 0x002000;
-        public static final int LE_AUDIO = 0x004000;
-        public static final int POSITIONING = 0x010000;
-        public static final int NETWORKING = 0x020000;
-        public static final int RENDER = 0x040000;
-        public static final int CAPTURE = 0x080000;
-        public static final int OBJECT_TRANSFER = 0x100000;
-        public static final int AUDIO = 0x200000;
-        public static final int TELEPHONY = 0x400000;
-        public static final int INFORMATION = 0x800000;
-    }
-
-    /**
-     * Return true if the specified service class is supported by this
-     * {@link BluetoothClass}.
-     * <p>Valid service classes are the public constants in
-     * {@link BluetoothClass.Service}. For example, {@link
-     * BluetoothClass.Service#AUDIO}.
-     *
-     * @param service valid service class
-     * @return true if the service class is supported
-     */
-    public boolean hasService(int service) {
-        return ((mClass & Service.BITMASK & service) != 0);
-    }
-
-    /**
-     * Defines all device class constants.
-     * <p>Each {@link BluetoothClass} encodes exactly one device class, with
-     * major and minor components.
-     * <p>The constants in {@link
-     * BluetoothClass.Device} represent a combination of major and minor
-     * device components (the complete device class). The constants in {@link
-     * BluetoothClass.Device.Major} represent only major device classes.
-     * <p>See {@link BluetoothClass.Service} for service class constants.
-     */
-    public static class Device {
-        private static final int BITMASK = 0x1FFC;
-
-        /**
-         * Defines all major device class constants.
-         * <p>See {@link BluetoothClass.Device} for minor classes.
-         */
-        public static class Major {
-            private static final int BITMASK = 0x1F00;
-
-            public static final int MISC = 0x0000;
-            public static final int COMPUTER = 0x0100;
-            public static final int PHONE = 0x0200;
-            public static final int NETWORKING = 0x0300;
-            public static final int AUDIO_VIDEO = 0x0400;
-            public static final int PERIPHERAL = 0x0500;
-            public static final int IMAGING = 0x0600;
-            public static final int WEARABLE = 0x0700;
-            public static final int TOY = 0x0800;
-            public static final int HEALTH = 0x0900;
-            public static final int UNCATEGORIZED = 0x1F00;
-        }
-
-        // Devices in the COMPUTER major class
-        public static final int COMPUTER_UNCATEGORIZED = 0x0100;
-        public static final int COMPUTER_DESKTOP = 0x0104;
-        public static final int COMPUTER_SERVER = 0x0108;
-        public static final int COMPUTER_LAPTOP = 0x010C;
-        public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110;
-        public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114;
-        public static final int COMPUTER_WEARABLE = 0x0118;
-
-        // Devices in the PHONE major class
-        public static final int PHONE_UNCATEGORIZED = 0x0200;
-        public static final int PHONE_CELLULAR = 0x0204;
-        public static final int PHONE_CORDLESS = 0x0208;
-        public static final int PHONE_SMART = 0x020C;
-        public static final int PHONE_MODEM_OR_GATEWAY = 0x0210;
-        public static final int PHONE_ISDN = 0x0214;
-
-        // Minor classes for the AUDIO_VIDEO major class
-        public static final int AUDIO_VIDEO_UNCATEGORIZED = 0x0400;
-        public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 0x0404;
-        public static final int AUDIO_VIDEO_HANDSFREE = 0x0408;
-        //public static final int AUDIO_VIDEO_RESERVED              = 0x040C;
-        public static final int AUDIO_VIDEO_MICROPHONE = 0x0410;
-        public static final int AUDIO_VIDEO_LOUDSPEAKER = 0x0414;
-        public static final int AUDIO_VIDEO_HEADPHONES = 0x0418;
-        public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 0x041C;
-        public static final int AUDIO_VIDEO_CAR_AUDIO = 0x0420;
-        public static final int AUDIO_VIDEO_SET_TOP_BOX = 0x0424;
-        public static final int AUDIO_VIDEO_HIFI_AUDIO = 0x0428;
-        public static final int AUDIO_VIDEO_VCR = 0x042C;
-        public static final int AUDIO_VIDEO_VIDEO_CAMERA = 0x0430;
-        public static final int AUDIO_VIDEO_CAMCORDER = 0x0434;
-        public static final int AUDIO_VIDEO_VIDEO_MONITOR = 0x0438;
-        public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 0x043C;
-        public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 0x0440;
-        //public static final int AUDIO_VIDEO_RESERVED              = 0x0444;
-        public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448;
-
-        // Devices in the WEARABLE major class
-        public static final int WEARABLE_UNCATEGORIZED = 0x0700;
-        public static final int WEARABLE_WRIST_WATCH = 0x0704;
-        public static final int WEARABLE_PAGER = 0x0708;
-        public static final int WEARABLE_JACKET = 0x070C;
-        public static final int WEARABLE_HELMET = 0x0710;
-        public static final int WEARABLE_GLASSES = 0x0714;
-
-        // Devices in the TOY major class
-        public static final int TOY_UNCATEGORIZED = 0x0800;
-        public static final int TOY_ROBOT = 0x0804;
-        public static final int TOY_VEHICLE = 0x0808;
-        public static final int TOY_DOLL_ACTION_FIGURE = 0x080C;
-        public static final int TOY_CONTROLLER = 0x0810;
-        public static final int TOY_GAME = 0x0814;
-
-        // Devices in the HEALTH major class
-        public static final int HEALTH_UNCATEGORIZED = 0x0900;
-        public static final int HEALTH_BLOOD_PRESSURE = 0x0904;
-        public static final int HEALTH_THERMOMETER = 0x0908;
-        public static final int HEALTH_WEIGHING = 0x090C;
-        public static final int HEALTH_GLUCOSE = 0x0910;
-        public static final int HEALTH_PULSE_OXIMETER = 0x0914;
-        public static final int HEALTH_PULSE_RATE = 0x0918;
-        public static final int HEALTH_DATA_DISPLAY = 0x091C;
-
-        // Devices in PERIPHERAL major class
-        /**
-         * @hide
-         */
-        public static final int PERIPHERAL_NON_KEYBOARD_NON_POINTING = 0x0500;
-        /**
-         * @hide
-         */
-        public static final int PERIPHERAL_KEYBOARD = 0x0540;
-        /**
-         * @hide
-         */
-        public static final int PERIPHERAL_POINTING = 0x0580;
-        /**
-         * @hide
-         */
-        public static final int PERIPHERAL_KEYBOARD_POINTING = 0x05C0;
-    }
-
-    /**
-     * Return the major device class component of this {@link BluetoothClass}.
-     * <p>Values returned from this function can be compared with the
-     * public constants in {@link BluetoothClass.Device.Major} to determine
-     * which major class is encoded in this Bluetooth class.
-     *
-     * @return major device class component
-     */
-    public int getMajorDeviceClass() {
-        return (mClass & Device.Major.BITMASK);
-    }
-
-    /**
-     * Return the (major and minor) device class component of this
-     * {@link BluetoothClass}.
-     * <p>Values returned from this function can be compared with the
-     * public constants in {@link BluetoothClass.Device} to determine which
-     * device class is encoded in this Bluetooth class.
-     *
-     * @return device class component
-     */
-    public int getDeviceClass() {
-        return (mClass & Device.BITMASK);
-    }
-
-    /**
-     * Return the Bluetooth Class of Device (CoD) value including the
-     * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
-     * minor device fields.
-     *
-     * <p>This value is an integer representation of Bluetooth CoD as in
-     * Bluetooth specification.
-     *
-     * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
-     *
-     * @hide
-     */
-    @TestApi
-    public int getClassOfDevice() {
-        return mClass;
-    }
-
-    /**
-     * Return the Bluetooth Class of Device (CoD) value including the
-     * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and
-     * minor device fields.
-     *
-     * <p>This value is a byte array representation of Bluetooth CoD as in
-     * Bluetooth specification.
-     *
-     * <p>Bluetooth COD information is 3 bytes, but stored as an int. Hence the
-     * MSB is useless and needs to be thrown away. The lower 3 bytes are
-     * converted into a byte array MSB to LSB. Hence, using BIG_ENDIAN.
-     *
-     * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a>
-     *
-     * @hide
-     */
-    public byte[] getClassOfDeviceBytes() {
-        byte[] bytes = ByteBuffer.allocate(4)
-                .order(ByteOrder.BIG_ENDIAN)
-                .putInt(mClass)
-                .array();
-
-        // Discard the top byte
-        return Arrays.copyOfRange(bytes, 1, bytes.length);
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public static final int PROFILE_HEADSET = 0;
-    /** @hide */
-    @UnsupportedAppUsage
-    public static final int PROFILE_A2DP = 1;
-    /** @hide */
-    public static final int PROFILE_OPP = 2;
-    /** @hide */
-    public static final int PROFILE_HID = 3;
-    /** @hide */
-    public static final int PROFILE_PANU = 4;
-    /** @hide */
-    public static final int PROFILE_NAP = 5;
-    /** @hide */
-    public static final int PROFILE_A2DP_SINK = 6;
-
-    /**
-     * Check class bits for possible bluetooth profile support.
-     * This is a simple heuristic that tries to guess if a device with the
-     * given class bits might support specified profile. It is not accurate for all
-     * devices. It tries to err on the side of false positives.
-     *
-     * @param profile The profile to be checked
-     * @return True if this device might support specified profile.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public boolean doesClassMatch(int profile) {
-        if (profile == PROFILE_A2DP) {
-            if (hasService(Service.RENDER)) {
-                return true;
-            }
-            // By the A2DP spec, sinks must indicate the RENDER service.
-            // However we found some that do not (Chordette). So lets also
-            // match on some other class bits.
-            switch (getDeviceClass()) {
-                case Device.AUDIO_VIDEO_HIFI_AUDIO:
-                case Device.AUDIO_VIDEO_HEADPHONES:
-                case Device.AUDIO_VIDEO_LOUDSPEAKER:
-                case Device.AUDIO_VIDEO_CAR_AUDIO:
-                    return true;
-                default:
-                    return false;
-            }
-        } else if (profile == PROFILE_A2DP_SINK) {
-            if (hasService(Service.CAPTURE)) {
-                return true;
-            }
-            // By the A2DP spec, srcs must indicate the CAPTURE service.
-            // However if some device that do not, we try to
-            // match on some other class bits.
-            switch (getDeviceClass()) {
-                case Device.AUDIO_VIDEO_HIFI_AUDIO:
-                case Device.AUDIO_VIDEO_SET_TOP_BOX:
-                case Device.AUDIO_VIDEO_VCR:
-                    return true;
-                default:
-                    return false;
-            }
-        } else if (profile == PROFILE_HEADSET) {
-            // The render service class is required by the spec for HFP, so is a
-            // pretty good signal
-            if (hasService(Service.RENDER)) {
-                return true;
-            }
-            // Just in case they forgot the render service class
-            switch (getDeviceClass()) {
-                case Device.AUDIO_VIDEO_HANDSFREE:
-                case Device.AUDIO_VIDEO_WEARABLE_HEADSET:
-                case Device.AUDIO_VIDEO_CAR_AUDIO:
-                    return true;
-                default:
-                    return false;
-            }
-        } else if (profile == PROFILE_OPP) {
-            if (hasService(Service.OBJECT_TRANSFER)) {
-                return true;
-            }
-
-            switch (getDeviceClass()) {
-                case Device.COMPUTER_UNCATEGORIZED:
-                case Device.COMPUTER_DESKTOP:
-                case Device.COMPUTER_SERVER:
-                case Device.COMPUTER_LAPTOP:
-                case Device.COMPUTER_HANDHELD_PC_PDA:
-                case Device.COMPUTER_PALM_SIZE_PC_PDA:
-                case Device.COMPUTER_WEARABLE:
-                case Device.PHONE_UNCATEGORIZED:
-                case Device.PHONE_CELLULAR:
-                case Device.PHONE_CORDLESS:
-                case Device.PHONE_SMART:
-                case Device.PHONE_MODEM_OR_GATEWAY:
-                case Device.PHONE_ISDN:
-                    return true;
-                default:
-                    return false;
-            }
-        } else if (profile == PROFILE_HID) {
-            return getMajorDeviceClass() == Device.Major.PERIPHERAL;
-        } else if (profile == PROFILE_PANU || profile == PROFILE_NAP) {
-            // No good way to distinguish between the two, based on class bits.
-            if (hasService(Service.NETWORKING)) {
-                return true;
-            }
-            return getMajorDeviceClass() == Device.Major.NETWORKING;
-        } else {
-            return false;
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
deleted file mode 100644
index 9a4151a..0000000
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Represents the codec configuration for a Bluetooth A2DP source device.
- * <p>Contains the source codec type, the codec priority, the codec sample
- * rate, the codec bits per sample, and the codec channel mode.
- * <p>The source codec type values are the same as those supported by the
- * device hardware.
- *
- * {@see BluetoothA2dp}
- */
-public final class BluetoothCodecConfig implements Parcelable {
-    /** @hide */
-    @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
-            SOURCE_CODEC_TYPE_SBC,
-            SOURCE_CODEC_TYPE_AAC,
-            SOURCE_CODEC_TYPE_APTX,
-            SOURCE_CODEC_TYPE_APTX_HD,
-            SOURCE_CODEC_TYPE_LDAC,
-            SOURCE_CODEC_TYPE_INVALID
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SourceCodecType {}
-
-    /**
-     * Source codec type SBC. This is the mandatory source codec
-     * type.
-     */
-    public static final int SOURCE_CODEC_TYPE_SBC = 0;
-
-    /**
-     * Source codec type AAC.
-     */
-    public static final int SOURCE_CODEC_TYPE_AAC = 1;
-
-    /**
-     * Source codec type APTX.
-     */
-    public static final int SOURCE_CODEC_TYPE_APTX = 2;
-
-    /**
-     * Source codec type APTX HD.
-     */
-    public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
-
-    /**
-     * Source codec type LDAC.
-     */
-    public static final int SOURCE_CODEC_TYPE_LDAC = 4;
-
-    /**
-     * Source codec type invalid. This is the default value used for codec
-     * type.
-     */
-    public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
-
-    /**
-     * Represents the count of valid source codec types. Can be accessed via
-     * {@link #getMaxCodecType}.
-     */
-    private static final int SOURCE_CODEC_TYPE_MAX = 5;
-
-    /** @hide */
-    @IntDef(prefix = "CODEC_PRIORITY_", value = {
-            CODEC_PRIORITY_DISABLED,
-            CODEC_PRIORITY_DEFAULT,
-            CODEC_PRIORITY_HIGHEST
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface CodecPriority {}
-
-    /**
-     * Codec priority disabled.
-     * Used to indicate that this codec is disabled and should not be used.
-     */
-    public static final int CODEC_PRIORITY_DISABLED = -1;
-
-    /**
-     * Codec priority default.
-     * Default value used for codec priority.
-     */
-    public static final int CODEC_PRIORITY_DEFAULT = 0;
-
-    /**
-     * Codec priority highest.
-     * Used to indicate the highest priority a codec can have.
-     */
-    public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
-
-    /** @hide */
-    @IntDef(prefix = "SAMPLE_RATE_", value = {
-            SAMPLE_RATE_NONE,
-            SAMPLE_RATE_44100,
-            SAMPLE_RATE_48000,
-            SAMPLE_RATE_88200,
-            SAMPLE_RATE_96000,
-            SAMPLE_RATE_176400,
-            SAMPLE_RATE_192000
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SampleRate {}
-
-    /**
-     * Codec sample rate 0 Hz. Default value used for
-     * codec sample rate.
-     */
-    public static final int SAMPLE_RATE_NONE = 0;
-
-    /**
-     * Codec sample rate 44100 Hz.
-     */
-    public static final int SAMPLE_RATE_44100 = 0x1 << 0;
-
-    /**
-     * Codec sample rate 48000 Hz.
-     */
-    public static final int SAMPLE_RATE_48000 = 0x1 << 1;
-
-    /**
-     * Codec sample rate 88200 Hz.
-     */
-    public static final int SAMPLE_RATE_88200 = 0x1 << 2;
-
-    /**
-     * Codec sample rate 96000 Hz.
-     */
-    public static final int SAMPLE_RATE_96000 = 0x1 << 3;
-
-    /**
-     * Codec sample rate 176400 Hz.
-     */
-    public static final int SAMPLE_RATE_176400 = 0x1 << 4;
-
-    /**
-     * Codec sample rate 192000 Hz.
-     */
-    public static final int SAMPLE_RATE_192000 = 0x1 << 5;
-
-    /** @hide */
-    @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
-            BITS_PER_SAMPLE_NONE,
-            BITS_PER_SAMPLE_16,
-            BITS_PER_SAMPLE_24,
-            BITS_PER_SAMPLE_32
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface BitsPerSample {}
-
-    /**
-     * Codec bits per sample 0. Default value of the codec
-     * bits per sample.
-     */
-    public static final int BITS_PER_SAMPLE_NONE = 0;
-
-    /**
-     * Codec bits per sample 16.
-     */
-    public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
-
-    /**
-     * Codec bits per sample 24.
-     */
-    public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
-
-    /**
-     * Codec bits per sample 32.
-     */
-    public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
-
-    /** @hide */
-    @IntDef(prefix = "CHANNEL_MODE_", value = {
-            CHANNEL_MODE_NONE,
-            CHANNEL_MODE_MONO,
-            CHANNEL_MODE_STEREO
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ChannelMode {}
-
-    /**
-     * Codec channel mode NONE. Default value of the
-     * codec channel mode.
-     */
-    public static final int CHANNEL_MODE_NONE = 0;
-
-    /**
-     * Codec channel mode MONO.
-     */
-    public static final int CHANNEL_MODE_MONO = 0x1 << 0;
-
-    /**
-     * Codec channel mode STEREO.
-     */
-    public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
-
-    private final @SourceCodecType int mCodecType;
-    private @CodecPriority int mCodecPriority;
-    private final @SampleRate int mSampleRate;
-    private final @BitsPerSample int mBitsPerSample;
-    private final @ChannelMode int mChannelMode;
-    private final long mCodecSpecific1;
-    private final long mCodecSpecific2;
-    private final long mCodecSpecific3;
-    private final long mCodecSpecific4;
-
-    /**
-     * Creates a new BluetoothCodecConfig.
-     *
-     * @param codecType the source codec type
-     * @param codecPriority the priority of this codec
-     * @param sampleRate the codec sample rate
-     * @param bitsPerSample the bits per sample of this codec
-     * @param channelMode the channel mode of this codec
-     * @param codecSpecific1 the specific value 1
-     * @param codecSpecific2 the specific value 2
-     * @param codecSpecific3 the specific value 3
-     * @param codecSpecific4 the specific value 4
-     * values to 0.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
-            @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
-            @ChannelMode int channelMode, long codecSpecific1,
-            long codecSpecific2, long codecSpecific3,
-            long codecSpecific4) {
-        mCodecType = codecType;
-        mCodecPriority = codecPriority;
-        mSampleRate = sampleRate;
-        mBitsPerSample = bitsPerSample;
-        mChannelMode = channelMode;
-        mCodecSpecific1 = codecSpecific1;
-        mCodecSpecific2 = codecSpecific2;
-        mCodecSpecific3 = codecSpecific3;
-        mCodecSpecific4 = codecSpecific4;
-    }
-
-    /**
-     * Creates a new BluetoothCodecConfig.
-     * <p> By default, the codec priority will be set
-     * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
-     * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
-     * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
-     * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
-     * values to 0.
-     *
-     * @param codecType the source codec type
-     */
-    public BluetoothCodecConfig(@SourceCodecType int codecType) {
-        this(codecType, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                BluetoothCodecConfig.SAMPLE_RATE_NONE,
-                BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
-                BluetoothCodecConfig.CHANNEL_MODE_NONE, 0, 0, 0, 0);
-    }
-
-    private BluetoothCodecConfig(Parcel in) {
-        mCodecType = in.readInt();
-        mCodecPriority = in.readInt();
-        mSampleRate = in.readInt();
-        mBitsPerSample = in.readInt();
-        mChannelMode = in.readInt();
-        mCodecSpecific1 = in.readLong();
-        mCodecSpecific2 = in.readLong();
-        mCodecSpecific3 = in.readLong();
-        mCodecSpecific4 = in.readLong();
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (o instanceof BluetoothCodecConfig) {
-            BluetoothCodecConfig other = (BluetoothCodecConfig) o;
-            return (other.mCodecType == mCodecType
-                    && other.mCodecPriority == mCodecPriority
-                    && other.mSampleRate == mSampleRate
-                    && other.mBitsPerSample == mBitsPerSample
-                    && other.mChannelMode == mChannelMode
-                    && other.mCodecSpecific1 == mCodecSpecific1
-                    && other.mCodecSpecific2 == mCodecSpecific2
-                    && other.mCodecSpecific3 == mCodecSpecific3
-                    && other.mCodecSpecific4 == mCodecSpecific4);
-        }
-        return false;
-    }
-
-    /**
-     * Returns a hash representation of this BluetoothCodecConfig
-     * based on all the config values.
-     */
-    @Override
-    public int hashCode() {
-        return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
-                mBitsPerSample, mChannelMode, mCodecSpecific1,
-                mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
-    }
-
-    /**
-     * Adds capability string to an existing string.
-     *
-     * @param prevStr the previous string with the capabilities. Can be a {@code null} pointer
-     * @param capStr the capability string to append to prevStr argument
-     * @return the result string in the form "prevStr|capStr"
-     */
-    private static String appendCapabilityToString(@Nullable String prevStr,
-            @NonNull String capStr) {
-        if (prevStr == null) {
-            return capStr;
-        }
-        return prevStr + "|" + capStr;
-    }
-
-    /**
-     * Returns a {@link String} that describes each BluetoothCodecConfig parameter
-     * current value.
-     */
-    @Override
-    public String toString() {
-        String sampleRateStr = null;
-        if (mSampleRate == SAMPLE_RATE_NONE) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
-        }
-        if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
-        }
-        if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
-        }
-        if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
-        }
-        if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
-        }
-        if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
-        }
-        if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
-            sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
-        }
-
-        String bitsPerSampleStr = null;
-        if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
-            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
-        }
-        if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
-            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
-        }
-        if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
-            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
-        }
-        if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
-            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
-        }
-
-        String channelModeStr = null;
-        if (mChannelMode == CHANNEL_MODE_NONE) {
-            channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
-        }
-        if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
-            channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
-        }
-        if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
-            channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
-        }
-
-        return "{codecName:" + getCodecName()
-                + ",mCodecType:" + mCodecType
-                + ",mCodecPriority:" + mCodecPriority
-                + ",mSampleRate:" + String.format("0x%x", mSampleRate)
-                + "(" + sampleRateStr + ")"
-                + ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample)
-                + "(" + bitsPerSampleStr + ")"
-                + ",mChannelMode:" + String.format("0x%x", mChannelMode)
-                + "(" + channelModeStr + ")"
-                + ",mCodecSpecific1:" + mCodecSpecific1
-                + ",mCodecSpecific2:" + mCodecSpecific2
-                + ",mCodecSpecific3:" + mCodecSpecific3
-                + ",mCodecSpecific4:" + mCodecSpecific4 + "}";
-    }
-
-    /**
-     * @return 0
-     * @hide
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecConfig> CREATOR =
-            new Parcelable.Creator<BluetoothCodecConfig>() {
-                public BluetoothCodecConfig createFromParcel(Parcel in) {
-                    return new BluetoothCodecConfig(in);
-                }
-
-                public BluetoothCodecConfig[] newArray(int size) {
-                    return new BluetoothCodecConfig[size];
-                }
-            };
-
-    /**
-     * Flattens the object to a parcel
-     *
-     * @param out The Parcel in which the object should be written
-     * @param flags Additional flags about how the object should be written
-     *
-     * @hide
-     */
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mCodecType);
-        out.writeInt(mCodecPriority);
-        out.writeInt(mSampleRate);
-        out.writeInt(mBitsPerSample);
-        out.writeInt(mChannelMode);
-        out.writeLong(mCodecSpecific1);
-        out.writeLong(mCodecSpecific2);
-        out.writeLong(mCodecSpecific3);
-        out.writeLong(mCodecSpecific4);
-    }
-
-    /**
-     * Returns the codec name converted to {@link String}.
-     * @hide
-     */
-    public @NonNull String getCodecName() {
-        switch (mCodecType) {
-            case SOURCE_CODEC_TYPE_SBC:
-                return "SBC";
-            case SOURCE_CODEC_TYPE_AAC:
-                return "AAC";
-            case SOURCE_CODEC_TYPE_APTX:
-                return "aptX";
-            case SOURCE_CODEC_TYPE_APTX_HD:
-                return "aptX HD";
-            case SOURCE_CODEC_TYPE_LDAC:
-                return "LDAC";
-            case SOURCE_CODEC_TYPE_INVALID:
-                return "INVALID CODEC";
-            default:
-                break;
-        }
-        return "UNKNOWN CODEC(" + mCodecType + ")";
-    }
-
-    /**
-     * Returns the source codec type of this config.
-     */
-    public @SourceCodecType int getCodecType() {
-        return mCodecType;
-    }
-
-    /**
-     * Returns the valid codec types count.
-     */
-    public static int getMaxCodecType() {
-        return SOURCE_CODEC_TYPE_MAX;
-    }
-
-    /**
-     * Checks whether the codec is mandatory.
-     * <p> The actual mandatory codec type for Android Bluetooth audio is SBC.
-     * See {@link #SOURCE_CODEC_TYPE_SBC}.
-     *
-     * @return {@code true} if the codec is mandatory, {@code false} otherwise
-     * @hide
-     */
-    public boolean isMandatoryCodec() {
-        return mCodecType == SOURCE_CODEC_TYPE_SBC;
-    }
-
-    /**
-     * Returns the codec selection priority.
-     * <p>The codec selection priority is relative to other codecs: larger value
-     * means higher priority.
-     */
-    public @CodecPriority int getCodecPriority() {
-        return mCodecPriority;
-    }
-
-    /**
-     * Sets the codec selection priority.
-     * <p>The codec selection priority is relative to other codecs: larger value
-     * means higher priority.
-     *
-     * @param codecPriority the priority this codec should have
-     * @hide
-     */
-    public void setCodecPriority(@CodecPriority int codecPriority) {
-        mCodecPriority = codecPriority;
-    }
-
-    /**
-     * Returns the codec sample rate. The value can be a bitmask with all
-     * supported sample rates.
-     */
-    public @SampleRate int getSampleRate() {
-        return mSampleRate;
-    }
-
-    /**
-     * Returns the codec bits per sample. The value can be a bitmask with all
-     * bits per sample supported.
-     */
-    public @BitsPerSample int getBitsPerSample() {
-        return mBitsPerSample;
-    }
-
-    /**
-     * Returns the codec channel mode. The value can be a bitmask with all
-     * supported channel modes.
-     */
-    public @ChannelMode int getChannelMode() {
-        return mChannelMode;
-    }
-
-    /**
-     * Returns the codec specific value1.
-     */
-    public long getCodecSpecific1() {
-        return mCodecSpecific1;
-    }
-
-    /**
-     * Returns the codec specific value2.
-     */
-    public long getCodecSpecific2() {
-        return mCodecSpecific2;
-    }
-
-    /**
-     * Returns the codec specific value3.
-     */
-    public long getCodecSpecific3() {
-        return mCodecSpecific3;
-    }
-
-    /**
-     * Returns the codec specific value4.
-     */
-    public long getCodecSpecific4() {
-        return mCodecSpecific4;
-    }
-
-    /**
-     * Checks whether a value set presented by a bitmask has zero or single bit
-     *
-     * @param valueSet the value set presented by a bitmask
-     * @return {@code true} if the valueSet contains zero or single bit, {@code false} otherwise
-     * @hide
-     */
-    private static boolean hasSingleBit(int valueSet) {
-        return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
-    }
-
-    /**
-     * Returns whether the object contains none or single sample rate.
-     * @hide
-     */
-    public boolean hasSingleSampleRate() {
-        return hasSingleBit(mSampleRate);
-    }
-
-    /**
-     * Returns whether the object contains none or single bits per sample.
-     * @hide
-     */
-    public boolean hasSingleBitsPerSample() {
-        return hasSingleBit(mBitsPerSample);
-    }
-
-    /**
-     * Returns whether the object contains none or single channel mode.
-     * @hide
-     */
-    public boolean hasSingleChannelMode() {
-        return hasSingleBit(mChannelMode);
-    }
-
-    /**
-     * Checks whether the audio feeding parameters are the same.
-     *
-     * @param other the codec config to compare against
-     * @return {@code true} if the audio feeding parameters are same, {@code false} otherwise
-     * @hide
-     */
-    public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
-        return (other != null && other.mSampleRate == mSampleRate
-                && other.mBitsPerSample == mBitsPerSample
-                && other.mChannelMode == mChannelMode);
-    }
-
-    /**
-     * Checks whether another codec config has the similar feeding parameters.
-     * Any parameters with NONE value will be considered to be a wildcard matching.
-     *
-     * @param other the codec config to compare against
-     * @return {@code true} if the audio feeding parameters are similar, {@code false} otherwise
-     * @hide
-     */
-    public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
-        if (other == null || mCodecType != other.mCodecType) {
-            return false;
-        }
-        int sampleRate = other.mSampleRate;
-        if (mSampleRate == SAMPLE_RATE_NONE
-                || sampleRate == SAMPLE_RATE_NONE) {
-            sampleRate = mSampleRate;
-        }
-        int bitsPerSample = other.mBitsPerSample;
-        if (mBitsPerSample == BITS_PER_SAMPLE_NONE
-                || bitsPerSample == BITS_PER_SAMPLE_NONE) {
-            bitsPerSample = mBitsPerSample;
-        }
-        int channelMode = other.mChannelMode;
-        if (mChannelMode == CHANNEL_MODE_NONE
-                || channelMode == CHANNEL_MODE_NONE) {
-            channelMode = mChannelMode;
-        }
-        return sameAudioFeedingParameters(new BluetoothCodecConfig(
-                mCodecType, /* priority */ 0, sampleRate, bitsPerSample, channelMode,
-                /* specific1 */ 0, /* specific2 */ 0, /* specific3 */ 0,
-                /* specific4 */ 0));
-    }
-
-    /**
-     * Checks whether the codec specific parameters are the same.
-     * <p> Currently, only AAC VBR and LDAC Playback Quality on CodecSpecific1
-     * are compared.
-     *
-     * @param other the codec config to compare against
-     * @return {@code true} if the codec specific parameters are the same, {@code false} otherwise
-     * @hide
-     */
-    public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
-        if (other == null && mCodecType != other.mCodecType) {
-            return false;
-        }
-        switch (mCodecType) {
-            case SOURCE_CODEC_TYPE_AAC:
-            case SOURCE_CODEC_TYPE_LDAC:
-                if (mCodecSpecific1 != other.mCodecSpecific1) {
-                    return false;
-                }
-            default:
-                return true;
-        }
-    }
-
-    /**
-     * Builder for {@link BluetoothCodecConfig}.
-     * <p> By default, the codec type will be set to
-     * {@link BluetoothCodecConfig#SOURCE_CODEC_TYPE_INVALID}, the codec priority
-     * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
-     * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
-     * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
-     * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
-     * values to 0.
-     */
-    public static final class Builder {
-        private int mCodecType = BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
-        private int mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
-        private int mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
-        private int mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
-        private int mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
-        private long mCodecSpecific1 = 0;
-        private long mCodecSpecific2 = 0;
-        private long mCodecSpecific3 = 0;
-        private long mCodecSpecific4 = 0;
-
-        /**
-         * Set codec type for Bluetooth codec config.
-         *
-         * @param codecType of this codec
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
-            mCodecType = codecType;
-            return this;
-        }
-
-        /**
-         * Set codec priority for Bluetooth codec config.
-         *
-         * @param codecPriority of this codec
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecPriority(@CodecPriority int codecPriority) {
-            mCodecPriority = codecPriority;
-            return this;
-        }
-
-        /**
-         * Set sample rate for Bluetooth codec config.
-         *
-         * @param sampleRate of this codec
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setSampleRate(@SampleRate int sampleRate) {
-            mSampleRate = sampleRate;
-            return this;
-        }
-
-        /**
-         * Set the bits per sample for Bluetooth codec config.
-         *
-         * @param bitsPerSample of this codec
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setBitsPerSample(@BitsPerSample int bitsPerSample) {
-            mBitsPerSample = bitsPerSample;
-            return this;
-        }
-
-        /**
-         * Set the channel mode for Bluetooth codec config.
-         *
-         * @param channelMode of this codec
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setChannelMode(@ChannelMode int channelMode) {
-            mChannelMode = channelMode;
-            return this;
-        }
-
-        /**
-         * Set the first codec specific values for Bluetooth codec config.
-         *
-         * @param codecSpecific1 codec specific value or 0 if default
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecSpecific1(long codecSpecific1) {
-            mCodecSpecific1 = codecSpecific1;
-            return this;
-        }
-
-        /**
-         * Set the second codec specific values for Bluetooth codec config.
-         *
-         * @param codecSpecific2 codec specific value or 0 if default
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecSpecific2(long codecSpecific2) {
-            mCodecSpecific2 = codecSpecific2;
-            return this;
-        }
-
-        /**
-         * Set the third codec specific values for Bluetooth codec config.
-         *
-         * @param codecSpecific3 codec specific value or 0 if default
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecSpecific3(long codecSpecific3) {
-            mCodecSpecific3 = codecSpecific3;
-            return this;
-        }
-
-        /**
-         * Set the fourth codec specific values for Bluetooth codec config.
-         *
-         * @param codecSpecific4 codec specific value or 0 if default
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecSpecific4(long codecSpecific4) {
-            mCodecSpecific4 = codecSpecific4;
-            return this;
-        }
-
-        /**
-         * Build {@link BluetoothCodecConfig}.
-         * @return new BluetoothCodecConfig built
-         */
-        public @NonNull BluetoothCodecConfig build() {
-            return new BluetoothCodecConfig(mCodecType, mCodecPriority,
-                    mSampleRate, mBitsPerSample,
-                    mChannelMode, mCodecSpecific1,
-                    mCodecSpecific2, mCodecSpecific3,
-                    mCodecSpecific4);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
deleted file mode 100644
index 02606fe..0000000
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Represents the codec status (configuration and capability) for a Bluetooth
- * A2DP source device.
- *
- * {@see BluetoothA2dp}
- */
-public final class BluetoothCodecStatus implements Parcelable {
-    /**
-     * Extra for the codec configuration intents of the individual profiles.
-     *
-     * This extra represents the current codec status of the A2DP
-     * profile.
-     */
-    public static final String EXTRA_CODEC_STATUS =
-            "android.bluetooth.extra.CODEC_STATUS";
-
-    private final @Nullable BluetoothCodecConfig mCodecConfig;
-    private final @Nullable List<BluetoothCodecConfig> mCodecsLocalCapabilities;
-    private final @Nullable List<BluetoothCodecConfig> mCodecsSelectableCapabilities;
-
-    public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
-            @Nullable List<BluetoothCodecConfig> codecsLocalCapabilities,
-            @Nullable List<BluetoothCodecConfig> codecsSelectableCapabilities) {
-        mCodecConfig = codecConfig;
-        mCodecsLocalCapabilities = codecsLocalCapabilities;
-        mCodecsSelectableCapabilities = codecsSelectableCapabilities;
-    }
-
-    private BluetoothCodecStatus(Parcel in) {
-        mCodecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
-        mCodecsLocalCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
-        mCodecsSelectableCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (o instanceof BluetoothCodecStatus) {
-            BluetoothCodecStatus other = (BluetoothCodecStatus) o;
-            return (Objects.equals(other.mCodecConfig, mCodecConfig)
-                    && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities)
-                    && sameCapabilities(other.mCodecsSelectableCapabilities,
-                    mCodecsSelectableCapabilities));
-        }
-        return false;
-    }
-
-    /**
-     * Checks whether two lists of capabilities contain same capabilities.
-     * The order of the capabilities in each list is ignored.
-     *
-     * @param c1 the first list of capabilities to compare
-     * @param c2 the second list of capabilities to compare
-     * @return {@code true} if both lists contain same capabilities
-     */
-    private static boolean sameCapabilities(@Nullable List<BluetoothCodecConfig> c1,
-                                           @Nullable List<BluetoothCodecConfig> c2) {
-        if (c1 == null) {
-            return (c2 == null);
-        }
-        if (c2 == null) {
-            return false;
-        }
-        if (c1.size() != c2.size()) {
-            return false;
-        }
-        return c1.containsAll(c2);
-    }
-
-    /**
-     * Checks whether the codec config matches the selectable capabilities.
-     * Any parameters of the codec config with NONE value will be considered a wildcard matching.
-     *
-     * @param codecConfig the codec config to compare against
-     * @return {@code true} if the codec config matches, {@code false} otherwise
-     */
-    public boolean isCodecConfigSelectable(@Nullable BluetoothCodecConfig codecConfig) {
-        if (codecConfig == null || !codecConfig.hasSingleSampleRate()
-                || !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) {
-            return false;
-        }
-        for (BluetoothCodecConfig selectableConfig : mCodecsSelectableCapabilities) {
-            if (codecConfig.getCodecType() != selectableConfig.getCodecType()) {
-                continue;
-            }
-            int sampleRate = codecConfig.getSampleRate();
-            if ((sampleRate & selectableConfig.getSampleRate()) == 0
-                    && sampleRate != BluetoothCodecConfig.SAMPLE_RATE_NONE) {
-                continue;
-            }
-            int bitsPerSample = codecConfig.getBitsPerSample();
-            if ((bitsPerSample & selectableConfig.getBitsPerSample()) == 0
-                    && bitsPerSample != BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
-                continue;
-            }
-            int channelMode = codecConfig.getChannelMode();
-            if ((channelMode & selectableConfig.getChannelMode()) == 0
-                    && channelMode != BluetoothCodecConfig.CHANNEL_MODE_NONE) {
-                continue;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Returns a hash based on the codec config and local capabilities.
-     */
-    @Override
-    public int hashCode() {
-        return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
-                mCodecsLocalCapabilities);
-    }
-
-    /**
-     * Returns a {@link String} that describes each BluetoothCodecStatus parameter
-     * current value.
-     */
-    @Override
-    public String toString() {
-        return "{mCodecConfig:" + mCodecConfig
-                + ",mCodecsLocalCapabilities:" + mCodecsLocalCapabilities
-                + ",mCodecsSelectableCapabilities:" + mCodecsSelectableCapabilities
-                + "}";
-    }
-
-    /**
-     * @return 0
-     * @hide
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecStatus> CREATOR =
-            new Parcelable.Creator<BluetoothCodecStatus>() {
-                public BluetoothCodecStatus createFromParcel(Parcel in) {
-                    return new BluetoothCodecStatus(in);
-                }
-
-                public BluetoothCodecStatus[] newArray(int size) {
-                    return new BluetoothCodecStatus[size];
-                }
-            };
-
-    /**
-     * Flattens the object to a parcel.
-     *
-     * @param out The Parcel in which the object should be written
-     * @param flags Additional flags about how the object should be written
-     */
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeTypedObject(mCodecConfig, 0);
-        out.writeTypedList(mCodecsLocalCapabilities);
-        out.writeTypedList(mCodecsSelectableCapabilities);
-    }
-
-    /**
-     * Returns the current codec configuration.
-     */
-    public @Nullable BluetoothCodecConfig getCodecConfig() {
-        return mCodecConfig;
-    }
-
-    /**
-     * Returns the codecs local capabilities.
-     */
-    public @NonNull List<BluetoothCodecConfig> getCodecsLocalCapabilities() {
-        return (mCodecsLocalCapabilities == null)
-                ? Collections.emptyList() : mCodecsLocalCapabilities;
-    }
-
-    /**
-     * Returns the codecs selectable capabilities.
-     */
-    public @NonNull List<BluetoothCodecConfig> getCodecsSelectableCapabilities() {
-        return (mCodecsSelectableCapabilities == null)
-                ? Collections.emptyList() : mCodecsSelectableCapabilities;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
deleted file mode 100644
index ba57ec4..0000000
--- a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * 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 static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-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.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-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;
-import java.util.concurrent.TimeoutException;
-
-/**
- * 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_CONNECT)
-    @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 final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    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(service);
-                }
-            };
-
-    /**
-     * Create a BluetoothCsipSetCoordinator proxy object for interacting with the local
-     * Bluetooth CSIS service.
-     */
-    /*package*/ BluetoothCsipSetCoordinator(Context context, ServiceListener listener, BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        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();
-        final UUID defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            IBluetoothCsipSetCoordinatorLockCallback delegate = null;
-            if ((executor != null) && (cb != null)) {
-                delegate = new BluetoothCsipSetCoordinatorLockCallbackDelegate(executor, cb);
-            }
-            try {
-                final SynchronousResultReceiver<ParcelUuid> recv = new SynchronousResultReceiver();
-                service.groupLock(groupId, delegate, mAttributionSource, recv);
-                final ParcelUuid ret = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-                return ret == null ? defaultValue : ret.getUuid();
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.groupUnlock(new ParcelUuid(lockUuid), mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-                return true;
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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();
-        final Map defaultValue = new HashMap<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Map> recv = new SynchronousResultReceiver();
-                service.getGroupUuidMapByDevice(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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();
-        final List<Integer> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<Integer>> recv =
-                        new SynchronousResultReceiver();
-                service.getAllGroupIds(uuid, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothCsipSetCoordinator service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public
-    @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[] states) {
-        if (VDBG) log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")");
-        final IBluetoothCsipSetCoordinator service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public
-    @BluetoothProfile.BtProfileState int getConnectionState(@Nullable BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        final IBluetoothCsipSetCoordinator service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    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
deleted file mode 100644
index 93f0268..0000000
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ /dev/null
@@ -1,2830 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.app.PropertyInvalidatedCache;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.companion.AssociationRequest;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.UUID;
-
-/**
- * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you
- * create a connection with the respective device or query information about
- * it, such as the name, address, class, and bonding state.
- *
- * <p>This class is really just a thin wrapper for a Bluetooth hardware
- * address. Objects of this class are immutable. Operations on this class
- * are performed on the remote Bluetooth hardware address, using the
- * {@link BluetoothAdapter} that was used to create this {@link
- * BluetoothDevice}.
- *
- * <p>To get a {@link BluetoothDevice}, use
- * {@link BluetoothAdapter#getRemoteDevice(String)
- * BluetoothAdapter.getRemoteDevice(String)} to create one representing a device
- * of a known MAC address (which you can get through device discovery with
- * {@link BluetoothAdapter}) or get one from the set of bonded devices
- * returned by {@link BluetoothAdapter#getBondedDevices()
- * BluetoothAdapter.getBondedDevices()}. You can then open a
- * {@link BluetoothSocket} for communication with the remote device, using
- * {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using
- * {@link #createL2capChannel(int)} over Bluetooth LE.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about using Bluetooth, read the <a href=
- * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
- * guide.
- * </p>
- * </div>
- *
- * {@see BluetoothAdapter}
- * {@see BluetoothSocket}
- */
-public final class BluetoothDevice implements Parcelable, Attributable {
-    private static final String TAG = "BluetoothDevice";
-    private static final boolean DBG = false;
-
-    /**
-     * Connection state bitmask as returned by getConnectionState.
-     */
-    private static final int CONNECTION_STATE_DISCONNECTED = 0;
-    private static final int CONNECTION_STATE_CONNECTED = 1;
-    private static final int CONNECTION_STATE_ENCRYPTED_BREDR = 2;
-    private static final int CONNECTION_STATE_ENCRYPTED_LE = 4;
-
-    /**
-     * Sentinel error value for this class. Guaranteed to not equal any other
-     * integer constant in this class. Provided as a convenience for functions
-     * that require a sentinel error value, for example:
-     * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
-     * BluetoothDevice.ERROR)</code>
-     */
-    public static final int ERROR = Integer.MIN_VALUE;
-
-    /**
-     * Broadcast Action: Remote device discovered.
-     * <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} and/or {@link #EXTRA_IS_COORDINATED_SET_MEMBER} if they are available.
-     */
-    // TODO: Change API to not broadcast RSSI if not available (incoming connection)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_FOUND =
-            "android.bluetooth.device.action.FOUND";
-
-    /**
-     * Broadcast Action: Bluetooth class of a remote device has changed.
-     * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
-     * #EXTRA_CLASS}.
-     * {@see BluetoothClass}
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CLASS_CHANGED =
-            "android.bluetooth.device.action.CLASS_CHANGED";
-
-    /**
-     * Broadcast Action: Indicates a low level (ACL) connection has been
-     * established with a remote device.
-     * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
-     * <p>ACL connections are managed automatically by the Android Bluetooth
-     * stack.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_ACL_CONNECTED =
-            "android.bluetooth.device.action.ACL_CONNECTED";
-
-    /**
-     * Broadcast Action: Indicates that a low level (ACL) disconnection has
-     * been requested for a remote device, and it will soon be disconnected.
-     * <p>This is useful for graceful disconnection. Applications should use
-     * this intent as a hint to immediately terminate higher level connections
-     * (RFCOMM, L2CAP, or profile connections) to the remote device.
-     * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_ACL_DISCONNECT_REQUESTED =
-            "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
-
-    /**
-     * Broadcast Action: Indicates a low level (ACL) disconnection from a
-     * remote device.
-     * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
-     * <p>ACL connections are managed automatically by the Android Bluetooth
-     * stack.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_ACL_DISCONNECTED =
-            "android.bluetooth.device.action.ACL_DISCONNECTED";
-
-    /**
-     * Broadcast Action: Indicates the friendly name of a remote device has
-     * been retrieved for the first time, or changed since the last retrieval.
-     * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
-     * #EXTRA_NAME}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_NAME_CHANGED =
-            "android.bluetooth.device.action.NAME_CHANGED";
-
-    /**
-     * Broadcast Action: Indicates the alias of a remote device has been
-     * changed.
-     * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
-     */
-    @SuppressLint("ActionValue")
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_ALIAS_CHANGED =
-            "android.bluetooth.device.action.ALIAS_CHANGED";
-
-    /**
-     * Broadcast Action: Indicates a change in the bond state of a remote
-     * device. For example, if a device is bonded (paired).
-     * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
-     * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
-     */
-    // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
-    // contain a hidden extra field EXTRA_REASON with the result code.
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_BOND_STATE_CHANGED =
-            "android.bluetooth.device.action.BOND_STATE_CHANGED";
-
-    /**
-     * Broadcast Action: Indicates the battery level of a remote device has
-     * been retrieved for the first time, or changed since the last retrieval
-     * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
-     * #EXTRA_BATTERY_LEVEL}.
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_BATTERY_LEVEL_CHANGED =
-            "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
-
-    /**
-     * Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED}
-     * intent. It contains the most recently retrieved battery level information
-     * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN}
-     * when the valid is unknown or there is an error
-     *
-     * @hide
-     */
-    public static final String EXTRA_BATTERY_LEVEL =
-            "android.bluetooth.device.extra.BATTERY_LEVEL";
-
-    /**
-     * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()}
-     *
-     * @hide
-     */
-    public static final int BATTERY_LEVEL_UNKNOWN = -1;
-
-    /**
-     * Used as an error value for {@link #getBatteryLevel()} to represent bluetooth is off
-     *
-     * @hide
-     */
-    public static final int BATTERY_LEVEL_BLUETOOTH_OFF = -100;
-
-    /**
-     * Used as a Parcelable {@link BluetoothDevice} extra field in every intent
-     * broadcast by this class. It contains the {@link BluetoothDevice} that
-     * the intent applies to.
-     */
-    public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
-
-    /**
-     * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link
-     * #ACTION_FOUND} intents. It contains the friendly Bluetooth name.
-     */
-    public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
-
-    /**
-     * Used as an optional short extra field in {@link #ACTION_FOUND} intents.
-     * Contains the RSSI value of the remote device as reported by the
-     * Bluetooth hardware.
-     */
-    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.
-     */
-    public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
-     * Contains the bond state of the remote device.
-     * <p>Possible values are:
-     * {@link #BOND_NONE},
-     * {@link #BOND_BONDING},
-     * {@link #BOND_BONDED}.
-     */
-    public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
-    /**
-     * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
-     * Contains the previous bond state of the remote device.
-     * <p>Possible values are:
-     * {@link #BOND_NONE},
-     * {@link #BOND_BONDING},
-     * {@link #BOND_BONDED}.
-     */
-    public static final String EXTRA_PREVIOUS_BOND_STATE =
-            "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
-    /**
-     * Indicates the remote device is not bonded (paired).
-     * <p>There is no shared link key with the remote device, so communication
-     * (if it is allowed at all) will be unauthenticated and unencrypted.
-     */
-    public static final int BOND_NONE = 10;
-    /**
-     * Indicates bonding (pairing) is in progress with the remote device.
-     */
-    public static final int BOND_BONDING = 11;
-    /**
-     * Indicates the remote device is bonded (paired).
-     * <p>A shared link keys exists locally for the remote device, so
-     * communication can be authenticated and encrypted.
-     * <p><i>Being bonded (paired) with a remote device does not necessarily
-     * mean the device is currently connected. It just means that the pending
-     * procedure was completed at some earlier time, and the link key is still
-     * stored locally, ready to use on the next connection.
-     * </i>
-     */
-    public static final int BOND_BONDED = 12;
-
-    /**
-     * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
-     * intents for unbond reason.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
-     * intents to indicate pairing method used. Possible values are:
-     * {@link #PAIRING_VARIANT_PIN},
-     * {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION},
-     */
-    public static final String EXTRA_PAIRING_VARIANT =
-            "android.bluetooth.device.extra.PAIRING_VARIANT";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
-     * intents as the value of passkey.
-     */
-    public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
-     * intents as the value of passkey.
-     * @hide
-     */
-    public static final String EXTRA_PAIRING_INITIATOR =
-            "android.bluetooth.device.extra.PAIRING_INITIATOR";
-
-    /**
-     * Bluetooth pairing initiator, Foreground App
-     * @hide
-     */
-    public static final int EXTRA_PAIRING_INITIATOR_FOREGROUND = 1;
-
-    /**
-     * Bluetooth pairing initiator, Background
-     * @hide
-     */
-    public static final int EXTRA_PAIRING_INITIATOR_BACKGROUND = 2;
-
-    /**
-     * Bluetooth device type, Unknown
-     */
-    public static final int DEVICE_TYPE_UNKNOWN = 0;
-
-    /**
-     * Bluetooth device type, Classic - BR/EDR devices
-     */
-    public static final int DEVICE_TYPE_CLASSIC = 1;
-
-    /**
-     * Bluetooth device type, Low Energy - LE-only
-     */
-    public static final int DEVICE_TYPE_LE = 2;
-
-    /**
-     * Bluetooth device type, Dual Mode - BR/EDR/LE
-     */
-    public static final int DEVICE_TYPE_DUAL = 3;
-
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final String ACTION_SDP_RECORD =
-            "android.bluetooth.device.action.SDP_RECORD";
-
-    /** @hide */
-    @IntDef(prefix = "METADATA_", value = {
-            METADATA_MANUFACTURER_NAME,
-            METADATA_MODEL_NAME,
-            METADATA_SOFTWARE_VERSION,
-            METADATA_HARDWARE_VERSION,
-            METADATA_COMPANION_APP,
-            METADATA_MAIN_ICON,
-            METADATA_IS_UNTETHERED_HEADSET,
-            METADATA_UNTETHERED_LEFT_ICON,
-            METADATA_UNTETHERED_RIGHT_ICON,
-            METADATA_UNTETHERED_CASE_ICON,
-            METADATA_UNTETHERED_LEFT_BATTERY,
-            METADATA_UNTETHERED_RIGHT_BATTERY,
-            METADATA_UNTETHERED_CASE_BATTERY,
-            METADATA_UNTETHERED_LEFT_CHARGING,
-            METADATA_UNTETHERED_RIGHT_CHARGING,
-            METADATA_UNTETHERED_CASE_CHARGING,
-            METADATA_ENHANCED_SETTINGS_UI_URI,
-            METADATA_DEVICE_TYPE,
-            METADATA_MAIN_BATTERY,
-            METADATA_MAIN_CHARGING,
-            METADATA_MAIN_LOW_BATTERY_THRESHOLD,
-            METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
-            METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
-            METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface MetadataKey{}
-
-    /**
-     * Maximum length of a metadata entry, this is to avoid exploding Bluetooth
-     * disk usage
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MAX_LENGTH = 2048;
-
-    /**
-     * Manufacturer name of this Bluetooth device
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MANUFACTURER_NAME = 0;
-
-    /**
-     * Model name of this Bluetooth device
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MODEL_NAME = 1;
-
-    /**
-     * Software version of this Bluetooth device
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_SOFTWARE_VERSION = 2;
-
-    /**
-     * Hardware version of this Bluetooth device
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_HARDWARE_VERSION = 3;
-
-    /**
-     * Package name of the companion app, if any
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_COMPANION_APP = 4;
-
-    /**
-     * URI to the main icon shown on the settings UI
-     * Data type should be {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MAIN_ICON = 5;
-
-    /**
-     * Whether this device is an untethered headset with left, right and case
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_IS_UNTETHERED_HEADSET = 6;
-
-    /**
-     * URI to icon of the left headset
-     * Data type should be {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_LEFT_ICON = 7;
-
-    /**
-     * URI to icon of the right headset
-     * Data type should be {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_RIGHT_ICON = 8;
-
-    /**
-     * URI to icon of the headset charging case
-     * Data type should be {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_CASE_ICON = 9;
-
-    /**
-     * Battery level of left headset
-     * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
-     * as invalid.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10;
-
-    /**
-     * Battery level of rigth headset
-     * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
-     * as invalid.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11;
-
-    /**
-     * Battery level of the headset charging case
-     * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
-     * as invalid.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_CASE_BATTERY = 12;
-
-    /**
-     * Whether the left headset is charging
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13;
-
-    /**
-     * Whether the right headset is charging
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14;
-
-    /**
-     * Whether the headset charging case is charging
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_CASE_CHARGING = 15;
-
-    /**
-     * URI to the enhanced settings UI slice
-     * Data type should be {@String} as {@link Byte} array, null means
-     * the UI does not exist.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16;
-
-    /**
-     * Type of the Bluetooth device, must be within the list of
-     * BluetoothDevice.DEVICE_TYPE_*
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_DEVICE_TYPE = 17;
-
-    /**
-     * Battery level of the Bluetooth device, use when the Bluetooth device
-     * does not support HFP battery indicator.
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MAIN_BATTERY = 18;
-
-    /**
-     * Whether the device is charging.
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MAIN_CHARGING = 19;
-
-    /**
-     * The battery threshold of the Bluetooth device to show low battery icon.
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20;
-
-    /**
-     * The battery threshold of the left headset to show low battery icon.
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21;
-
-    /**
-     * The battery threshold of the right headset to show low battery icon.
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22;
-
-    /**
-     * The battery threshold of the case to show low battery icon.
-     * Data type should be {@String} as {@link Byte} array.
-     * @hide
-     */
-    @SystemApi
-    public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23;
-
-    /**
-     * Device type which is used in METADATA_DEVICE_TYPE
-     * Indicates this Bluetooth device is a standard Bluetooth accessory or
-     * not listed in METADATA_DEVICE_TYPE_*.
-     * @hide
-     */
-    @SystemApi
-    public static final String DEVICE_TYPE_DEFAULT = "Default";
-
-    /**
-     * Device type which is used in METADATA_DEVICE_TYPE
-     * Indicates this Bluetooth device is a watch.
-     * @hide
-     */
-    @SystemApi
-    public static final String DEVICE_TYPE_WATCH = "Watch";
-
-    /**
-     * Device type which is used in METADATA_DEVICE_TYPE
-     * Indicates this Bluetooth device is an untethered headset.
-     * @hide
-     */
-    @SystemApi
-    public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset";
-
-    /**
-     * Broadcast Action: This intent is used to broadcast the {@link UUID}
-     * wrapped as a {@link android.os.ParcelUuid} of the remote device after it
-     * has been fetched. This intent is sent only when the UUIDs of the remote
-     * device are requested to be fetched using Service Discovery Protocol
-     * <p> Always contains the extra field {@link #EXTRA_DEVICE}
-     * <p> Always contains the extra field {@link #EXTRA_UUID}
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_UUID =
-            "android.bluetooth.device.action.UUID";
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_MAS_INSTANCE =
-            "android.bluetooth.device.action.MAS_INSTANCE";
-
-    /**
-     * Broadcast Action: Indicates a failure to retrieve the name of a remote
-     * device.
-     * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
-     *
-     * @hide
-     */
-    //TODO: is this actually useful?
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_NAME_FAILED =
-            "android.bluetooth.device.action.NAME_FAILED";
-
-    /**
-     * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PAIRING_REQUEST =
-            "android.bluetooth.device.action.PAIRING_REQUEST";
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage
-    public static final String ACTION_PAIRING_CANCEL =
-            "android.bluetooth.device.action.PAIRING_CANCEL";
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_ACCESS_REQUEST =
-            "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_ACCESS_REPLY =
-            "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_ACCESS_CANCEL =
-            "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
-
-    /**
-     * Intent to broadcast silence mode changed.
-     * Alway contains the extra field {@link #EXTRA_DEVICE}
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @SystemApi
-    public static final String ACTION_SILENCE_MODE_CHANGED =
-            "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
-
-    /**
-     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent.
-     *
-     * @hide
-     */
-    public static final String EXTRA_ACCESS_REQUEST_TYPE =
-            "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE";
-
-    /** @hide */
-    public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1;
-
-    /** @hide */
-    public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
-
-    /** @hide */
-    public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3;
-
-    /** @hide */
-    public static final int REQUEST_TYPE_SIM_ACCESS = 4;
-
-    /**
-     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
-     * Contains package name to return reply intent to.
-     *
-     * @hide
-     */
-    public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME";
-
-    /**
-     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
-     * Contains class name to return reply intent to.
-     *
-     * @hide
-     */
-    public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME";
-
-    /**
-     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent.
-     *
-     * @hide
-     */
-    public static final String EXTRA_CONNECTION_ACCESS_RESULT =
-            "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT";
-
-    /** @hide */
-    public static final int CONNECTION_ACCESS_YES = 1;
-
-    /** @hide */
-    public static final int CONNECTION_ACCESS_NO = 2;
-
-    /**
-     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents,
-     * Contains boolean to indicate if the allowed response is once-for-all so that
-     * next request will be granted without asking user again.
-     *
-     * @hide
-     */
-    public static final String EXTRA_ALWAYS_ALLOWED =
-            "android.bluetooth.device.extra.ALWAYS_ALLOWED";
-
-    /**
-     * A bond attempt succeeded
-     *
-     * @hide
-     */
-    public static final int BOND_SUCCESS = 0;
-
-    /**
-     * A bond attempt failed because pins did not match, or remote device did
-     * not respond to pin request in time
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_AUTH_FAILED = 1;
-
-    /**
-     * A bond attempt failed because the other side explicitly rejected
-     * bonding
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_AUTH_REJECTED = 2;
-
-    /**
-     * A bond attempt failed because we canceled the bonding process
-     *
-     * @hide
-     */
-    public static final int UNBOND_REASON_AUTH_CANCELED = 3;
-
-    /**
-     * A bond attempt failed because we could not contact the remote device
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
-
-    /**
-     * A bond attempt failed because a discovery is in progress
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
-
-    /**
-     * A bond attempt failed because of authentication timeout
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
-
-    /**
-     * A bond attempt failed because of repeated attempts
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
-
-    /**
-     * A bond attempt failed because we received an Authentication Cancel
-     * by remote end
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
-
-    /**
-     * An existing bond was explicitly revoked
-     *
-     * @hide
-     */
-    public static final int UNBOND_REASON_REMOVED = 9;
-
-    /**
-     * The user will be prompted to enter a pin or
-     * an app will enter a pin for user.
-     */
-    public static final int PAIRING_VARIANT_PIN = 0;
-
-    /**
-     * The user will be prompted to enter a passkey
-     *
-     * @hide
-     */
-    public static final int PAIRING_VARIANT_PASSKEY = 1;
-
-    /**
-     * The user will be prompted to confirm the passkey displayed on the screen or
-     * an app will confirm the passkey for the user.
-     */
-    public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
-
-    /**
-     * The user will be prompted to accept or deny the incoming pairing request
-     *
-     * @hide
-     */
-    public static final int PAIRING_VARIANT_CONSENT = 3;
-
-    /**
-     * The user will be prompted to enter the passkey displayed on remote device
-     * This is used for Bluetooth 2.1 pairing.
-     *
-     * @hide
-     */
-    public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
-
-    /**
-     * The user will be prompted to enter the PIN displayed on remote device.
-     * This is used for Bluetooth 2.0 pairing.
-     *
-     * @hide
-     */
-    public static final int PAIRING_VARIANT_DISPLAY_PIN = 5;
-
-    /**
-     * The user will be prompted to accept or deny the OOB pairing request
-     *
-     * @hide
-     */
-    public static final int PAIRING_VARIANT_OOB_CONSENT = 6;
-
-    /**
-     * The user will be prompted to enter a 16 digit pin or
-     * an app will enter a 16 digit pin for user.
-     *
-     * @hide
-     */
-    public static final int PAIRING_VARIANT_PIN_16_DIGITS = 7;
-
-    /**
-     * Used as an extra field in {@link #ACTION_UUID} intents,
-     * Contains the {@link android.os.ParcelUuid}s of the remote device which
-     * is a parcelable version of {@link UUID}.
-     */
-    public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
-
-    /** @hide */
-    public static final String EXTRA_SDP_RECORD =
-            "android.bluetooth.device.extra.SDP_RECORD";
-
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final String EXTRA_SDP_SEARCH_STATUS =
-            "android.bluetooth.device.extra.SDP_SEARCH_STATUS";
-
-    /** @hide */
-    @IntDef(prefix = "ACCESS_", value = {ACCESS_UNKNOWN,
-            ACCESS_ALLOWED, ACCESS_REJECTED})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AccessPermission{}
-
-    /**
-     * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
-     * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ACCESS_UNKNOWN = 0;
-
-    /**
-     * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
-     * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ACCESS_ALLOWED = 1;
-
-    /**
-     * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
-     * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ACCESS_REJECTED = 2;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-        prefix = { "TRANSPORT_" },
-        value = {
-            /** Allow host to automatically select a transport (dual-mode only) */
-            TRANSPORT_AUTO,
-            /** Use Classic or BR/EDR transport.*/
-            TRANSPORT_BREDR,
-            /** Use Low Energy transport.*/
-            TRANSPORT_LE,
-        }
-    )
-    public @interface Transport {}
-
-    /**
-     * No preference of physical transport for GATT connections to remote dual-mode devices
-     */
-    public static final int TRANSPORT_AUTO = 0;
-
-    /**
-     * Prefer BR/EDR transport for GATT connections to remote dual-mode devices
-     */
-    public static final int TRANSPORT_BREDR = 1;
-
-    /**
-     * Prefer LE transport for GATT connections to remote dual-mode devices
-     */
-    public static final int TRANSPORT_LE = 2;
-
-    /**
-     * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
-     * connection.
-     */
-    public static final int PHY_LE_1M = 1;
-
-    /**
-     * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
-     * connection.
-     */
-    public static final int PHY_LE_2M = 2;
-
-    /**
-     * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
-     * or connection.
-     */
-    public static final int PHY_LE_CODED = 3;
-
-    /**
-     * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
-     * options in a bitmask.
-     */
-    public static final int PHY_LE_1M_MASK = 1;
-
-    /**
-     * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
-     * options in a bitmask.
-     */
-    public static final int PHY_LE_2M_MASK = 2;
-
-    /**
-     * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
-     * available options in a bitmask.
-     */
-    public static final int PHY_LE_CODED_MASK = 4;
-
-    /**
-     * No preferred coding when transmitting on the LE Coded PHY.
-     */
-    public static final int PHY_OPTION_NO_PREFERRED = 0;
-
-    /**
-     * Prefer the S=2 coding to be used when transmitting on the LE Coded PHY.
-     */
-    public static final int PHY_OPTION_S2 = 1;
-
-    /**
-     * Prefer the S=8 coding to be used when transmitting on the LE Coded PHY.
-     */
-    public static final int PHY_OPTION_S8 = 2;
-
-
-    /** @hide */
-    public static final String EXTRA_MAS_INSTANCE =
-            "android.bluetooth.device.extra.MAS_INSTANCE";
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-        prefix = { "ADDRESS_TYPE_" },
-        value = {
-            /** Hardware MAC Address */
-            ADDRESS_TYPE_PUBLIC,
-            /** Address is either resolvable, non-resolvable or static.*/
-            ADDRESS_TYPE_RANDOM,
-        }
-    )
-    public @interface AddressType {}
-
-    /** Hardware MAC Address of the device */
-    public static final int ADDRESS_TYPE_PUBLIC = 0;
-    /** 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.
-     * TODO: Unify implementation of sService amongst BluetoothFoo API's
-     */
-    private static volatile IBluetooth sService;
-
-    private final String mAddress;
-    @AddressType private final int mAddressType;
-
-    private AttributionSource mAttributionSource;
-
-    /*package*/
-    @UnsupportedAppUsage
-    static IBluetooth getService() {
-        synchronized (BluetoothDevice.class) {
-            if (sService == null) {
-                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-                sService = adapter.getBluetoothService(sStateChangeCallback);
-            }
-        }
-        return sService;
-    }
-
-    static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() {
-
-        public void onBluetoothServiceUp(IBluetooth bluetoothService)
-                throws RemoteException {
-            synchronized (BluetoothDevice.class) {
-                if (sService == null) {
-                    sService = bluetoothService;
-                }
-            }
-        }
-
-        public void onBluetoothServiceDown()
-                throws RemoteException {
-            synchronized (BluetoothDevice.class) {
-                sService = null;
-            }
-        }
-
-        public void onBrEdrDown() {
-            if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state");
-        }
-
-        public void onOobData(@Transport int transport, OobData oobData) {
-            if (DBG) Log.d(TAG, "onOobData: got data");
-        }
-    };
-
-    /**
-     * Create a new BluetoothDevice
-     * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
-     * and is validated in this constructor.
-     *
-     * @param address valid Bluetooth MAC address
-     * @param attributionSource attribution for permission-protected calls
-     * @throws RuntimeException Bluetooth is not available on this platform
-     * @throws IllegalArgumentException address is invalid
-     * @hide
-     */
-    @UnsupportedAppUsage
-    /*package*/ BluetoothDevice(String address) {
-        getService();  // ensures sService is initialized
-        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-            throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
-        }
-
-        mAddress = address;
-        mAddressType = ADDRESS_TYPE_PUBLIC;
-        mAttributionSource = AttributionSource.myAttributionSource();
-    }
-
-    /** {@hide} */
-    public void setAttributionSource(@NonNull AttributionSource attributionSource) {
-        mAttributionSource = attributionSource;
-    }
-
-    /** {@hide} */
-    public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
-        setAttributionSource(attributionSource);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (o instanceof BluetoothDevice) {
-            return mAddress.equals(((BluetoothDevice) o).getAddress());
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return mAddress.hashCode();
-    }
-
-    /**
-     * Returns a string representation of this BluetoothDevice.
-     * <p>Currently this is the Bluetooth hardware address, for example
-     * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress}
-     * if you explicitly require the Bluetooth hardware address in case the
-     * {@link #toString} representation changes in the future.
-     *
-     * @return string representation of this BluetoothDevice
-     */
-    @Override
-    public String toString() {
-        return mAddress;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothDevice> CREATOR =
-            new Parcelable.Creator<BluetoothDevice>() {
-                public BluetoothDevice createFromParcel(Parcel in) {
-                    return new BluetoothDevice(in.readString());
-                }
-
-                public BluetoothDevice[] newArray(int size) {
-                    return new BluetoothDevice[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(mAddress);
-    }
-
-    /**
-     * Returns the hardware address of this BluetoothDevice.
-     * <p> For example, "00:11:22:AA:BB:CC".
-     *
-     * @return Bluetooth hardware address as string
-     */
-    public String getAddress() {
-        if (DBG) Log.d(TAG, "mAddress: " + mAddress);
-        return mAddress;
-    }
-
-    /**
-     * Returns the anonymized hardware address of this BluetoothDevice. The first three octets
-     * will be suppressed for anonymization.
-     * <p> For example, "XX:XX:XX:AA:BB:CC".
-     *
-     * @return Anonymized bluetooth hardware address as string
-     * @hide
-     */
-    public String getAnonymizedAddress() {
-        return "XX:XX:XX" + getAddress().substring(8);
-    }
-
-    /**
-     * Get the friendly Bluetooth name of the remote device.
-     *
-     * <p>The local adapter will automatically retrieve remote names when
-     * performing a device scan, and will cache them. This method just returns
-     * the name for this device from the cache.
-     *
-     * @return the Bluetooth name, or null if there was a problem.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public String getName() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
-            return null;
-        }
-        try {
-            String name = service.getRemoteName(this, mAttributionSource);
-            if (name != null) {
-                // remove whitespace characters from the name
-                return name
-                        .replace('\t', ' ')
-                        .replace('\n', ' ')
-                        .replace('\r', ' ');
-            }
-            return null;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /**
-     * Get the Bluetooth device type of the remote device.
-     *
-     * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link
-     * #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getType() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
-            return DEVICE_TYPE_UNKNOWN;
-        }
-        try {
-            return service.getRemoteType(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return DEVICE_TYPE_UNKNOWN;
-    }
-
-    /**
-     * Get the locally modifiable name (alias) of the remote Bluetooth device.
-     *
-     * @return the Bluetooth alias, the friendly device name if no alias, or
-     * null if there was a problem
-     */
-    @Nullable
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public String getAlias() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
-            return null;
-        }
-        try {
-            String alias = service.getRemoteAliasWithAttribution(this, mAttributionSource);
-            if (alias == null) {
-                return getName();
-            }
-            return alias
-                    .replace('\t', ' ')
-                    .replace('\n', ' ')
-                    .replace('\r', ' ');
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            BluetoothStatusCodes.SUCCESS,
-            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
-            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
-            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
-            BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
-    })
-    public @interface SetAliasReturnValues{}
-
-    /**
-     * Sets the locally modifiable name (alias) of the remote Bluetooth device. This method
-     * overwrites the previously stored alias. The new alias is saved in local
-     * storage so that the change is preserved over power cycles.
-     *
-     * <p>This method requires the calling app to be associated with Companion Device Manager (see
-     * {@link android.companion.CompanionDeviceManager#associate(AssociationRequest,
-     * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the
-     * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. Alternatively, if the
-     * caller has the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can
-     * bypass the Companion Device Manager association requirement as well as other permission
-     * requirements.
-     *
-     * @param alias is the new locally modifiable name for the remote Bluetooth device which must
-     *              be the empty string. If null, we clear the alias.
-     * @return whether the alias was successfully changed
-     * @throws IllegalArgumentException if the alias is the empty string
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @SetAliasReturnValues int setAlias(@Nullable String alias) {
-        if (alias != null && alias.isEmpty()) {
-            throw new IllegalArgumentException("alias cannot be the empty string");
-        }
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
-            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
-        }
-        try {
-            return service.setRemoteAlias(this, alias, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get the most recent identified battery level of this Bluetooth device
-     *
-     * @return Battery level in percents from 0 to 100, {@link #BATTERY_LEVEL_BLUETOOTH_OFF} if
-     * Bluetooth is disabled or {@link #BATTERY_LEVEL_UNKNOWN} if device is disconnected, or does
-     * not have any battery reporting service, or return value is invalid
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getBatteryLevel() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
-            return BATTERY_LEVEL_BLUETOOTH_OFF;
-        }
-        try {
-            return service.getBatteryLevel(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return BATTERY_LEVEL_UNKNOWN;
-    }
-
-    /**
-     * Start the bonding (pairing) process with the remote device.
-     * <p>This is an asynchronous call, it will return immediately. Register
-     * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
-     * the bonding process completes, and its result.
-     * <p>Android system services will handle the necessary user interactions
-     * to confirm and complete the bonding process.
-     *
-     * @return false on immediate error, true if bonding will begin
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean createBond() {
-        return createBond(TRANSPORT_AUTO);
-    }
-
-    /**
-     * Start the bonding (pairing) process with the remote device using the
-     * specified transport.
-     *
-     * <p>This is an asynchronous call, it will return immediately. Register
-     * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
-     * the bonding process completes, and its result.
-     * <p>Android system services will handle the necessary user interactions
-     * to confirm and complete the bonding process.
-     *
-     * @param transport The transport to use for the pairing procedure.
-     * @return false on immediate error, true if bonding will begin
-     * @throws IllegalArgumentException if an invalid transport was specified
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean createBond(int transport) {
-        return createBondInternal(transport, null, null);
-    }
-
-    /**
-     * Start the bonding (pairing) process with the remote device using the
-     * Out Of Band mechanism.
-     *
-     * <p>This is an asynchronous call, it will return immediately. Register
-     * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
-     * the bonding process completes, and its result.
-     *
-     * <p>Android system services will handle the necessary user interactions
-     * to confirm and complete the bonding process.
-     *
-     * <p>There are two possible versions of OOB Data.  This data can come in as
-     * P192 or P256.  This is a reference to the cryptography used to generate the key.
-     * The caller may pass one or both.  If both types of data are passed, then the
-     * P256 data will be preferred, and thus used.
-     *
-     * @param transport - Transport to use
-     * @param remoteP192Data - Out Of Band data (P192) or null
-     * @param remoteP256Data - Out Of Band data (P256) or null
-     * @return false on immediate error, true if bonding will begin
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean createBondOutOfBand(int transport, @Nullable OobData remoteP192Data,
-            @Nullable OobData remoteP256Data) {
-        if (remoteP192Data == null && remoteP256Data == null) {
-            throw new IllegalArgumentException(
-                "One or both arguments for the OOB data types are required to not be null."
-                + "  Please use createBond() instead if you do not have OOB data to pass.");
-        }
-        return createBondInternal(transport, remoteP192Data, remoteP256Data);
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data,
-            @Nullable OobData remoteP256Data) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            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, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Gets whether bonding was initiated locally
-     *
-     * @return true if bonding is initiated locally, false otherwise
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isBondingInitiatedLocally() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed");
-            return false;
-        }
-        try {
-            return service.isBondingInitiatedLocally(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Cancel an in-progress bonding request started with {@link #createBond}.
-     *
-     * @return true on success, false on error
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean cancelBondProcess() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
-            return false;
-        }
-        try {
-            Log.i(TAG, "cancelBondProcess() for device " + getAddress()
-                    + " called by pid: " + Process.myPid()
-                    + " tid: " + Process.myTid());
-            return service.cancelBondProcess(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Remove bond (pairing) with the remote device.
-     * <p>Delete the link key associated with the remote device, and
-     * immediately terminate connections to that device that require
-     * authentication and encryption.
-     *
-     * @return true on success, false on error
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean removeBond() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
-            return false;
-        }
-        try {
-            Log.i(TAG, "removeBond() for device " + getAddress()
-                    + " called by pid: " + Process.myPid()
-                    + " tid: " + Process.myTid());
-            return service.removeBond(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    private static final String BLUETOOTH_BONDING_CACHE_PROPERTY =
-            "cache_key.bluetooth.get_bond_state";
-    private final PropertyInvalidatedCache<BluetoothDevice, Integer> mBluetoothBondCache =
-            new PropertyInvalidatedCache<BluetoothDevice, Integer>(
-                8, BLUETOOTH_BONDING_CACHE_PROPERTY) {
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                protected Integer recompute(BluetoothDevice query) {
-                    try {
-                        return sService.getBondState(query, mAttributionSource);
-                    } catch (RemoteException e) {
-                        throw e.rethrowAsRuntimeException();
-                    }
-                }
-            };
-
-    /** @hide */
-    public void disableBluetoothGetBondStateCache() {
-        mBluetoothBondCache.disableLocal();
-    }
-
-    /** @hide */
-    public static void invalidateBluetoothGetBondStateCache() {
-        PropertyInvalidatedCache.invalidateCache(BLUETOOTH_BONDING_CACHE_PROPERTY);
-    }
-
-    /**
-     * Get the bond state of the remote device.
-     * <p>Possible values for the bond state are:
-     * {@link #BOND_NONE},
-     * {@link #BOND_BONDING},
-     * {@link #BOND_BONDED}.
-     *
-     * @return the bond state
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public int getBondState() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot get bond state");
-            return BOND_NONE;
-        }
-        try {
-            return mBluetoothBondCache.query(this);
-        } catch (RuntimeException e) {
-            if (e.getCause() instanceof RemoteException) {
-                Log.e(TAG, "", e);
-            } else {
-                throw e;
-            }
-        }
-        return BOND_NONE;
-    }
-
-    /**
-     * Checks whether this bluetooth device is associated with CDM and meets the criteria to skip
-     * the bluetooth pairing dialog because it has been already consented by the CDM prompt.
-     *
-     * @return true if we can bond without the dialog, false otherwise
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean canBondWithoutDialog() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot check if we can skip pairing dialog");
-            return false;
-        }
-        try {
-            if (DBG) Log.d(TAG, "canBondWithoutDialog, device: " + this);
-            return service.canBondWithoutDialog(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            BluetoothStatusCodes.SUCCESS,
-            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
-            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
-            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
-            BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
-    })
-    public @interface ConnectionReturnValues{}
-
-    /**
-     * Connects all user enabled and supported bluetooth profiles between the local and remote
-     * device. If no profiles are user enabled (e.g. first connection), we connect all supported
-     * profiles. If the device is not already connected, this will page the device before initiating
-     * profile connections. Connection is asynchronous and you should listen to each profile's
-     * broadcast intent ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful.
-     * For example, to verify a2dp is connected, you would listen for
-     * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
-     *
-     * @return whether the messages were successfully sent to try to connect all profiles
-     * @throws IllegalArgumentException if the device address is invalid
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public @ConnectionReturnValues int connect() {
-        if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
-            throw new IllegalArgumentException("device cannot have an invalid address");
-        }
-
-        try {
-            if (sService == null) {
-                Log.e(TAG, "BT not enabled. Cannot connect to remote device.");
-                return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
-            }
-            return sService.connectAllEnabledProfiles(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Disconnects all connected bluetooth profiles between the local and remote device.
-     * Disconnection is asynchronous and you should listen to each profile's broadcast intent
-     * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example,
-     * to verify a2dp is disconnected, you would listen for
-     * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
-     *
-     * @return whether the messages were successfully sent to try to disconnect all profiles
-     * @throws IllegalArgumentException if the device address is invalid
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionReturnValues int disconnect() {
-        if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
-            throw new IllegalArgumentException("device cannot have an invalid address");
-        }
-
-        try {
-            if (sService == null) {
-                Log.e(TAG, "BT not enabled. Cannot disconnect from remote device.");
-                return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
-            }
-            return sService.disconnectAllEnabledProfiles(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Returns whether there is an open connection to this device.
-     *
-     * @return True if there is at least one open connection to this device.
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isConnected() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            // BT is not enabled, we cannot be connected.
-            return false;
-        }
-        try {
-            return service.getConnectionStateWithAttribution(this, mAttributionSource)
-                    != CONNECTION_STATE_DISCONNECTED;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-    }
-
-    /**
-     * Returns whether there is an open connection to this device
-     * that has been encrypted.
-     *
-     * @return True if there is at least one encrypted connection to this device.
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isEncrypted() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            // BT is not enabled, we cannot be connected.
-            return false;
-        }
-        try {
-            return service.getConnectionStateWithAttribution(this, mAttributionSource)
-                    > CONNECTION_STATE_CONNECTED;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-    }
-
-    /**
-     * Get the Bluetooth class of the remote device.
-     *
-     * @return Bluetooth class object, or null on error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothClass getBluetoothClass() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
-            return null;
-        }
-        try {
-            int classInt = service.getRemoteClass(this, mAttributionSource);
-            if (classInt == BluetoothClass.ERROR) return null;
-            return new BluetoothClass(classInt);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /**
-     * Returns the supported features (UUIDs) of the remote device.
-     *
-     * <p>This method does not start a service discovery procedure to retrieve the UUIDs
-     * from the remote device. Instead, the local cached copy of the service
-     * UUIDs are returned.
-     * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired.
-     *
-     * @return the supported features (UUIDs) of the remote device, or null on error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public ParcelUuid[] getUuids() {
-        final IBluetooth service = sService;
-        if (service == null || !isBluetoothEnabled()) {
-            Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
-            return null;
-        }
-        try {
-            return service.getRemoteUuids(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /**
-     * Perform a service discovery on the remote device to get the UUIDs supported.
-     *
-     * <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 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.
-     *
-     * @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.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    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(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.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.fetchRemoteUuidsWithAttribution(this, transport, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Perform a service discovery on the remote device to get the SDP records associated
-     * with the specified UUID.
-     *
-     * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent,
-     * with the SDP records found on the remote end. If there is an error
-     * in getting the SDP records or if the process takes a long time,
-     * {@link #ACTION_SDP_RECORD} intent is sent with an status value in
-     * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0.
-     * Detailed status error codes can be found by members of the Bluetooth package in
-     * the AbstractionLayer class.
-     * <p>The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
-     * The object type will match one of the SdpXxxRecord types, depending on the UUID searched
-     * for.
-     *
-     * @return False if the check fails, True if the process
-     *               of initiating an ACL connection to the remote device
-     *               was started.
-     */
-    /** @hide */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sdpSearch(ParcelUuid uuid) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
-            return false;
-        }
-        try {
-            return service.sdpSearch(this, uuid, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
-     *
-     * @return true pin has been set false for error
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setPin(byte[] pin) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
-            return false;
-        }
-        try {
-            return service.setPin(this, true, pin.length, pin, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
-     *
-     * @return true pin has been set false for error
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setPin(@NonNull String pin) {
-        byte[] pinBytes = convertPinToBytes(pin);
-        if (pinBytes == null) {
-            return false;
-        }
-        return setPin(pinBytes);
-    }
-
-    /**
-     * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing.
-     *
-     * @return true confirmation has been sent out false for error
-     */
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPairingConfirmation(boolean confirm) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
-            return false;
-        }
-        try {
-            return service.setPairingConfirmation(this, confirm, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Cancels pairing to this device
-     *
-     * @return true if pairing cancelled successfully, false otherwise
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean cancelPairing() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot cancel pairing");
-            return false;
-        }
-        try {
-            return service.cancelBondProcess(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    boolean isBluetoothEnabled() {
-        boolean ret = false;
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter != null && adapter.isEnabled()) {
-            ret = true;
-        }
-        return ret;
-    }
-
-    /**
-     * Gets whether the phonebook access is allowed for this bluetooth device
-     *
-     * @return Whether the phonebook access is allowed to this device. Can be {@link
-     * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @AccessPermission int getPhonebookAccessPermission() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            return ACCESS_UNKNOWN;
-        }
-        try {
-            return service.getPhonebookAccessPermission(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return ACCESS_UNKNOWN;
-    }
-
-    /**
-     * Sets whether the {@link BluetoothDevice} enters silence mode. Audio will not
-     * be routed to the {@link BluetoothDevice} if set to {@code true}.
-     *
-     * When the {@link BluetoothDevice} enters silence mode, and the {@link BluetoothDevice}
-     * is an active device (for A2DP or HFP), the active device for that profile
-     * will be set to null.
-     * If the {@link BluetoothDevice} exits silence mode while the A2DP or HFP
-     * active device is null, the {@link BluetoothDevice} will be set as the
-     * active device for that profile.
-     * If the {@link BluetoothDevice} is disconnected, it exits silence mode.
-     * If the {@link BluetoothDevice} is set as the active device for A2DP or
-     * HFP, while silence mode is enabled, then the device will exit silence mode.
-     * If the {@link BluetoothDevice} is in silence mode, AVRCP position change
-     * event and HFP AG indicators will be disabled.
-     * If the {@link BluetoothDevice} is not connected with A2DP or HFP, it cannot
-     * enter silence mode.
-     *
-     * @param silence true to enter silence mode, false to exit
-     * @return true on success, false on error.
-     * @throws IllegalStateException if Bluetooth is not turned ON.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setSilenceMode(boolean silence) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            throw new IllegalStateException("Bluetooth is not turned ON");
-        }
-        try {
-            return service.setSilenceMode(this, silence, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "setSilenceMode fail", e);
-            return false;
-        }
-    }
-
-    /**
-     * Check whether the {@link BluetoothDevice} is in silence mode
-     *
-     * @return true on device in silence mode, otherwise false.
-     * @throws IllegalStateException if Bluetooth is not turned ON.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean isInSilenceMode() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            throw new IllegalStateException("Bluetooth is not turned ON");
-        }
-        try {
-            return service.getSilenceMode(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "isInSilenceMode fail", e);
-            return false;
-        }
-    }
-
-    /**
-     * Sets whether the phonebook access is allowed to this device.
-     *
-     * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
-     * #ACCESS_REJECTED}.
-     * @return Whether the value has been successfully set.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPhonebookAccessPermission(@AccessPermission int value) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            return false;
-        }
-        try {
-            return service.setPhonebookAccessPermission(this, value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Gets whether message access is allowed to this bluetooth device
-     *
-     * @return Whether the message access is allowed to this device.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @AccessPermission int getMessageAccessPermission() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            return ACCESS_UNKNOWN;
-        }
-        try {
-            return service.getMessageAccessPermission(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return ACCESS_UNKNOWN;
-    }
-
-    /**
-     * Sets whether the message access is allowed to this device.
-     *
-     * @param value Can be {@link #ACCESS_UNKNOWN} if the device is unbonded,
-     * {@link #ACCESS_ALLOWED} if the permission is being granted, or {@link #ACCESS_REJECTED} if
-     * the permission is not being granted.
-     * @return Whether the value has been successfully set.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setMessageAccessPermission(@AccessPermission int value) {
-        // Validates param value is one of the accepted constants
-        if (value != ACCESS_ALLOWED && value != ACCESS_REJECTED && value != ACCESS_UNKNOWN) {
-            throw new IllegalArgumentException(value + "is not a valid AccessPermission value");
-        }
-        final IBluetooth service = sService;
-        if (service == null) {
-            return false;
-        }
-        try {
-            return service.setMessageAccessPermission(this, value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Gets whether sim access is allowed for this bluetooth device
-     *
-     * @return Whether the Sim access is allowed to this device.
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @AccessPermission int getSimAccessPermission() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            return ACCESS_UNKNOWN;
-        }
-        try {
-            return service.getSimAccessPermission(this, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return ACCESS_UNKNOWN;
-    }
-
-    /**
-     * Sets whether the Sim access is allowed to this device.
-     *
-     * @param value Can be {@link #ACCESS_UNKNOWN} if the device is unbonded,
-     * {@link #ACCESS_ALLOWED} if the permission is being granted, or {@link #ACCESS_REJECTED} if
-     * the permission is not being granted.
-     * @return Whether the value has been successfully set.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setSimAccessPermission(int value) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            return false;
-        }
-        try {
-            return service.setSimAccessPermission(this, value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
-    }
-
-    /**
-     * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
-     * outgoing connection to this remote device on given channel.
-     * <p>The remote device will be authenticated and communication on this
-     * socket will be encrypted.
-     * <p> Use this socket only if an authenticated socket link is possible.
-     * Authentication refers to the authentication of the link key to
-     * prevent person-in-the-middle type of attacks.
-     * For example, for Bluetooth 2.1 devices, if any of the devices does not
-     * have an input and output capability or just has the ability to
-     * display a numeric key, a secure socket connection is not possible.
-     * In such a case, use {@link createInsecureRfcommSocket}.
-     * For more details, refer to the Security Model section 5.2 (vol 3) of
-     * Bluetooth Core Specification version 2.1 + EDR.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
-     * connection.
-     * <p>Valid RFCOMM channels are in range 1 to 30.
-     *
-     * @param channel RFCOMM channel to connect to
-     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createRfcommSocket(int channel) throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "Bluetooth is not enabled");
-            throw new IOException();
-        }
-        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel,
-                null);
-    }
-
-    /**
-     * Create an L2cap {@link BluetoothSocket} ready to start a secure
-     * outgoing connection to this remote device on given channel.
-     * <p>The remote device will be authenticated and communication on this
-     * socket will be encrypted.
-     * <p> Use this socket only if an authenticated socket link is possible.
-     * Authentication refers to the authentication of the link key to
-     * prevent person-in-the-middle type of attacks.
-     * For example, for Bluetooth 2.1 devices, if any of the devices does not
-     * have an input and output capability or just has the ability to
-     * display a numeric key, a secure socket connection is not possible.
-     * In such a case, use {@link createInsecureRfcommSocket}.
-     * For more details, refer to the Security Model section 5.2 (vol 3) of
-     * Bluetooth Core Specification version 2.1 + EDR.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
-     * connection.
-     * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
-     *
-     * @param channel L2cap PSM/channel to connect to
-     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createL2capSocket(int channel) throws IOException {
-        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, true, true, this, channel,
-                null);
-    }
-
-    /**
-     * Create an L2cap {@link BluetoothSocket} ready to start an insecure
-     * outgoing connection to this remote device on given channel.
-     * <p>The remote device will be not authenticated and communication on this
-     * socket will not be encrypted.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
-     * connection.
-     * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
-     *
-     * @param channel L2cap PSM/channel to connect to
-     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException {
-        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel,
-                null);
-    }
-
-    /**
-     * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
-     * outgoing connection to this remote device using SDP lookup of uuid.
-     * <p>This is designed to be used with {@link
-     * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer
-     * Bluetooth applications.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
-     * connection. This will also perform an SDP lookup of the given uuid to
-     * determine which channel to connect to.
-     * <p>The remote device will be authenticated and communication on this
-     * socket will be encrypted.
-     * <p> Use this socket only if an authenticated socket link is possible.
-     * Authentication refers to the authentication of the link key to
-     * prevent person-in-the-middle type of attacks.
-     * For example, for Bluetooth 2.1 devices, if any of the devices does not
-     * have an input and output capability or just has the ability to
-     * display a numeric key, a secure socket connection is not possible.
-     * In such a case, use {@link #createInsecureRfcommSocketToServiceRecord}.
-     * For more details, refer to the Security Model section 5.2 (vol 3) of
-     * Bluetooth Core Specification version 2.1 + EDR.
-     * <p>Hint: If you are connecting to a Bluetooth serial board then try
-     * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
-     * However if you are connecting to an Android peer then please generate
-     * your own unique UUID.
-     *
-     * @param uuid service record uuid to lookup RFCOMM channel
-     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "Bluetooth is not enabled");
-            throw new IOException();
-        }
-
-        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1,
-                new ParcelUuid(uuid));
-    }
-
-    /**
-     * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure
-     * outgoing connection to this remote device using SDP lookup of uuid.
-     * <p> The communication channel will not have an authenticated link key
-     * i.e it will be subject to person-in-the-middle attacks. For Bluetooth 2.1
-     * devices, the link key will be encrypted, as encryption is mandatory.
-     * For legacy devices (pre Bluetooth 2.1 devices) the link key will
-     * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an
-     * encrypted and authenticated communication channel is desired.
-     * <p>This is designed to be used with {@link
-     * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer
-     * Bluetooth applications.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
-     * connection. This will also perform an SDP lookup of the given uuid to
-     * determine which channel to connect to.
-     * <p>The remote device will be authenticated and communication on this
-     * socket will be encrypted.
-     * <p>Hint: If you are connecting to a Bluetooth serial board then try
-     * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
-     * However if you are connecting to an Android peer then please generate
-     * your own unique UUID.
-     *
-     * @param uuid service record uuid to lookup RFCOMM channel
-     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "Bluetooth is not enabled");
-            throw new IOException();
-        }
-        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1,
-                new ParcelUuid(uuid));
-    }
-
-    /**
-     * Construct an insecure RFCOMM socket ready to start an outgoing
-     * connection.
-     * Call #connect on the returned #BluetoothSocket to begin the connection.
-     * The remote device will not be authenticated and communication on this
-     * socket will not be encrypted.
-     *
-     * @param port remote port
-     * @return An RFCOMM BluetoothSocket
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * permissions.
-     * @hide
-     */
-    @UnsupportedAppUsage(publicAlternatives = "Use "
-            + "{@link #createInsecureRfcommSocketToServiceRecord} instead.")
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "Bluetooth is not enabled");
-            throw new IOException();
-        }
-        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port,
-                null);
-    }
-
-    /**
-     * Construct a SCO socket ready to start an outgoing connection.
-     * Call #connect on the returned #BluetoothSocket to begin the connection.
-     *
-     * @return a SCO BluetoothSocket
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public BluetoothSocket createScoSocket() throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "Bluetooth is not enabled");
-            throw new IOException();
-        }
-        return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
-    }
-
-    /**
-     * Check that a pin is valid and convert to byte array.
-     *
-     * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters.
-     *
-     * @param pin pin as java String
-     * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static byte[] convertPinToBytes(String pin) {
-        if (pin == null) {
-            return null;
-        }
-        byte[] pinBytes;
-        try {
-            pinBytes = pin.getBytes("UTF-8");
-        } catch (UnsupportedEncodingException uee) {
-            Log.e(TAG, "UTF-8 not supported?!?");  // this should not happen
-            return null;
-        }
-        if (pinBytes.length <= 0 || pinBytes.length > 16) {
-            return null;
-        }
-        return pinBytes;
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @throws IllegalArgumentException if callback is null
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-            BluetoothGattCallback callback) {
-        return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO));
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
-     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
-     * BluetoothDevice#TRANSPORT_LE}
-     * @throws IllegalArgumentException if callback is null
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-            BluetoothGattCallback callback, int transport) {
-        return (connectGatt(context, autoConnect, callback, transport, PHY_LE_1M_MASK));
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
-     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
-     * BluetoothDevice#TRANSPORT_LE}
-     * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
-     * is set to true.
-     * @throws NullPointerException if callback is null
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-            BluetoothGattCallback callback, int transport, int phy) {
-        return connectGatt(context, autoConnect, callback, transport, phy, null);
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
-     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
-     * BluetoothDevice#TRANSPORT_LE}
-     * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
-     * is set to true.
-     * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
-     * an un-specified background thread.
-     * @throws NullPointerException if callback is null
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-            BluetoothGattCallback callback, int transport, int phy,
-            Handler handler) {
-        return connectGatt(context, autoConnect, callback, transport, false, phy, handler);
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
-     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
-     * BluetoothDevice#TRANSPORT_LE}
-     * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
-     * does not hold a GATT connection. It automatically disconnects when no other GATT connections
-     * are active for the remote device.
-     * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
-     * is set to true.
-     * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
-     * an un-specified background thread.
-     * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client
-     * operations.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-            BluetoothGattCallback callback, int transport,
-            boolean opportunistic, int phy, Handler handler) {
-        if (callback == null) {
-            throw new NullPointerException("callback is null");
-        }
-
-        // TODO(Bluetooth) check whether platform support BLE
-        //     Do the check here or in GattServer?
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        IBluetoothManager managerService = adapter.getBluetoothManager();
-        try {
-            IBluetoothGatt iGatt = managerService.getBluetoothGatt();
-            if (iGatt == null) {
-                // BLE is not supported
-                return null;
-            }
-            BluetoothGatt gatt = new BluetoothGatt(
-                    iGatt, this, transport, opportunistic, phy, mAttributionSource);
-            gatt.connect(autoConnect, callback, handler);
-            return gatt;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return null;
-    }
-
-    /**
-     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
-     * be used to start a secure outgoing connection to the remote device with the same dynamic
-     * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
-     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for
-     * peer-peer Bluetooth applications.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
-     * <p>Application using this API is responsible for obtaining PSM value from remote device.
-     * <p>The remote device will be authenticated and communication on this socket will be
-     * encrypted.
-     * <p> Use this socket if an authenticated socket link is possible. Authentication refers
-     * to the authentication of the link key to prevent person-in-the-middle type of attacks.
-     *
-     * @param psm dynamic PSM value from remote device
-     * @return a CoC #BluetoothSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
-            throw new IOException();
-        }
-        if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm);
-        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
-                null);
-    }
-
-    /**
-     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
-     * be used to start a secure outgoing connection to the remote device with the same dynamic
-     * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
-     * <p>This is designed to be used with {@link
-     * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications.
-     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
-     * <p>Application using this API is responsible for obtaining PSM value from remote device.
-     * <p> The communication channel may not have an authenticated link key, i.e. it may be subject
-     * to person-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and
-     * authenticated communication channel is possible.
-     *
-     * @param psm dynamic PSM value from remote device
-     * @return a CoC #BluetoothSocket ready for an outgoing connection
-     * @throws IOException on error, for example Bluetooth not available, or insufficient
-     * permissions
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
-        if (!isBluetoothEnabled()) {
-            Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
-            throw new IOException();
-        }
-        if (DBG) {
-            Log.d(TAG, "createInsecureL2capChannel: psm=" + psm);
-        }
-        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
-                null);
-    }
-
-    /**
-     * Set a keyed metadata of this {@link BluetoothDevice} to a
-     * {@link String} value.
-     * Only bonded devices's metadata will be persisted across Bluetooth
-     * restart.
-     * Metadata will be removed when the device's bond state is moved to
-     * {@link #BOND_NONE}.
-     *
-     * @param key must be within the list of BluetoothDevice.METADATA_*
-     * @param value a byte array data to set for key. Must be less than
-     * {@link BluetoothAdapter#METADATA_MAX_LENGTH} characters in length
-     * @return true on success, false on error
-     * @hide
-    */
-    @SystemApi
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setMetadata(@MetadataKey int key, @NonNull byte[] value) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "Bluetooth is not enabled. Cannot set metadata");
-            return false;
-        }
-        if (value.length > METADATA_MAX_LENGTH) {
-            throw new IllegalArgumentException("value length is " + value.length
-                    + ", should not over " + METADATA_MAX_LENGTH);
-        }
-        try {
-            return service.setMetadata(this, key, value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "setMetadata fail", e);
-            return false;
-        }
-    }
-
-    /**
-     * Get a keyed metadata for this {@link BluetoothDevice} as {@link String}
-     *
-     * @param key must be within the list of BluetoothDevice.METADATA_*
-     * @return Metadata of the key as byte array, null on error or not found
-     * @hide
-     */
-    @SystemApi
-    @Nullable
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public byte[] getMetadata(@MetadataKey int key) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "Bluetooth is not enabled. Cannot get metadata");
-            return null;
-        }
-        try {
-            return service.getMetadata(this, key, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "getMetadata fail", e);
-            return null;
-        }
-    }
-
-    /**
-     * Get the maxinum metadata key ID.
-     *
-     * @return the last supported metadata key
-     * @hide
-     */
-    public static @MetadataKey int getMaxMetadataKey() {
-        return METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothDevicePicker.java b/core/java/android/bluetooth/BluetoothDevicePicker.java
deleted file mode 100644
index 26e4657..0000000
--- a/core/java/android/bluetooth/BluetoothDevicePicker.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-
-/**
- * A helper to show a system "Device Picker" activity to the user.
- *
- * @hide
- */
-public interface BluetoothDevicePicker {
-    public static final String EXTRA_NEED_AUTH =
-            "android.bluetooth.devicepicker.extra.NEED_AUTH";
-    public static final String EXTRA_FILTER_TYPE =
-            "android.bluetooth.devicepicker.extra.FILTER_TYPE";
-    public static final String EXTRA_LAUNCH_PACKAGE =
-            "android.bluetooth.devicepicker.extra.LAUNCH_PACKAGE";
-    public static final String EXTRA_LAUNCH_CLASS =
-            "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS";
-
-    /**
-     * Broadcast when one BT device is selected from BT device picker screen.
-     * Selected {@link BluetoothDevice} is returned in extra data named
-     * {@link BluetoothDevice#EXTRA_DEVICE}.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_DEVICE_SELECTED =
-            "android.bluetooth.devicepicker.action.DEVICE_SELECTED";
-
-    /**
-     * Broadcast when someone want to select one BT device from devices list.
-     * This intent contains below extra data:
-     * - {@link #EXTRA_NEED_AUTH} (boolean): if need authentication
-     * - {@link #EXTRA_FILTER_TYPE} (int): what kinds of device should be
-     * listed
-     * - {@link #EXTRA_LAUNCH_PACKAGE} (string): where(which package) this
-     * intent come from
-     * - {@link #EXTRA_LAUNCH_CLASS} (string): where(which class) this intent
-     * come from
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_LAUNCH =
-            "android.bluetooth.devicepicker.action.LAUNCH";
-
-    /** Ask device picker to show all kinds of BT devices */
-    public static final int FILTER_TYPE_ALL = 0;
-    /** Ask device picker to show BT devices that support AUDIO profiles */
-    public static final int FILTER_TYPE_AUDIO = 1;
-    /** Ask device picker to show BT devices that support Object Transfer */
-    public static final int FILTER_TYPE_TRANSFER = 2;
-    /**
-     * Ask device picker to show BT devices that support
-     * Personal Area Networking User (PANU) profile
-     */
-    public static final int FILTER_TYPE_PANU = 3;
-    /** Ask device picker to show BT devices that support Network Access Point (NAP) profile */
-    public static final int FILTER_TYPE_NAP = 4;
-}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
deleted file mode 100644
index b531829..0000000
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ /dev/null
@@ -1,1848 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.os.Build;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Public API for the Bluetooth GATT Profile.
- *
- * <p>This class provides Bluetooth GATT functionality to enable communication
- * with Bluetooth Smart or Smart Ready devices.
- *
- * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
- * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
- * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
- * scan process.
- */
-public final class BluetoothGatt implements BluetoothProfile {
-    private static final String TAG = "BluetoothGatt";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    @UnsupportedAppUsage
-    private IBluetoothGatt mService;
-    @UnsupportedAppUsage
-    private volatile BluetoothGattCallback mCallback;
-    private Handler mHandler;
-    @UnsupportedAppUsage
-    private int mClientIf;
-    private BluetoothDevice mDevice;
-    @UnsupportedAppUsage
-    private boolean mAutoConnect;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private int mAuthRetryState;
-    private int mConnState;
-    private final Object mStateLock = new Object();
-    private final Object mDeviceBusyLock = new Object();
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private Boolean mDeviceBusy = false;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private int mTransport;
-    private int mPhy;
-    private boolean mOpportunistic;
-    private final AttributionSource mAttributionSource;
-
-    private static final int AUTH_RETRY_STATE_IDLE = 0;
-    private static final int AUTH_RETRY_STATE_NO_MITM = 1;
-    private static final int AUTH_RETRY_STATE_MITM = 2;
-
-    private static final int CONN_STATE_IDLE = 0;
-    private static final int CONN_STATE_CONNECTING = 1;
-    private static final int CONN_STATE_CONNECTED = 2;
-    private static final int CONN_STATE_DISCONNECTING = 3;
-    private static final int CONN_STATE_CLOSED = 4;
-
-    private static final int WRITE_CHARACTERISTIC_MAX_RETRIES = 5;
-    private static final int WRITE_CHARACTERISTIC_TIME_TO_WAIT = 10; // milliseconds
-
-    private List<BluetoothGattService> mServices;
-
-    /** A GATT operation completed successfully */
-    public static final int GATT_SUCCESS = 0;
-
-    /** GATT read operation is not permitted */
-    public static final int GATT_READ_NOT_PERMITTED = 0x2;
-
-    /** GATT write operation is not permitted */
-    public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
-
-    /** Insufficient authentication for a given operation */
-    public static final int GATT_INSUFFICIENT_AUTHENTICATION = 0x5;
-
-    /** The given request is not supported */
-    public static final int GATT_REQUEST_NOT_SUPPORTED = 0x6;
-
-    /** Insufficient encryption for a given operation */
-    public static final int GATT_INSUFFICIENT_ENCRYPTION = 0xf;
-
-    /** 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;
-
-    /** A remote device connection is congested. */
-    public static final int GATT_CONNECTION_CONGESTED = 0x8f;
-
-    /** A GATT operation failed, errors other than the above */
-    public static final int GATT_FAILURE = 0x101;
-
-    /**
-     * Connection parameter update - Use the connection parameters recommended by the
-     * Bluetooth SIG. This is the default value if no connection parameter update
-     * is requested.
-     */
-    public static final int CONNECTION_PRIORITY_BALANCED = 0;
-
-    /**
-     * Connection parameter update - Request a high priority, low latency connection.
-     * An application should only request high priority connection parameters to transfer large
-     * amounts of data over LE quickly. Once the transfer is complete, the application should
-     * request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connection parameters to reduce
-     * energy use.
-     */
-    public static final int CONNECTION_PRIORITY_HIGH = 1;
-
-    /** Connection parameter update - Request low power, reduced data rate connection parameters. */
-    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
-
-    /**
-     * No authentication required.
-     *
-     * @hide
-     */
-    /*package*/ static final int AUTHENTICATION_NONE = 0;
-
-    /**
-     * Authentication requested; no person-in-the-middle protection required.
-     *
-     * @hide
-     */
-    /*package*/ static final int AUTHENTICATION_NO_MITM = 1;
-
-    /**
-     * Authentication with person-in-the-middle protection requested.
-     *
-     * @hide
-     */
-    /*package*/ static final int AUTHENTICATION_MITM = 2;
-
-    /**
-     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
-     */
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final IBluetoothGattCallback mBluetoothGattCallback =
-            new IBluetoothGattCallback.Stub() {
-                /**
-                 * Application interface registered - app is ready to go
-                 * @hide
-                 */
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onClientRegistered(int status, int clientIf) {
-                    if (DBG) {
-                        Log.d(TAG, "onClientRegistered() - status=" + status
-                                + " clientIf=" + clientIf);
-                    }
-                    if (VDBG) {
-                        synchronized (mStateLock) {
-                            if (mConnState != CONN_STATE_CONNECTING) {
-                                Log.e(TAG, "Bad connection state: " + mConnState);
-                            }
-                        }
-                    }
-                    mClientIf = clientIf;
-                    if (status != GATT_SUCCESS) {
-                        runOrQueueCallback(new Runnable() {
-                            @Override
-                            public void run() {
-                                final BluetoothGattCallback callback = mCallback;
-                                if (callback != null) {
-                                    callback.onConnectionStateChange(BluetoothGatt.this,
-                                            GATT_FAILURE,
-                                            BluetoothProfile.STATE_DISCONNECTED);
-                                }
-                            }
-                        });
-
-                        synchronized (mStateLock) {
-                            mConnState = CONN_STATE_IDLE;
-                        }
-                        return;
-                    }
-                    try {
-                        mService.clientConnect(mClientIf, mDevice.getAddress(),
-                                !mAutoConnect, mTransport, mOpportunistic,
-                                mPhy, mAttributionSource); // autoConnect is inverse of "isDirect"
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "", e);
-                    }
-                }
-
-                /**
-                 * Phy update callback
-                 * @hide
-                 */
-                @Override
-                public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
-                    if (DBG) {
-                        Log.d(TAG, "onPhyUpdate() - status=" + status
-                                + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Phy read callback
-                 * @hide
-                 */
-                @Override
-                public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
-                    if (DBG) {
-                        Log.d(TAG, "onPhyRead() - status=" + status
-                                + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Client connection state changed
-                 * @hide
-                 */
-                @Override
-                public void onClientConnectionState(int status, int clientIf,
-                        boolean connected, String address) {
-                    if (DBG) {
-                        Log.d(TAG, "onClientConnectionState() - status=" + status
-                                + " clientIf=" + clientIf + " device=" + address);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-                    int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
-                            BluetoothProfile.STATE_DISCONNECTED;
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onConnectionStateChange(BluetoothGatt.this, status,
-                                        profileState);
-                            }
-                        }
-                    });
-
-                    synchronized (mStateLock) {
-                        if (connected) {
-                            mConnState = CONN_STATE_CONNECTED;
-                        } else {
-                            mConnState = CONN_STATE_IDLE;
-                        }
-                    }
-
-                    synchronized (mDeviceBusyLock) {
-                        mDeviceBusy = false;
-                    }
-                }
-
-                /**
-                 * Remote search has been completed.
-                 * The internal object structure should now reflect the state
-                 * of the remote device database. Let the application know that
-                 * we are done at this point.
-                 * @hide
-                 */
-                @Override
-                public void onSearchComplete(String address, List<BluetoothGattService> services,
-                        int status) {
-                    if (DBG) {
-                        Log.d(TAG,
-                                "onSearchComplete() = Device=" + address + " Status=" + status);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    for (BluetoothGattService s : services) {
-                        //services we receive don't have device set properly.
-                        s.setDevice(mDevice);
-                    }
-
-                    mServices.addAll(services);
-
-                    // Fix references to included services, as they doesn't point to right objects.
-                    for (BluetoothGattService fixedService : mServices) {
-                        ArrayList<BluetoothGattService> includedServices =
-                                new ArrayList(fixedService.getIncludedServices());
-                        fixedService.getIncludedServices().clear();
-
-                        for (BluetoothGattService brokenRef : includedServices) {
-                            BluetoothGattService includedService = getService(mDevice,
-                                    brokenRef.getUuid(), brokenRef.getInstanceId());
-                            if (includedService != null) {
-                                fixedService.addIncludedService(includedService);
-                            } else {
-                                Log.e(TAG, "Broken GATT database: can't find included service.");
-                            }
-                        }
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onServicesDiscovered(BluetoothGatt.this, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Remote characteristic has been read.
-                 * Updates the internal value.
-                 * @hide
-                 */
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onCharacteristicRead(String address, int status, int handle,
-                        byte[] value) {
-                    if (VDBG) {
-                        Log.d(TAG, "onCharacteristicRead() - Device=" + address
-                                + " handle=" + handle + " Status=" + status);
-                    }
-
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    synchronized (mDeviceBusyLock) {
-                        mDeviceBusy = false;
-                    }
-
-                    if ((status == GATT_INSUFFICIENT_AUTHENTICATION
-                            || status == GATT_INSUFFICIENT_ENCRYPTION)
-                            && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
-                        try {
-                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
-                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
-                            mService.readCharacteristic(
-                                    mClientIf, address, handle, authReq, mAttributionSource);
-                            mAuthRetryState++;
-                            return;
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "", e);
-                        }
-                    }
-
-                    mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
-                    BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
-                            handle);
-                    if (characteristic == null) {
-                        Log.w(TAG, "onCharacteristicRead() failed to find characteristic!");
-                        return;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                if (status == 0) characteristic.setValue(value);
-                                callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
-                                        value, status);
-                                // Keep calling deprecated callback to maintain app compatibility
-                                callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
-                                        status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Characteristic has been written to the remote device.
-                 * Let the app know how we did...
-                 * @hide
-                 */
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onCharacteristicWrite(String address, int status, int handle,
-                        byte[] value) {
-                    if (VDBG) {
-                        Log.d(TAG, "onCharacteristicWrite() - Device=" + address
-                                + " handle=" + handle + " Status=" + status);
-                    }
-
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    synchronized (mDeviceBusyLock) {
-                        mDeviceBusy = false;
-                    }
-
-                    BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
-                            handle);
-                    if (characteristic == null) return;
-
-                    if ((status == GATT_INSUFFICIENT_AUTHENTICATION
-                            || status == GATT_INSUFFICIENT_ENCRYPTION)
-                            && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
-                        try {
-                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
-                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
-                            int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
-                            for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
-                                requestStatus =  mService.writeCharacteristic(mClientIf, address,
-                                                  handle, characteristic.getWriteType(), authReq,
-                                                  value, mAttributionSource);
-                                if (requestStatus
-                                        != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
-                                    break;
-                                }
-                                try {
-                                    Thread.sleep(WRITE_CHARACTERISTIC_TIME_TO_WAIT);
-                                } catch (InterruptedException e) {
-                                }
-                            }
-                            mAuthRetryState++;
-                            return;
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "", e);
-                        }
-                    }
-
-                    mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
-                                        status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Remote characteristic has been updated.
-                 * Updates the internal value.
-                 * @hide
-                 */
-                @Override
-                public void onNotify(String address, int handle, byte[] value) {
-                    if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
-
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice,
-                            handle);
-                    if (characteristic == null) return;
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                characteristic.setValue(value);
-                                callback.onCharacteristicChanged(BluetoothGatt.this,
-                                        characteristic, value);
-                                // Keep calling deprecated callback to maintain app compatibility
-                                callback.onCharacteristicChanged(BluetoothGatt.this,
-                                        characteristic);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Descriptor has been read.
-                 * @hide
-                 */
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onDescriptorRead(String address, int status, int handle, byte[] value) {
-                    if (VDBG) {
-                        Log.d(TAG,
-                                "onDescriptorRead() - Device=" + address + " handle=" + handle);
-                    }
-
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    synchronized (mDeviceBusyLock) {
-                        mDeviceBusy = false;
-                    }
-
-                    BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
-                    if (descriptor == null) return;
-
-
-                    if ((status == GATT_INSUFFICIENT_AUTHENTICATION
-                            || status == GATT_INSUFFICIENT_ENCRYPTION)
-                            && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
-                        try {
-                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
-                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
-                            mService.readDescriptor(
-                                    mClientIf, address, handle, authReq, mAttributionSource);
-                            mAuthRetryState++;
-                            return;
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "", e);
-                        }
-                    }
-
-                    mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                if (status == 0) descriptor.setValue(value);
-                                callback.onDescriptorRead(BluetoothGatt.this, descriptor, status,
-                                        value);
-                                // Keep calling deprecated callback to maintain app compatibility
-                                callback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Descriptor write operation complete.
-                 * @hide
-                 */
-                @Override
-                @SuppressLint("AndroidFrameworkRequiresPermission")
-                public void onDescriptorWrite(String address, int status, int handle,
-                        byte[] value) {
-                    if (VDBG) {
-                        Log.d(TAG,
-                                "onDescriptorWrite() - Device=" + address + " handle=" + handle);
-                    }
-
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    synchronized (mDeviceBusyLock) {
-                        mDeviceBusy = false;
-                    }
-
-                    BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
-                    if (descriptor == null) return;
-
-                    if ((status == GATT_INSUFFICIENT_AUTHENTICATION
-                            || status == GATT_INSUFFICIENT_ENCRYPTION)
-                            && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
-                        try {
-                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
-                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
-                            mService.writeDescriptor(mClientIf, address, handle,
-                                    authReq, value, mAttributionSource);
-                            mAuthRetryState++;
-                            return;
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "", e);
-                        }
-                    }
-
-                    mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Prepared write transaction completed (or aborted)
-                 * @hide
-                 */
-                @Override
-                public void onExecuteWrite(String address, int status) {
-                    if (VDBG) {
-                        Log.d(TAG, "onExecuteWrite() - Device=" + address
-                                + " status=" + status);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    synchronized (mDeviceBusyLock) {
-                        mDeviceBusy = false;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onReliableWriteCompleted(BluetoothGatt.this, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Remote device RSSI has been read
-                 * @hide
-                 */
-                @Override
-                public void onReadRemoteRssi(String address, int rssi, int status) {
-                    if (VDBG) {
-                        Log.d(TAG, "onReadRemoteRssi() - Device=" + address
-                                + " rssi=" + rssi + " status=" + status);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Callback invoked when the MTU for a given connection changes
-                 * @hide
-                 */
-                @Override
-                public void onConfigureMTU(String address, int mtu, int status) {
-                    if (DBG) {
-                        Log.d(TAG, "onConfigureMTU() - Device=" + address
-                                + " mtu=" + mtu + " status=" + status);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onMtuChanged(BluetoothGatt.this, mtu, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Callback invoked when the given connection is updated
-                 * @hide
-                 */
-                @Override
-                public void onConnectionUpdated(String address, int interval, int latency,
-                        int timeout, int status) {
-                    if (DBG) {
-                        Log.d(TAG, "onConnectionUpdated() - Device=" + address
-                                + " interval=" + interval + " latency=" + latency
-                                + " timeout=" + timeout + " status=" + status);
-                    }
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
-                                        timeout, status);
-                            }
-                        }
-                    });
-                }
-
-                /**
-                 * Callback invoked when service changed event is received
-                 * @hide
-                 */
-                @Override
-                public void onServiceChanged(String address) {
-                    if (DBG) {
-                        Log.d(TAG, "onServiceChanged() - Device=" + address);
-                    }
-
-                    if (!address.equals(mDevice.getAddress())) {
-                        return;
-                    }
-
-                    runOrQueueCallback(new Runnable() {
-                        @Override
-                        public void run() {
-                            final BluetoothGattCallback callback = mCallback;
-                            if (callback != null) {
-                                callback.onServiceChanged(BluetoothGatt.this);
-                            }
-                        }
-                    });
-                }
-            };
-
-    /* package */ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, int transport,
-            boolean opportunistic, int phy, AttributionSource attributionSource) {
-        mService = iGatt;
-        mDevice = device;
-        mTransport = transport;
-        mPhy = phy;
-        mOpportunistic = opportunistic;
-        mAttributionSource = attributionSource;
-        mServices = new ArrayList<BluetoothGattService>();
-
-        mConnState = CONN_STATE_IDLE;
-        mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-    }
-
-    /**
-     * Close this Bluetooth GATT client.
-     *
-     * Application should call this method as early as possible after it is done with
-     * this GATT client.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void close() {
-        if (DBG) Log.d(TAG, "close()");
-
-        unregisterApp();
-        mConnState = CONN_STATE_CLOSED;
-        mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-    }
-
-    /**
-     * Returns a service by UUID, instance and type.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid,
-            int instanceId) {
-        for (BluetoothGattService svc : mServices) {
-            if (svc.getDevice().equals(device)
-                    && svc.getInstanceId() == instanceId
-                    && svc.getUuid().equals(uuid)) {
-                return svc;
-            }
-        }
-        return null;
-    }
-
-
-    /**
-     * Returns a characteristic with id equal to instanceId.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device,
-            int instanceId) {
-        for (BluetoothGattService svc : mServices) {
-            for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
-                if (charac.getInstanceId() == instanceId) {
-                    return charac;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns a descriptor with id equal to instanceId.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattDescriptor getDescriptorById(BluetoothDevice device, int instanceId) {
-        for (BluetoothGattService svc : mServices) {
-            for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
-                for (BluetoothGattDescriptor desc : charac.getDescriptors()) {
-                    if (desc.getInstanceId() == instanceId) {
-                        return desc;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Queue the runnable on a {@link Handler} provided by the user, or execute the runnable
-     * immediately if no Handler was provided.
-     */
-    private void runOrQueueCallback(final Runnable cb) {
-        if (mHandler == null) {
-            try {
-                cb.run();
-            } catch (Exception ex) {
-                Log.w(TAG, "Unhandled exception in callback", ex);
-            }
-        } else {
-            mHandler.post(cb);
-        }
-    }
-
-    /**
-     * Register an application callback to start using GATT.
-     *
-     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
-     * is used to notify success or failure if the function returns true.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @return If true, the callback will be called to notify success or failure, false on immediate
-     * error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
-        return registerApp(callback, handler, false);
-    }
-
-    /**
-     * Register an application callback to start using GATT.
-     *
-     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
-     * is used to notify success or failure if the function returns true.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param eatt_support indicate to allow for eatt support
-     * @return If true, the callback will be called to notify success or failure, false on immediate
-     * error
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private boolean registerApp(BluetoothGattCallback callback, Handler handler,
-                                boolean eatt_support) {
-        if (DBG) Log.d(TAG, "registerApp()");
-        if (mService == null) return false;
-
-        mCallback = callback;
-        mHandler = handler;
-        UUID uuid = UUID.randomUUID();
-        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
-
-        try {
-            mService.registerClient(
-                    new ParcelUuid(uuid), mBluetoothGattCallback, eatt_support, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Unregister the current application and callbacks.
-     */
-    @UnsupportedAppUsage
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private void unregisterApp() {
-        if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
-        if (mService == null || mClientIf == 0) return;
-
-        try {
-            mCallback = null;
-            mService.unregisterClient(mClientIf, mAttributionSource);
-            mClientIf = 0;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Initiate a connection to a Bluetooth GATT capable device.
-     *
-     * <p>The connection may not be established right away, but will be
-     * completed when the remote device is available. A
-     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
-     * invoked when the connection state changes as a result of this function.
-     *
-     * <p>The autoConnect parameter determines whether to actively connect to
-     * the remote device, or rather passively scan and finalize the connection
-     * when the remote device is in range/available. Generally, the first ever
-     * connection to a device should be direct (autoConnect set to false) and
-     * subsequent connections to known devices should be invoked with the
-     * autoConnect parameter set to true.
-     *
-     * @param device Remote device to connect to
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @return true, if the connection attempt was initiated successfully
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
-            Handler handler) {
-        if (DBG) {
-            Log.d(TAG,
-                    "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
-        }
-        synchronized (mStateLock) {
-            if (mConnState != CONN_STATE_IDLE) {
-                throw new IllegalStateException("Not idle");
-            }
-            mConnState = CONN_STATE_CONNECTING;
-        }
-
-        mAutoConnect = autoConnect;
-
-        if (!registerApp(callback, handler)) {
-            synchronized (mStateLock) {
-                mConnState = CONN_STATE_IDLE;
-            }
-            Log.e(TAG, "Failed to register callback");
-            return false;
-        }
-
-        // The connection will continue in the onClientRegistered callback
-        return true;
-    }
-
-    /**
-     * Disconnects an established connection, or cancels a connection attempt
-     * currently in progress.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void disconnect() {
-        if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return;
-
-        try {
-            mService.clientDisconnect(mClientIf, mDevice.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Connect back to remote device.
-     *
-     * <p>This method is used to re-connect to a remote device after the
-     * connection has been dropped. If the device is not in range, the
-     * re-connection will be triggered once the device is back in range.
-     *
-     * @return true, if the connection attempt was initiated successfully
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connect() {
-        try {
-            // autoConnect is inverse of "isDirect"
-            mService.clientConnect(mClientIf, mDevice.getAddress(), false, mTransport,
-                    mOpportunistic, mPhy, mAttributionSource);
-            return true;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-    }
-
-    /**
-     * Set the preferred connection PHY for this app. Please note that this is just a
-     * recommendation, whether the PHY change will happen depends on other applications preferences,
-     * local and remote controller capabilities. Controller can override these settings.
-     * <p>
-     * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
-     * if no PHY change happens. It is also triggered when remote device updates the PHY.
-     *
-     * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}.
-     * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}.
-     * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
-     * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
-     * {@link BluetoothDevice#PHY_OPTION_S8}
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) {
-        try {
-            mService.clientSetPreferredPhy(mClientIf, mDevice.getAddress(), txPhy, rxPhy,
-                    phyOptions, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
-     * in {@link BluetoothGattCallback#onPhyRead}
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void readPhy() {
-        try {
-            mService.clientReadPhy(mClientIf, mDevice.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Return the remote bluetooth device this GATT client targets to
-     *
-     * @return remote bluetooth device
-     */
-    @RequiresNoPermission
-    public BluetoothDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Discovers services offered by a remote device as well as their
-     * characteristics and descriptors.
-     *
-     * <p>This is an asynchronous operation. Once service discovery is completed,
-     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
-     * triggered. If the discovery was successful, the remote services can be
-     * retrieved using the {@link #getServices} function.
-     *
-     * @return true, if the remote service discovery has been started
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean discoverServices() {
-        if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return false;
-
-        mServices.clear();
-
-        try {
-            mService.discoverServices(mClientIf, mDevice.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Discovers a service by UUID. This is exposed only for passing PTS tests.
-     * It should never be used by real applications. The service is not searched
-     * for characteristics and descriptors, or returned in any callback.
-     *
-     * @return true, if the remote service discovery has been started
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean discoverServiceByUuid(UUID uuid) {
-        if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return false;
-
-        mServices.clear();
-
-        try {
-            mService.discoverServiceByUuid(
-                    mClientIf, mDevice.getAddress(), new ParcelUuid(uuid), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Returns a list of GATT services offered by the remote device.
-     *
-     * <p>This function requires that service discovery has been completed
-     * for the given device.
-     *
-     * @return List of services on the remote device. Returns an empty list if service discovery has
-     * not yet been performed.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public List<BluetoothGattService> getServices() {
-        List<BluetoothGattService> result =
-                new ArrayList<BluetoothGattService>();
-
-        for (BluetoothGattService service : mServices) {
-            if (service.getDevice().equals(mDevice)) {
-                result.add(service);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Returns a {@link BluetoothGattService}, if the requested UUID is
-     * supported by the remote device.
-     *
-     * <p>This function requires that service discovery has been completed
-     * for the given device.
-     *
-     * <p>If multiple instances of the same service (as identified by UUID)
-     * exist, the first instance of the service is returned.
-     *
-     * @param uuid UUID of the requested service
-     * @return BluetoothGattService if supported, or null if the requested service is not offered by
-     * the remote device.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public BluetoothGattService getService(UUID uuid) {
-        for (BluetoothGattService service : mServices) {
-            if (service.getDevice().equals(mDevice) && service.getUuid().equals(uuid)) {
-                return service;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Reads the requested characteristic from the associated remote device.
-     *
-     * <p>This is an asynchronous operation. The result of the read operation
-     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
-     * BluetoothGattCharacteristic, byte[], int)} callback.
-     *
-     * @param characteristic Characteristic to read from the remote device
-     * @return true, if the read operation was initiated successfully
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
-        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) == 0) {
-            return false;
-        }
-
-        if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid());
-        if (mService == null || mClientIf == 0) return false;
-
-        BluetoothGattService service = characteristic.getService();
-        if (service == null) return false;
-
-        BluetoothDevice device = service.getDevice();
-        if (device == null) return false;
-
-        synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) return false;
-            mDeviceBusy = true;
-        }
-
-        try {
-            mService.readCharacteristic(mClientIf, device.getAddress(),
-                    characteristic.getInstanceId(), AUTHENTICATION_NONE, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            synchronized (mDeviceBusyLock) {
-                mDeviceBusy = false;
-            }
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Reads the characteristic using its UUID from the associated remote device.
-     *
-     * <p>This is an asynchronous operation. The result of the read operation
-     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
-     * BluetoothGattCharacteristic, byte[], int)} callback.
-     *
-     * @param uuid UUID of characteristic to read from the remote device
-     * @return true, if the read operation was initiated successfully
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) {
-        if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid);
-        if (mService == null || mClientIf == 0) return false;
-
-        synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) return false;
-            mDeviceBusy = true;
-        }
-
-        try {
-            mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(),
-                    new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE,
-                    mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            synchronized (mDeviceBusyLock) {
-                mDeviceBusy = false;
-            }
-            return false;
-        }
-
-        return true;
-    }
-
-
-    /**
-     * Writes a given characteristic and its values to the associated remote device.
-     *
-     * <p>Once the write operation has been completed, the
-     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
-     * reporting the result of the operation.
-     *
-     * @param characteristic Characteristic to write on the remote device
-     * @return true, if the write operation was initiated successfully
-     * @throws IllegalArgumentException if characteristic or its value are null
-     *
-     * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[],
-     * int)} as this is not memory safe.
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
-        try {
-            return writeCharacteristic(characteristic, characteristic.getValue(),
-                    characteristic.getWriteType()) == BluetoothStatusCodes.SUCCESS;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            BluetoothStatusCodes.SUCCESS,
-            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
-            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
-            BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
-            BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
-            BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
-            BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
-            BluetoothStatusCodes.ERROR_UNKNOWN
-    })
-    public @interface WriteOperationReturnValues{}
-
-    /**
-     * Writes a given characteristic and its values to the associated remote device.
-     *
-     * <p>Once the write operation has been completed, the
-     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
-     * reporting the result of the operation.
-     *
-     * @param characteristic Characteristic to write on the remote device
-     * @return whether the characteristic was successfully written to
-     * @throws IllegalArgumentException if characteristic or value are null
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @WriteOperationReturnValues
-    public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic,
-            @NonNull byte[] value, int writeType) {
-        if (characteristic == null) {
-            throw new IllegalArgumentException("characteristic must not be null");
-        }
-        if (value == null) {
-            throw new IllegalArgumentException("value must not be null");
-        }
-        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
-        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
-                && (characteristic.getProperties()
-                & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
-            return BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED;
-        }
-        if (mService == null || mClientIf == 0) {
-            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
-        }
-
-        BluetoothGattService service = characteristic.getService();
-        if (service == null) {
-            throw new IllegalArgumentException("Characteristic must have a non-null service");
-        }
-
-        BluetoothDevice device = service.getDevice();
-        if (device == null) {
-            throw new IllegalArgumentException("Service must have a non-null device");
-        }
-
-        synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) {
-                return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
-            }
-            mDeviceBusy = true;
-        }
-
-        int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
-        try {
-            for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
-                requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(),
-                        characteristic.getInstanceId(), writeType, AUTHENTICATION_NONE, value,
-                        mAttributionSource);
-                if (requestStatus != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
-                    break;
-                }
-                try {
-                    Thread.sleep(WRITE_CHARACTERISTIC_TIME_TO_WAIT);
-                } catch (InterruptedException e) {
-                }
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            synchronized (mDeviceBusyLock) {
-                mDeviceBusy = false;
-            }
-            throw e.rethrowFromSystemServer();
-        }
-
-        return requestStatus;
-    }
-
-    /**
-     * Reads the value for a given descriptor from the associated remote device.
-     *
-     * <p>Once the read operation has been completed, the
-     * {@link BluetoothGattCallback#onDescriptorRead} callback is
-     * triggered, signaling the result of the operation.
-     *
-     * @param descriptor Descriptor value to read from the remote device
-     * @return true, if the read operation was initiated successfully
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
-        if (VDBG) Log.d(TAG, "readDescriptor() - uuid: " + descriptor.getUuid());
-        if (mService == null || mClientIf == 0) return false;
-
-        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
-        if (characteristic == null) return false;
-
-        BluetoothGattService service = characteristic.getService();
-        if (service == null) return false;
-
-        BluetoothDevice device = service.getDevice();
-        if (device == null) return false;
-
-        synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) return false;
-            mDeviceBusy = true;
-        }
-
-        try {
-            mService.readDescriptor(mClientIf, device.getAddress(),
-                    descriptor.getInstanceId(), AUTHENTICATION_NONE, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            synchronized (mDeviceBusyLock) {
-                mDeviceBusy = false;
-            }
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Write the value of a given descriptor to the associated remote device.
-     *
-     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
-     * result of the write operation.
-     *
-     * @param descriptor Descriptor to write to the associated remote device
-     * @return true, if the write operation was initiated successfully
-     * @throws IllegalArgumentException if descriptor or its value are null
-     *
-     * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as
-     * this is not memory safe.
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
-        try {
-            return writeDescriptor(descriptor, descriptor.getValue())
-                    == BluetoothStatusCodes.SUCCESS;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * Write the value of a given descriptor to the associated remote device.
-     *
-     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
-     * result of the write operation.
-     *
-     * @param descriptor Descriptor to write to the associated remote device
-     * @return true, if the write operation was initiated successfully
-     * @throws IllegalArgumentException if descriptor or value are null
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @WriteOperationReturnValues
-    public int writeDescriptor(@NonNull BluetoothGattDescriptor descriptor,
-            @NonNull byte[] value) {
-        if (descriptor == null) {
-            throw new IllegalArgumentException("descriptor must not be null");
-        }
-        if (value == null) {
-            throw new IllegalArgumentException("value must not be null");
-        }
-        if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
-        if (mService == null || mClientIf == 0) {
-            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
-        }
-
-        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
-        if (characteristic == null) {
-            throw new IllegalArgumentException("Descriptor must have a non-null characteristic");
-        }
-
-        BluetoothGattService service = characteristic.getService();
-        if (service == null) {
-            throw new IllegalArgumentException("Characteristic must have a non-null service");
-        }
-
-        BluetoothDevice device = service.getDevice();
-        if (device == null) {
-            throw new IllegalArgumentException("Service must have a non-null device");
-        }
-
-        synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
-            mDeviceBusy = true;
-        }
-
-        try {
-            return mService.writeDescriptor(mClientIf, device.getAddress(),
-                    descriptor.getInstanceId(), AUTHENTICATION_NONE, value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            synchronized (mDeviceBusyLock) {
-                mDeviceBusy = false;
-            }
-            e.rethrowFromSystemServer();
-        }
-        return BluetoothStatusCodes.ERROR_UNKNOWN;
-    }
-
-    /**
-     * Initiates a reliable write transaction for a given remote device.
-     *
-     * <p>Once a reliable write transaction has been initiated, all calls
-     * to {@link #writeCharacteristic} are sent to the remote device for
-     * verification and queued up for atomic execution. The application will
-     * receive a {@link BluetoothGattCallback#onCharacteristicWrite} callback in response to every
-     * {@link #writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} call and is
-     * responsible for verifying if the value has been transmitted accurately.
-     *
-     * <p>After all characteristics have been queued up and verified,
-     * {@link #executeReliableWrite} will execute all writes. If a characteristic
-     * was not written correctly, calling {@link #abortReliableWrite} will
-     * cancel the current transaction without committing any values on the
-     * remote device.
-     *
-     * @return true, if the reliable write transaction has been initiated
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean beginReliableWrite() {
-        if (VDBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return false;
-
-        try {
-            mService.beginReliableWrite(mClientIf, mDevice.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Executes a reliable write transaction for a given remote device.
-     *
-     * <p>This function will commit all queued up characteristic write
-     * operations for a given remote device.
-     *
-     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
-     * invoked to indicate whether the transaction has been executed correctly.
-     *
-     * @return true, if the request to execute the transaction has been sent
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean executeReliableWrite() {
-        if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return false;
-
-        synchronized (mDeviceBusyLock) {
-            if (mDeviceBusy) return false;
-            mDeviceBusy = true;
-        }
-
-        try {
-            mService.endReliableWrite(mClientIf, mDevice.getAddress(), true, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            synchronized (mDeviceBusyLock) {
-                mDeviceBusy = false;
-            }
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Cancels a reliable write transaction for a given device.
-     *
-     * <p>Calling this function will discard all queued characteristic write
-     * operations for a given remote device.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void abortReliableWrite() {
-        if (VDBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return;
-
-        try {
-            mService.endReliableWrite(mClientIf, mDevice.getAddress(), false, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * @deprecated Use {@link #abortReliableWrite()}
-     */
-    @Deprecated
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void abortReliableWrite(BluetoothDevice mDevice) {
-        abortReliableWrite();
-    }
-
-    /**
-     * Enable or disable notifications/indications for a given characteristic.
-     *
-     * <p>Once notifications are enabled for a characteristic, a
-     * {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
-     * BluetoothGattCharacteristic, byte[])} callback will be triggered if the remote device
-     * indicates that the given characteristic has changed.
-     *
-     * @param characteristic The characteristic for which to enable notifications
-     * @param enable Set to true to enable notifications/indications
-     * @return true, if the requested notification status was set successfully
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
-            boolean enable) {
-        if (DBG) {
-            Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid()
-                    + " enable: " + enable);
-        }
-        if (mService == null || mClientIf == 0) return false;
-
-        BluetoothGattService service = characteristic.getService();
-        if (service == null) return false;
-
-        BluetoothDevice device = service.getDevice();
-        if (device == null) return false;
-
-        try {
-            mService.registerForNotification(mClientIf, device.getAddress(),
-                    characteristic.getInstanceId(), enable, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Clears the internal cache and forces a refresh of the services from the
-     * remote device.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean refresh() {
-        if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return false;
-
-        try {
-            mService.refreshDevice(mClientIf, mDevice.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Read the RSSI for a connected remote device.
-     *
-     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
-     * invoked when the RSSI value has been read.
-     *
-     * @return true, if the RSSI value has been requested successfully
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean readRemoteRssi() {
-        if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
-        if (mService == null || mClientIf == 0) return false;
-
-        try {
-            mService.readRemoteRssi(mClientIf, mDevice.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Request an MTU size used for a given connection.
-     *
-     * <p>When performing a write request operation (write without response),
-     * the data sent is truncated to the MTU size. This function may be used
-     * to request a larger MTU size to be able to send more data at once.
-     *
-     * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
-     * whether this operation was successful.
-     *
-     * @return true, if the new MTU value has been requested successfully
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean requestMtu(int mtu) {
-        if (DBG) {
-            Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
-                    + " mtu: " + mtu);
-        }
-        if (mService == null || mClientIf == 0) return false;
-
-        try {
-            mService.configureMTU(mClientIf, mDevice.getAddress(), mtu, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Request a connection parameter update.
-     *
-     * <p>This function will send a connection parameter update request to the
-     * remote device.
-     *
-     * @param connectionPriority Request a specific connection priority. Must be one of {@link
-     * BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH}
-     * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
-     * @throws IllegalArgumentException If the parameters are outside of their specified range.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean requestConnectionPriority(int connectionPriority) {
-        if (connectionPriority < CONNECTION_PRIORITY_BALANCED
-                || connectionPriority > CONNECTION_PRIORITY_LOW_POWER) {
-            throw new IllegalArgumentException("connectionPriority not within valid range");
-        }
-
-        if (DBG) Log.d(TAG, "requestConnectionPriority() - params: " + connectionPriority);
-        if (mService == null || mClientIf == 0) return false;
-
-        try {
-            mService.connectionParameterUpdate(
-                    mClientIf, mDevice.getAddress(), connectionPriority, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Request an LE connection parameter update.
-     *
-     * <p>This function will send an LE connection parameters update request to the remote device.
-     *
-     * @return true, if the request is send to the Bluetooth stack.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean requestLeConnectionUpdate(int minConnectionInterval, int maxConnectionInterval,
-                                             int slaveLatency, int supervisionTimeout,
-                                             int minConnectionEventLen, int maxConnectionEventLen) {
-        if (DBG) {
-            Log.d(TAG, "requestLeConnectionUpdate() - min=(" + minConnectionInterval
-                        + ")" + (1.25 * minConnectionInterval)
-                        + "msec, max=(" + maxConnectionInterval + ")"
-                        + (1.25 * maxConnectionInterval) + "msec, latency=" + slaveLatency
-                        + ", timeout=" + supervisionTimeout + "msec" + ", min_ce="
-                        + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen);
-        }
-        if (mService == null || mClientIf == 0) return false;
-
-        try {
-            mService.leConnectionUpdate(mClientIf, mDevice.getAddress(),
-                    minConnectionInterval, maxConnectionInterval,
-                    slaveLatency, supervisionTimeout,
-                    minConnectionEventLen, maxConnectionEventLen,
-                    mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
-     * with {@link BluetoothProfile#GATT} as argument
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    @RequiresNoPermission
-    @Deprecated
-    public int getConnectionState(BluetoothDevice device) {
-        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
-    }
-
-    /**
-     * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
-     * with {@link BluetoothProfile#GATT} as argument
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    @RequiresNoPermission
-    @Deprecated
-    public List<BluetoothDevice> getConnectedDevices() {
-        throw new UnsupportedOperationException(
-                "Use BluetoothManager#getConnectedDevices instead.");
-    }
-
-    /**
-     * @deprecated Not supported - please use
-     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
-     * with {@link BluetoothProfile#GATT} as first argument
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    @RequiresNoPermission
-    @Deprecated
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        throw new UnsupportedOperationException(
-                "Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
deleted file mode 100644
index d0a5a1e..0000000
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-
-/**
- * This abstract class is used to implement {@link BluetoothGatt} callbacks.
- */
-public abstract class BluetoothGattCallback {
-
-    /**
-     * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
-     * remote device changing the PHY.
-     *
-     * @param gatt GATT client
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param status Status of the PHY update operation. {@link BluetoothGatt#GATT_SUCCESS} if the
-     * operation succeeds.
-     */
-    public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback triggered as result of {@link BluetoothGatt#readPhy}
-     *
-     * @param gatt GATT client
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param status Status of the PHY read operation. {@link BluetoothGatt#GATT_SUCCESS} if the
-     * operation succeeds.
-     */
-    public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback indicating when GATT client has connected/disconnected to/from a remote
-     * GATT server.
-     *
-     * @param gatt GATT client
-     * @param status Status of the connect or disconnect operation. {@link
-     * BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     * @param newState Returns the new connection state. Can be one of {@link
-     * BluetoothProfile#STATE_DISCONNECTED} or {@link BluetoothProfile#STATE_CONNECTED}
-     */
-    public void onConnectionStateChange(BluetoothGatt gatt, int status,
-            int newState) {
-    }
-
-    /**
-     * Callback invoked when the list of remote services, characteristics and descriptors
-     * for the remote device have been updated, ie new services have been discovered.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device has been explored
-     * successfully.
-     */
-    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
-    }
-
-    /**
-     * Callback reporting the result of a characteristic read operation.
-     *
-     * @param gatt           GATT client invoked
-     *                       {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
-     * @param characteristic Characteristic that was read from the associated remote device.
-     * @param status         {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
-     *                       successfully.
-     * @deprecated Use {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
-     * BluetoothGattCharacteristic, byte[], int)} as it is memory safe
-     */
-    @Deprecated
-    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
-            int status) {
-    }
-
-    /**
-     * Callback reporting the result of a characteristic read operation.
-     *
-     * @param gatt           GATT client invoked
-     *                       {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
-     * @param characteristic Characteristic that was read from the associated remote device.
-     * @param value          the value of the characteristic
-     * @param status         {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
-     *                       successfully.
-     */
-    public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull
-            BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) {
-    }
-
-    /**
-     * Callback indicating the result of a characteristic write operation.
-     *
-     * <p>If this callback is invoked while a reliable write transaction is
-     * in progress, the value of the characteristic represents the value
-     * reported by the remote device. An application should compare this
-     * value to the desired value to be written. If the values don't match,
-     * the application must abort the reliable write transaction.
-     *
-     * @param gatt           GATT client that invoked
-     *                       {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic,
-     *                       byte[], int)}
-     * @param characteristic Characteristic that was written to the associated remote device.
-     * @param status         The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if
-     *                       the
-     *                       operation succeeds.
-     */
-    public void onCharacteristicWrite(BluetoothGatt gatt,
-            BluetoothGattCharacteristic characteristic, int status) {
-    }
-
-    /**
-     * Callback triggered as a result of a remote characteristic notification.
-     *
-     * @param gatt           GATT client the characteristic is associated with
-     * @param characteristic Characteristic that has been updated as a result of a remote
-     *                       notification event.
-     * @deprecated Use {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
-     * BluetoothGattCharacteristic, byte[])} as it is memory safe by providing the characteristic
-     * value at the time of notification.
-     */
-    @Deprecated
-    public void onCharacteristicChanged(BluetoothGatt gatt,
-            BluetoothGattCharacteristic characteristic) {
-    }
-
-    /**
-     * Callback triggered as a result of a remote characteristic notification. Note that the value
-     * within the characteristic object may have changed since receiving the remote characteristic
-     * notification, so check the parameter value for the value at the time of notification.
-     *
-     * @param gatt           GATT client the characteristic is associated with
-     * @param characteristic Characteristic that has been updated as a result of a remote
-     *                       notification event.
-     * @param value          notified characteristic value
-     */
-    public void onCharacteristicChanged(@NonNull BluetoothGatt gatt,
-            @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
-    }
-
-    /**
-     * Callback reporting the result of a descriptor read operation.
-     *
-     * @param gatt       GATT client invoked {@link BluetoothGatt#readDescriptor}
-     * @param descriptor Descriptor that was read from the associated remote device.
-     * @param status     {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
-     *                   successfully
-     * @deprecated Use {@link BluetoothGattCallback#onDescriptorRead(BluetoothGatt,
-     * BluetoothGattDescriptor, int, byte[])} as it is memory safe by providing the descriptor
-     * value at the time it was read.
-     */
-    @Deprecated
-    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-            int status) {
-    }
-
-    /**
-     * Callback reporting the result of a descriptor read operation.
-     *
-     * @param gatt       GATT client invoked {@link BluetoothGatt#readDescriptor}
-     * @param descriptor Descriptor that was read from the associated remote device.
-     * @param status     {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
-     *                   successfully
-     * @param value      the descriptor value at the time of the read operation
-     */
-    public void onDescriptorRead(@NonNull BluetoothGatt gatt,
-            @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) {
-    }
-
-    /**
-     * Callback indicating the result of a descriptor write operation.
-     *
-     * @param gatt       GATT client invoked {@link BluetoothGatt#writeDescriptor}
-     * @param descriptor Descriptor that was writte to the associated remote device.
-     * @param status     The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
-     *                   operation succeeds.
-     */
-    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-            int status) {
-    }
-
-    /**
-     * Callback invoked when a reliable write transaction has been completed.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write transaction was
-     * executed successfully
-     */
-    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
-    }
-
-    /**
-     * Callback reporting the RSSI for a remote device connection.
-     *
-     * This callback is triggered in response to the
-     * {@link BluetoothGatt#readRemoteRssi} function.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
-     * @param rssi The RSSI value for the remote device
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
-     */
-    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
-    }
-
-    /**
-     * Callback indicating the MTU for a given device connection has changed.
-     *
-     * This callback is triggered in response to the
-     * {@link BluetoothGatt#requestMtu} function, or in response to a connection
-     * event.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
-     * @param mtu The new MTU size
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
-     */
-    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
-    }
-
-    /**
-     * Callback indicating the connection parameters were updated.
-     *
-     * @param gatt GATT client involved
-     * @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from
-     * 6 (7.5ms) to 3200 (4000ms).
-     * @param latency Worker latency for the connection in number of connection events. Valid range
-     * is from 0 to 499
-     * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10
-     * (0.1s) to 3200 (32s)
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
-     * successfully
-     * @hide
-     */
-    public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout,
-            int status) {
-    }
-
-    /**
-     * Callback indicating service changed event is received
-     *
-     * <p>Receiving this event means that the GATT database is out of sync with
-     * the remote device. {@link BluetoothGatt#discoverServices} should be
-     * called to re-discover the services.
-     *
-     * @param gatt GATT client involved
-     */
-    public void onServiceChanged(@NonNull BluetoothGatt gatt) {
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
deleted file mode 100644
index c5e986e..0000000
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.compat.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Characteristic
- *
- * <p>A GATT characteristic is a basic data element used to construct a GATT service,
- * {@link BluetoothGattService}. The characteristic contains a value as well as
- * additional information and optional GATT descriptors, {@link BluetoothGattDescriptor}.
- */
-public class BluetoothGattCharacteristic implements Parcelable {
-
-    /**
-     * Characteristic proprty: Characteristic is broadcastable.
-     */
-    public static final int PROPERTY_BROADCAST = 0x01;
-
-    /**
-     * Characteristic property: Characteristic is readable.
-     */
-    public static final int PROPERTY_READ = 0x02;
-
-    /**
-     * Characteristic property: Characteristic can be written without response.
-     */
-    public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04;
-
-    /**
-     * Characteristic property: Characteristic can be written.
-     */
-    public static final int PROPERTY_WRITE = 0x08;
-
-    /**
-     * Characteristic property: Characteristic supports notification
-     */
-    public static final int PROPERTY_NOTIFY = 0x10;
-
-    /**
-     * Characteristic property: Characteristic supports indication
-     */
-    public static final int PROPERTY_INDICATE = 0x20;
-
-    /**
-     * Characteristic property: Characteristic supports write with signature
-     */
-    public static final int PROPERTY_SIGNED_WRITE = 0x40;
-
-    /**
-     * Characteristic property: Characteristic has extended properties
-     */
-    public static final int PROPERTY_EXTENDED_PROPS = 0x80;
-
-    /**
-     * Characteristic read permission
-     */
-    public static final int PERMISSION_READ = 0x01;
-
-    /**
-     * Characteristic permission: Allow encrypted read operations
-     */
-    public static final int PERMISSION_READ_ENCRYPTED = 0x02;
-
-    /**
-     * Characteristic permission: Allow reading with person-in-the-middle protection
-     */
-    public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04;
-
-    /**
-     * Characteristic write permission
-     */
-    public static final int PERMISSION_WRITE = 0x10;
-
-    /**
-     * Characteristic permission: Allow encrypted writes
-     */
-    public static final int PERMISSION_WRITE_ENCRYPTED = 0x20;
-
-    /**
-     * Characteristic permission: Allow encrypted writes with person-in-the-middle
-     * protection
-     */
-    public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40;
-
-    /**
-     * Characteristic permission: Allow signed write operations
-     */
-    public static final int PERMISSION_WRITE_SIGNED = 0x80;
-
-    /**
-     * Characteristic permission: Allow signed write operations with
-     * person-in-the-middle protection
-     */
-    public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100;
-
-    /**
-     * Write characteristic, requesting acknoledgement by the remote device
-     */
-    public static final int WRITE_TYPE_DEFAULT = 0x02;
-
-    /**
-     * Write characteristic without requiring a response by the remote device
-     */
-    public static final int WRITE_TYPE_NO_RESPONSE = 0x01;
-
-    /**
-     * Write characteristic including authentication signature
-     */
-    public static final int WRITE_TYPE_SIGNED = 0x04;
-
-    /**
-     * Characteristic value format type uint8
-     */
-    public static final int FORMAT_UINT8 = 0x11;
-
-    /**
-     * Characteristic value format type uint16
-     */
-    public static final int FORMAT_UINT16 = 0x12;
-
-    /**
-     * Characteristic value format type uint32
-     */
-    public static final int FORMAT_UINT32 = 0x14;
-
-    /**
-     * Characteristic value format type sint8
-     */
-    public static final int FORMAT_SINT8 = 0x21;
-
-    /**
-     * Characteristic value format type sint16
-     */
-    public static final int FORMAT_SINT16 = 0x22;
-
-    /**
-     * Characteristic value format type sint32
-     */
-    public static final int FORMAT_SINT32 = 0x24;
-
-    /**
-     * Characteristic value format type sfloat (16-bit float)
-     */
-    public static final int FORMAT_SFLOAT = 0x32;
-
-    /**
-     * Characteristic value format type float (32-bit float)
-     */
-    public static final int FORMAT_FLOAT = 0x34;
-
-
-    /**
-     * The UUID of this characteristic.
-     *
-     * @hide
-     */
-    protected UUID mUuid;
-
-    /**
-     * Instance ID for this characteristic.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    protected int mInstance;
-
-    /**
-     * Characteristic properties.
-     *
-     * @hide
-     */
-    protected int mProperties;
-
-    /**
-     * Characteristic permissions.
-     *
-     * @hide
-     */
-    protected int mPermissions;
-
-    /**
-     * Key size (default = 16).
-     *
-     * @hide
-     */
-    protected int mKeySize = 16;
-
-    /**
-     * Write type for this characteristic.
-     * See WRITE_TYPE_* constants.
-     *
-     * @hide
-     */
-    protected int mWriteType;
-
-    /**
-     * Back-reference to the service this characteristic belongs to.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    protected BluetoothGattService mService;
-
-    /**
-     * The cached value of this characteristic.
-     *
-     * @hide
-     */
-    protected byte[] mValue;
-
-    /**
-     * List of descriptors included in this characteristic.
-     */
-    protected List<BluetoothGattDescriptor> mDescriptors;
-
-    /**
-     * Create a new BluetoothGattCharacteristic.
-     *
-     * @param uuid The UUID for this characteristic
-     * @param properties Properties of this characteristic
-     * @param permissions Permissions for this characteristic
-     */
-    public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
-        initCharacteristic(null, uuid, 0, properties, permissions);
-    }
-
-    /**
-     * Create a new BluetoothGattCharacteristic
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
-            UUID uuid, int instanceId,
-            int properties, int permissions) {
-        initCharacteristic(service, uuid, instanceId, properties, permissions);
-    }
-
-    /**
-     * Create a new BluetoothGattCharacteristic
-     *
-     * @hide
-     */
-    public BluetoothGattCharacteristic(UUID uuid, int instanceId,
-            int properties, int permissions) {
-        initCharacteristic(null, uuid, instanceId, properties, permissions);
-    }
-
-    private void initCharacteristic(BluetoothGattService service,
-            UUID uuid, int instanceId,
-            int properties, int permissions) {
-        mUuid = uuid;
-        mInstance = instanceId;
-        mProperties = properties;
-        mPermissions = permissions;
-        mService = service;
-        mValue = null;
-        mDescriptors = new ArrayList<BluetoothGattDescriptor>();
-
-        if ((mProperties & PROPERTY_WRITE_NO_RESPONSE) != 0) {
-            mWriteType = WRITE_TYPE_NO_RESPONSE;
-        } else {
-            mWriteType = WRITE_TYPE_DEFAULT;
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(new ParcelUuid(mUuid), 0);
-        out.writeInt(mInstance);
-        out.writeInt(mProperties);
-        out.writeInt(mPermissions);
-        out.writeInt(mKeySize);
-        out.writeInt(mWriteType);
-        out.writeTypedList(mDescriptors);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattCharacteristic> CREATOR =
-            new Parcelable.Creator<BluetoothGattCharacteristic>() {
-        public BluetoothGattCharacteristic createFromParcel(Parcel in) {
-            return new BluetoothGattCharacteristic(in);
-        }
-
-        public BluetoothGattCharacteristic[] newArray(int size) {
-            return new BluetoothGattCharacteristic[size];
-        }
-    };
-
-    private BluetoothGattCharacteristic(Parcel in) {
-        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
-        mInstance = in.readInt();
-        mProperties = in.readInt();
-        mPermissions = in.readInt();
-        mKeySize = in.readInt();
-        mWriteType = in.readInt();
-
-        mDescriptors = new ArrayList<BluetoothGattDescriptor>();
-
-        ArrayList<BluetoothGattDescriptor> descs =
-                in.createTypedArrayList(BluetoothGattDescriptor.CREATOR);
-        if (descs != null) {
-            for (BluetoothGattDescriptor desc : descs) {
-                desc.setCharacteristic(this);
-                mDescriptors.add(desc);
-            }
-        }
-    }
-
-    /**
-     * Returns the desired key size.
-     *
-     * @hide
-     */
-    public int getKeySize() {
-        return mKeySize;
-    }
-
-    /**
-     * Adds a descriptor to this characteristic.
-     *
-     * @param descriptor Descriptor to be added to this characteristic.
-     * @return true, if the descriptor was added to the characteristic
-     */
-    public boolean addDescriptor(BluetoothGattDescriptor descriptor) {
-        mDescriptors.add(descriptor);
-        descriptor.setCharacteristic(this);
-        return true;
-    }
-
-    /**
-     * Get a descriptor by UUID and isntance id.
-     *
-     * @hide
-     */
-    /*package*/  BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) {
-        for (BluetoothGattDescriptor descriptor : mDescriptors) {
-            if (descriptor.getUuid().equals(uuid)
-                    && descriptor.getInstanceId() == instanceId) {
-                return descriptor;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the service this characteristic belongs to.
-     *
-     * @return The asscociated service
-     */
-    public BluetoothGattService getService() {
-        return mService;
-    }
-
-    /**
-     * Sets the service associated with this device.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    /*package*/ void setService(BluetoothGattService service) {
-        mService = service;
-    }
-
-    /**
-     * Returns the UUID of this characteristic
-     *
-     * @return UUID of this characteristic
-     */
-    public UUID getUuid() {
-        return mUuid;
-    }
-
-    /**
-     * Returns the instance ID for this characteristic.
-     *
-     * <p>If a remote device offers multiple characteristics with the same UUID,
-     * the instance ID is used to distuinguish between characteristics.
-     *
-     * @return Instance ID of this characteristic
-     */
-    public int getInstanceId() {
-        return mInstance;
-    }
-
-    /**
-     * Force the instance ID.
-     *
-     * @hide
-     */
-    public void setInstanceId(int instanceId) {
-        mInstance = instanceId;
-    }
-
-    /**
-     * Returns the properties of this characteristic.
-     *
-     * <p>The properties contain a bit mask of property flags indicating
-     * the features of this characteristic.
-     *
-     * @return Properties of this characteristic
-     */
-    public int getProperties() {
-        return mProperties;
-    }
-
-    /**
-     * Returns the permissions for this characteristic.
-     *
-     * @return Permissions of this characteristic
-     */
-    public int getPermissions() {
-        return mPermissions;
-    }
-
-    /**
-     * Gets the write type for this characteristic.
-     *
-     * @return Write type for this characteristic
-     */
-    public int getWriteType() {
-        return mWriteType;
-    }
-
-    /**
-     * Set the write type for this characteristic
-     *
-     * <p>Setting the write type of a characteristic determines how the
-     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function
-     * write this characteristic.
-     *
-     * @param writeType The write type to for this characteristic. Can be one of: {@link
-     * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}.
-     */
-    public void setWriteType(int writeType) {
-        mWriteType = writeType;
-    }
-
-    /**
-     * Set the desired key size.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setKeySize(int keySize) {
-        mKeySize = keySize;
-    }
-
-    /**
-     * Returns a list of descriptors for this characteristic.
-     *
-     * @return Descriptors for this characteristic
-     */
-    public List<BluetoothGattDescriptor> getDescriptors() {
-        return mDescriptors;
-    }
-
-    /**
-     * Returns a descriptor with a given UUID out of the list of
-     * descriptors for this characteristic.
-     *
-     * @return GATT descriptor object or null if no descriptor with the given UUID was found.
-     */
-    public BluetoothGattDescriptor getDescriptor(UUID uuid) {
-        for (BluetoothGattDescriptor descriptor : mDescriptors) {
-            if (descriptor.getUuid().equals(uuid)) {
-                return descriptor;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Get the stored value for this characteristic.
-     *
-     * <p>This function returns the stored value for this characteristic as
-     * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
-     * value of the characteristic is updated as a result of a read characteristic
-     * operation or if a characteristic update notification has been received.
-     *
-     * @return Cached value of the characteristic
-     *
-     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} instead
-     */
-    @Deprecated
-    public byte[] getValue() {
-        return mValue;
-    }
-
-    /**
-     * Return the stored value of this characteristic.
-     *
-     * <p>The formatType parameter determines how the characteristic value
-     * is to be interpreted. For example, settting formatType to
-     * {@link #FORMAT_UINT16} specifies that the first two bytes of the
-     * characteristic value at the given offset are interpreted to generate the
-     * return value.
-     *
-     * @param formatType The format type used to interpret the characteristic value.
-     * @param offset Offset at which the integer value can be found.
-     * @return Cached value of the characteristic or null of offset exceeds value size.
-     *
-     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
-     * the characteristic value
-     */
-    @Deprecated
-    public Integer getIntValue(int formatType, int offset) {
-        if ((offset + getTypeLen(formatType)) > mValue.length) return null;
-
-        switch (formatType) {
-            case FORMAT_UINT8:
-                return unsignedByteToInt(mValue[offset]);
-
-            case FORMAT_UINT16:
-                return unsignedBytesToInt(mValue[offset], mValue[offset + 1]);
-
-            case FORMAT_UINT32:
-                return unsignedBytesToInt(mValue[offset], mValue[offset + 1],
-                        mValue[offset + 2], mValue[offset + 3]);
-            case FORMAT_SINT8:
-                return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8);
-
-            case FORMAT_SINT16:
-                return unsignedToSigned(unsignedBytesToInt(mValue[offset],
-                        mValue[offset + 1]), 16);
-
-            case FORMAT_SINT32:
-                return unsignedToSigned(unsignedBytesToInt(mValue[offset],
-                        mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]), 32);
-        }
-
-        return null;
-    }
-
-    /**
-     * Return the stored value of this characteristic.
-     * <p>See {@link #getValue} for details.
-     *
-     * @param formatType The format type used to interpret the characteristic value.
-     * @param offset Offset at which the float value can be found.
-     * @return Cached value of the characteristic at a given offset or null if the requested offset
-     * exceeds the value size.
-     *
-     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
-     * the characteristic value
-     */
-    @Deprecated
-    public Float getFloatValue(int formatType, int offset) {
-        if ((offset + getTypeLen(formatType)) > mValue.length) return null;
-
-        switch (formatType) {
-            case FORMAT_SFLOAT:
-                return bytesToFloat(mValue[offset], mValue[offset + 1]);
-
-            case FORMAT_FLOAT:
-                return bytesToFloat(mValue[offset], mValue[offset + 1],
-                        mValue[offset + 2], mValue[offset + 3]);
-        }
-
-        return null;
-    }
-
-    /**
-     * Return the stored value of this characteristic.
-     * <p>See {@link #getValue} for details.
-     *
-     * @param offset Offset at which the string value can be found.
-     * @return Cached value of the characteristic
-     *
-     * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
-     * the characteristic value
-     */
-    @Deprecated
-    public String getStringValue(int offset) {
-        if (mValue == null || offset > mValue.length) return null;
-        byte[] strBytes = new byte[mValue.length - offset];
-        for (int i = 0; i != (mValue.length - offset); ++i) strBytes[i] = mValue[offset + i];
-        return new String(strBytes);
-    }
-
-    /**
-     * Updates the locally stored value of this characteristic.
-     *
-     * <p>This function modifies the locally stored cached value of this
-     * characteristic. To send the value to the remote device, call
-     * {@link BluetoothGatt#writeCharacteristic} to send the value to the
-     * remote device.
-     *
-     * @param value New value for this characteristic
-     * @return true if the locally stored value has been set, false if the requested value could not
-     * be stored locally.
-     *
-     * @deprecated Pass the characteristic value directly into
-     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
-     */
-    @Deprecated
-    public boolean setValue(byte[] value) {
-        mValue = value;
-        return true;
-    }
-
-    /**
-     * Set the locally stored value of this characteristic.
-     * <p>See {@link #setValue(byte[])} for details.
-     *
-     * @param value New value for this characteristic
-     * @param formatType Integer format type used to transform the value parameter
-     * @param offset Offset at which the value should be placed
-     * @return true if the locally stored value has been set
-     *
-     * @deprecated Pass the characteristic value directly into
-     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
-     */
-    @Deprecated
-    public boolean setValue(int value, int formatType, int offset) {
-        int len = offset + getTypeLen(formatType);
-        if (mValue == null) mValue = new byte[len];
-        if (len > mValue.length) return false;
-
-        switch (formatType) {
-            case FORMAT_SINT8:
-                value = intToSignedBits(value, 8);
-                // Fall-through intended
-            case FORMAT_UINT8:
-                mValue[offset] = (byte) (value & 0xFF);
-                break;
-
-            case FORMAT_SINT16:
-                value = intToSignedBits(value, 16);
-                // Fall-through intended
-            case FORMAT_UINT16:
-                mValue[offset++] = (byte) (value & 0xFF);
-                mValue[offset] = (byte) ((value >> 8) & 0xFF);
-                break;
-
-            case FORMAT_SINT32:
-                value = intToSignedBits(value, 32);
-                // Fall-through intended
-            case FORMAT_UINT32:
-                mValue[offset++] = (byte) (value & 0xFF);
-                mValue[offset++] = (byte) ((value >> 8) & 0xFF);
-                mValue[offset++] = (byte) ((value >> 16) & 0xFF);
-                mValue[offset] = (byte) ((value >> 24) & 0xFF);
-                break;
-
-            default:
-                return false;
-        }
-        return true;
-    }
-
-    /**
-     * Set the locally stored value of this characteristic.
-     * <p>See {@link #setValue(byte[])} for details.
-     *
-     * @param mantissa Mantissa for this characteristic
-     * @param exponent exponent value for this characteristic
-     * @param formatType Float format type used to transform the value parameter
-     * @param offset Offset at which the value should be placed
-     * @return true if the locally stored value has been set
-     *
-     * @deprecated Pass the characteristic value directly into
-     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
-     */
-    @Deprecated
-    public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
-        int len = offset + getTypeLen(formatType);
-        if (mValue == null) mValue = new byte[len];
-        if (len > mValue.length) return false;
-
-        switch (formatType) {
-            case FORMAT_SFLOAT:
-                mantissa = intToSignedBits(mantissa, 12);
-                exponent = intToSignedBits(exponent, 4);
-                mValue[offset++] = (byte) (mantissa & 0xFF);
-                mValue[offset] = (byte) ((mantissa >> 8) & 0x0F);
-                mValue[offset] += (byte) ((exponent & 0x0F) << 4);
-                break;
-
-            case FORMAT_FLOAT:
-                mantissa = intToSignedBits(mantissa, 24);
-                exponent = intToSignedBits(exponent, 8);
-                mValue[offset++] = (byte) (mantissa & 0xFF);
-                mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF);
-                mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF);
-                mValue[offset] += (byte) (exponent & 0xFF);
-                break;
-
-            default:
-                return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Set the locally stored value of this characteristic.
-     * <p>See {@link #setValue(byte[])} for details.
-     *
-     * @param value New value for this characteristic
-     * @return true if the locally stored value has been set
-     *
-     * @deprecated Pass the characteristic value directly into
-     * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
-     */
-    @Deprecated
-    public boolean setValue(String value) {
-        mValue = value.getBytes();
-        return true;
-    }
-
-    /**
-     * Returns the size of a give value type.
-     */
-    private int getTypeLen(int formatType) {
-        return formatType & 0xF;
-    }
-
-    /**
-     * Convert a signed byte to an unsigned int.
-     */
-    private int unsignedByteToInt(byte b) {
-        return b & 0xFF;
-    }
-
-    /**
-     * Convert signed bytes to a 16-bit unsigned int.
-     */
-    private int unsignedBytesToInt(byte b0, byte b1) {
-        return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
-    }
-
-    /**
-     * Convert signed bytes to a 32-bit unsigned int.
-     */
-    private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
-        return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
-                + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
-    }
-
-    /**
-     * Convert signed bytes to a 16-bit short float value.
-     */
-    private float bytesToFloat(byte b0, byte b1) {
-        int mantissa = unsignedToSigned(unsignedByteToInt(b0)
-                + ((unsignedByteToInt(b1) & 0x0F) << 8), 12);
-        int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4);
-        return (float) (mantissa * Math.pow(10, exponent));
-    }
-
-    /**
-     * Convert signed bytes to a 32-bit short float value.
-     */
-    private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
-        int mantissa = unsignedToSigned(unsignedByteToInt(b0)
-                + (unsignedByteToInt(b1) << 8)
-                + (unsignedByteToInt(b2) << 16), 24);
-        return (float) (mantissa * Math.pow(10, b3));
-    }
-
-    /**
-     * Convert an unsigned integer value to a two's-complement encoded
-     * signed value.
-     */
-    private int unsignedToSigned(int unsigned, int size) {
-        if ((unsigned & (1 << size - 1)) != 0) {
-            unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1)));
-        }
-        return unsigned;
-    }
-
-    /**
-     * Convert an integer into the signed bits of a given length.
-     */
-    private int intToSignedBits(int i, int size) {
-        if (i < 0) {
-            i = (1 << size - 1) + (i & ((1 << size - 1) - 1));
-        }
-        return i;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
deleted file mode 100644
index a35d5b9..0000000
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.compat.annotation.UnsupportedAppUsage;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Descriptor
- *
- * <p> GATT Descriptors contain additional information and attributes of a GATT
- * characteristic, {@link BluetoothGattCharacteristic}. They can be used to describe
- * the characteristic's features or to control certain behaviours of the characteristic.
- */
-public class BluetoothGattDescriptor implements Parcelable {
-
-    /**
-     * Value used to enable notification for a client configuration descriptor
-     */
-    public static final byte[] ENABLE_NOTIFICATION_VALUE = {0x01, 0x00};
-
-    /**
-     * Value used to enable indication for a client configuration descriptor
-     */
-    public static final byte[] ENABLE_INDICATION_VALUE = {0x02, 0x00};
-
-    /**
-     * Value used to disable notifications or indicatinos
-     */
-    public static final byte[] DISABLE_NOTIFICATION_VALUE = {0x00, 0x00};
-
-    /**
-     * Descriptor read permission
-     */
-    public static final int PERMISSION_READ = 0x01;
-
-    /**
-     * Descriptor permission: Allow encrypted read operations
-     */
-    public static final int PERMISSION_READ_ENCRYPTED = 0x02;
-
-    /**
-     * Descriptor permission: Allow reading with person-in-the-middle protection
-     */
-    public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04;
-
-    /**
-     * Descriptor write permission
-     */
-    public static final int PERMISSION_WRITE = 0x10;
-
-    /**
-     * Descriptor permission: Allow encrypted writes
-     */
-    public static final int PERMISSION_WRITE_ENCRYPTED = 0x20;
-
-    /**
-     * Descriptor permission: Allow encrypted writes with person-in-the-middle
-     * protection
-     */
-    public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40;
-
-    /**
-     * Descriptor permission: Allow signed write operations
-     */
-    public static final int PERMISSION_WRITE_SIGNED = 0x80;
-
-    /**
-     * Descriptor permission: Allow signed write operations with
-     * person-in-the-middle protection
-     */
-    public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100;
-
-    /**
-     * The UUID of this descriptor.
-     *
-     * @hide
-     */
-    protected UUID mUuid;
-
-    /**
-     * Instance ID for this descriptor.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    protected int mInstance;
-
-    /**
-     * Permissions for this descriptor
-     *
-     * @hide
-     */
-    protected int mPermissions;
-
-    /**
-     * Back-reference to the characteristic this descriptor belongs to.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    protected BluetoothGattCharacteristic mCharacteristic;
-
-    /**
-     * The value for this descriptor.
-     *
-     * @hide
-     */
-    protected byte[] mValue;
-
-    /**
-     * Create a new BluetoothGattDescriptor.
-     *
-     * @param uuid The UUID for this descriptor
-     * @param permissions Permissions for this descriptor
-     */
-    public BluetoothGattDescriptor(UUID uuid, int permissions) {
-        initDescriptor(null, uuid, 0, permissions);
-    }
-
-    /**
-     * Create a new BluetoothGattDescriptor.
-     *
-     * @param characteristic The characteristic this descriptor belongs to
-     * @param uuid The UUID for this descriptor
-     * @param permissions Permissions for this descriptor
-     */
-    /*package*/ BluetoothGattDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
-            int instance, int permissions) {
-        initDescriptor(characteristic, uuid, instance, permissions);
-    }
-
-    /**
-     * @hide
-     */
-    public BluetoothGattDescriptor(UUID uuid, int instance, int permissions) {
-        initDescriptor(null, uuid, instance, permissions);
-    }
-
-    private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
-            int instance, int permissions) {
-        mCharacteristic = characteristic;
-        mUuid = uuid;
-        mInstance = instance;
-        mPermissions = permissions;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(new ParcelUuid(mUuid), 0);
-        out.writeInt(mInstance);
-        out.writeInt(mPermissions);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattDescriptor> CREATOR =
-            new Parcelable.Creator<BluetoothGattDescriptor>() {
-        public BluetoothGattDescriptor createFromParcel(Parcel in) {
-            return new BluetoothGattDescriptor(in);
-        }
-
-        public BluetoothGattDescriptor[] newArray(int size) {
-            return new BluetoothGattDescriptor[size];
-        }
-    };
-
-    private BluetoothGattDescriptor(Parcel in) {
-        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
-        mInstance = in.readInt();
-        mPermissions = in.readInt();
-    }
-
-    /**
-     * Returns the characteristic this descriptor belongs to.
-     *
-     * @return The characteristic.
-     */
-    public BluetoothGattCharacteristic getCharacteristic() {
-        return mCharacteristic;
-    }
-
-    /**
-     * Set the back-reference to the associated characteristic
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
-        mCharacteristic = characteristic;
-    }
-
-    /**
-     * Returns the UUID of this descriptor.
-     *
-     * @return UUID of this descriptor
-     */
-    public UUID getUuid() {
-        return mUuid;
-    }
-
-    /**
-     * Returns the instance ID for this descriptor.
-     *
-     * <p>If a remote device offers multiple descriptors with the same UUID,
-     * the instance ID is used to distuinguish between descriptors.
-     *
-     * @return Instance ID of this descriptor
-     * @hide
-     */
-    public int getInstanceId() {
-        return mInstance;
-    }
-
-    /**
-     * Force the instance ID.
-     *
-     * @hide
-     */
-    public void setInstanceId(int instanceId) {
-        mInstance = instanceId;
-    }
-
-    /**
-     * Returns the permissions for this descriptor.
-     *
-     * @return Permissions of this descriptor
-     */
-    public int getPermissions() {
-        return mPermissions;
-    }
-
-    /**
-     * Returns the stored value for this descriptor
-     *
-     * <p>This function returns the stored value for this descriptor as
-     * retrieved by calling {@link BluetoothGatt#readDescriptor}. The cached
-     * value of the descriptor is updated as a result of a descriptor read
-     * operation.
-     *
-     * @return Cached value of the descriptor
-     *
-     * @deprecated  Use {@link BluetoothGatt#readDescriptor(BluetoothGattDescriptor)} instead
-     */
-    @Deprecated
-    public byte[] getValue() {
-        return mValue;
-    }
-
-    /**
-     * Updates the locally stored value of this descriptor.
-     *
-     * <p>This function modifies the locally stored cached value of this
-     * descriptor. To send the value to the remote device, call
-     * {@link BluetoothGatt#writeDescriptor} to send the value to the
-     * remote device.
-     *
-     * @param value New value for this descriptor
-     * @return true if the locally stored value has been set, false if the requested value could not
-     * be stored locally.
-     *
-     * @deprecated Pass the descriptor value directly into
-     * {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])}
-     */
-    @Deprecated
-    public boolean setValue(byte[] value) {
-        mValue = value;
-        return true;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattIncludedService.java b/core/java/android/bluetooth/BluetoothGattIncludedService.java
deleted file mode 100644
index 5580619..0000000
--- a/core/java/android/bluetooth/BluetoothGattIncludedService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Included Service
- *
- * @hide
- */
-public class BluetoothGattIncludedService implements Parcelable {
-
-    /**
-     * The UUID of this service.
-     */
-    protected UUID mUuid;
-
-    /**
-     * Instance ID for this service.
-     */
-    protected int mInstanceId;
-
-    /**
-     * Service type (Primary/Secondary).
-     */
-    protected int mServiceType;
-
-    /**
-     * Create a new BluetoothGattIncludedService
-     */
-    public BluetoothGattIncludedService(UUID uuid, int instanceId, int serviceType) {
-        mUuid = uuid;
-        mInstanceId = instanceId;
-        mServiceType = serviceType;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(new ParcelUuid(mUuid), 0);
-        out.writeInt(mInstanceId);
-        out.writeInt(mServiceType);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattIncludedService> CREATOR =
-            new Parcelable.Creator<BluetoothGattIncludedService>() {
-        public BluetoothGattIncludedService createFromParcel(Parcel in) {
-            return new BluetoothGattIncludedService(in);
-        }
-
-        public BluetoothGattIncludedService[] newArray(int size) {
-            return new BluetoothGattIncludedService[size];
-        }
-    };
-
-    private BluetoothGattIncludedService(Parcel in) {
-        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
-        mInstanceId = in.readInt();
-        mServiceType = in.readInt();
-    }
-
-    /**
-     * Returns the UUID of this service
-     *
-     * @return UUID of this service
-     */
-    public UUID getUuid() {
-        return mUuid;
-    }
-
-    /**
-     * Returns the instance ID for this service
-     *
-     * <p>If a remote device offers multiple services with the same UUID
-     * (ex. multiple battery services for different batteries), the instance
-     * ID is used to distuinguish services.
-     *
-     * @return Instance ID of this service
-     */
-    public int getInstanceId() {
-        return mInstanceId;
-    }
-
-    /**
-     * Get the type of this service (primary/secondary)
-     */
-    public int getType() {
-        return mServiceType;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
deleted file mode 100644
index 08e0178..0000000
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Public API for the Bluetooth GATT Profile server role.
- *
- * <p>This class provides Bluetooth GATT server role functionality,
- * allowing applications to create Bluetooth Smart services and
- * characteristics.
- *
- * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
- * via IPC.  Use {@link BluetoothManager#openGattServer} to get an instance
- * of this class.
- */
-public final class BluetoothGattServer implements BluetoothProfile {
-    private static final String TAG = "BluetoothGattServer";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    private final IBluetoothGatt mService;
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-
-    private BluetoothGattServerCallback mCallback;
-
-    private Object mServerIfLock = new Object();
-    private int mServerIf;
-    private int mTransport;
-    private BluetoothGattService mPendingService;
-    private List<BluetoothGattService> mServices;
-
-    private static final int CALLBACK_REG_TIMEOUT = 10000;
-
-    /**
-     * Bluetooth GATT interface callbacks
-     */
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
-            new IBluetoothGattServerCallback.Stub() {
-                /**
-                 * Application interface registered - app is ready to go
-                 * @hide
-                 */
-                @Override
-                public void onServerRegistered(int status, int serverIf) {
-                    if (DBG) {
-                        Log.d(TAG, "onServerRegistered() - status=" + status
-                                + " serverIf=" + serverIf);
-                    }
-                    synchronized (mServerIfLock) {
-                        if (mCallback != null) {
-                            mServerIf = serverIf;
-                            mServerIfLock.notify();
-                        } else {
-                            // registration timeout
-                            Log.e(TAG, "onServerRegistered: mCallback is null");
-                        }
-                    }
-                }
-
-                /**
-                 * Server connection state changed
-                 * @hide
-                 */
-                @Override
-                public void onServerConnectionState(int status, int serverIf,
-                        boolean connected, String address) {
-                    if (DBG) {
-                        Log.d(TAG, "onServerConnectionState() - status=" + status
-                                + " serverIf=" + serverIf + " device=" + address);
-                    }
-                    try {
-                        mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
-                                connected ? BluetoothProfile.STATE_CONNECTED :
-                                        BluetoothProfile.STATE_DISCONNECTED);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-                }
-
-                /**
-                 * Service has been added
-                 * @hide
-                 */
-                @Override
-                public void onServiceAdded(int status, BluetoothGattService service) {
-                    if (DBG) {
-                        Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
-                                + " uuid=" + service.getUuid() + " status=" + status);
-                    }
-
-                    if (mPendingService == null) {
-                        return;
-                    }
-
-                    BluetoothGattService tmp = mPendingService;
-                    mPendingService = null;
-
-                    // Rewrite newly assigned handles to existing service.
-                    tmp.setInstanceId(service.getInstanceId());
-                    List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics();
-                    List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics();
-                    for (int i = 0; i < svc_chars.size(); i++) {
-                        BluetoothGattCharacteristic temp_char = temp_chars.get(i);
-                        BluetoothGattCharacteristic svc_char = svc_chars.get(i);
-
-                        temp_char.setInstanceId(svc_char.getInstanceId());
-
-                        List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors();
-                        List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors();
-                        for (int j = 0; j < svc_descs.size(); j++) {
-                            temp_descs.get(j).setInstanceId(svc_descs.get(j).getInstanceId());
-                        }
-                    }
-
-                    mServices.add(tmp);
-
-                    try {
-                        mCallback.onServiceAdded((int) status, tmp);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-                }
-
-                /**
-                 * Remote client characteristic read request.
-                 * @hide
-                 */
-                @Override
-                public void onCharacteristicReadRequest(String address, int transId,
-                        int offset, boolean isLong, int handle) {
-                    if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
-                    if (characteristic == null) {
-                        Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle);
-                        return;
-                    }
-
-                    try {
-                        mCallback.onCharacteristicReadRequest(device, transId, offset,
-                                characteristic);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-                }
-
-                /**
-                 * Remote client descriptor read request.
-                 * @hide
-                 */
-                @Override
-                public void onDescriptorReadRequest(String address, int transId,
-                        int offset, boolean isLong, int handle) {
-                    if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
-                    if (descriptor == null) {
-                        Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle);
-                        return;
-                    }
-
-                    try {
-                        mCallback.onDescriptorReadRequest(device, transId, offset, descriptor);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-                }
-
-                /**
-                 * Remote client characteristic write request.
-                 * @hide
-                 */
-                @Override
-                public void onCharacteristicWriteRequest(String address, int transId,
-                        int offset, int length, boolean isPrep, boolean needRsp,
-                        int handle, byte[] value) {
-                    if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle);
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
-                    if (characteristic == null) {
-                        Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle);
-                        return;
-                    }
-
-                    try {
-                        mCallback.onCharacteristicWriteRequest(device, transId, characteristic,
-                                isPrep, needRsp, offset, value);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-
-                }
-
-                /**
-                 * Remote client descriptor write request.
-                 * @hide
-                 */
-                @Override
-                public void onDescriptorWriteRequest(String address, int transId, int offset,
-                        int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
-                    if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
-                    if (descriptor == null) {
-                        Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle);
-                        return;
-                    }
-
-                    try {
-                        mCallback.onDescriptorWriteRequest(device, transId, descriptor,
-                                isPrep, needRsp, offset, value);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-                }
-
-                /**
-                 * Execute pending writes.
-                 * @hide
-                 */
-                @Override
-                public void onExecuteWrite(String address, int transId,
-                        boolean execWrite) {
-                    if (DBG) {
-                        Log.d(TAG, "onExecuteWrite() - "
-                                + "device=" + address + ", transId=" + transId
-                                + "execWrite=" + execWrite);
-                    }
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    if (device == null) return;
-
-                    try {
-                        mCallback.onExecuteWrite(device, transId, execWrite);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception in callback", ex);
-                    }
-                }
-
-                /**
-                 * A notification/indication has been sent.
-                 * @hide
-                 */
-                @Override
-                public void onNotificationSent(String address, int status) {
-                    if (VDBG) {
-                        Log.d(TAG, "onNotificationSent() - "
-                                + "device=" + address + ", status=" + status);
-                    }
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    if (device == null) return;
-
-                    try {
-                        mCallback.onNotificationSent(device, status);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception: " + ex);
-                    }
-                }
-
-                /**
-                 * The MTU for a connection has changed
-                 * @hide
-                 */
-                @Override
-                public void onMtuChanged(String address, int mtu) {
-                    if (DBG) {
-                        Log.d(TAG, "onMtuChanged() - "
-                                + "device=" + address + ", mtu=" + mtu);
-                    }
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    if (device == null) return;
-
-                    try {
-                        mCallback.onMtuChanged(device, mtu);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception: " + ex);
-                    }
-                }
-
-                /**
-                 * The PHY for a connection was updated
-                 * @hide
-                 */
-                @Override
-                public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
-                    if (DBG) {
-                        Log.d(TAG,
-                                "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
-                                        + ", rxPHy=" + rxPhy);
-                    }
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    if (device == null) return;
-
-                    try {
-                        mCallback.onPhyUpdate(device, txPhy, rxPhy, status);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception: " + ex);
-                    }
-                }
-
-                /**
-                 * The PHY for a connection was read
-                 * @hide
-                 */
-                @Override
-                public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
-                    if (DBG) {
-                        Log.d(TAG,
-                                "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
-                                        + ", rxPHy=" + rxPhy);
-                    }
-
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    if (device == null) return;
-
-                    try {
-                        mCallback.onPhyRead(device, txPhy, rxPhy, status);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception: " + ex);
-                    }
-                }
-
-                /**
-                 * Callback invoked when the given connection is updated
-                 * @hide
-                 */
-                @Override
-                public void onConnectionUpdated(String address, int interval, int latency,
-                        int timeout, int status) {
-                    if (DBG) {
-                        Log.d(TAG, "onConnectionUpdated() - Device=" + address
-                                + " interval=" + interval + " latency=" + latency
-                                + " timeout=" + timeout + " status=" + status);
-                    }
-                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                    if (device == null) return;
-
-                    try {
-                        mCallback.onConnectionUpdated(device, interval, latency,
-                                timeout, status);
-                    } catch (Exception ex) {
-                        Log.w(TAG, "Unhandled exception: " + ex);
-                    }
-                }
-
-            };
-
-    /**
-     * Create a BluetoothGattServer proxy object.
-     */
-    /* package */ BluetoothGattServer(IBluetoothGatt iGatt, int transport,
-            BluetoothAdapter adapter) {
-        mService = iGatt;
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mCallback = null;
-        mServerIf = 0;
-        mTransport = transport;
-        mServices = new ArrayList<BluetoothGattService>();
-    }
-
-    /**
-     * Returns a characteristic with given handle.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattCharacteristic getCharacteristicByHandle(int handle) {
-        for (BluetoothGattService svc : mServices) {
-            for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
-                if (charac.getInstanceId() == handle) {
-                    return charac;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns a descriptor with given handle.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattDescriptor getDescriptorByHandle(int handle) {
-        for (BluetoothGattService svc : mServices) {
-            for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
-                for (BluetoothGattDescriptor desc : charac.getDescriptors()) {
-                    if (desc.getInstanceId() == handle) {
-                        return desc;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Close this GATT server instance.
-     *
-     * Application should call this method as early as possible after it is done with
-     * this GATT server.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void close() {
-        if (DBG) Log.d(TAG, "close()");
-        unregisterCallback();
-    }
-
-    /**
-     * Register an application callback to start using GattServer.
-     *
-     * <p>This is an asynchronous call. The callback is used to notify
-     * success or failure if the function returns true.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @return true, the callback will be called to notify success or failure, false on immediate
-     * error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
-        return registerCallback(callback, false);
-    }
-
-    /**
-     * Register an application callback to start using GattServer.
-     *
-     * <p>This is an asynchronous call. The callback is used to notify
-     * success or failure if the function returns true.
-     *
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param eatt_support indicates if server can use eatt
-     * @return true, the callback will be called to notify success or failure, false on immediate
-     * error
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback,
-                                         boolean eatt_support) {
-        if (DBG) Log.d(TAG, "registerCallback()");
-        if (mService == null) {
-            Log.e(TAG, "GATT service not available");
-            return false;
-        }
-        UUID uuid = UUID.randomUUID();
-        if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
-
-        synchronized (mServerIfLock) {
-            if (mCallback != null) {
-                Log.e(TAG, "App can register callback only once");
-                return false;
-            }
-
-            mCallback = callback;
-            try {
-                mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback,
-                        eatt_support, mAttributionSource);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-                mCallback = null;
-                return false;
-            }
-
-            try {
-                mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
-            } catch (InterruptedException e) {
-                Log.e(TAG, "" + e);
-                mCallback = null;
-            }
-
-            if (mServerIf == 0) {
-                mCallback = null;
-                return false;
-            } else {
-                return true;
-            }
-        }
-    }
-
-    /**
-     * Unregister the current application and callbacks.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private void unregisterCallback() {
-        if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
-        if (mService == null || mServerIf == 0) return;
-
-        try {
-            mCallback = null;
-            mService.unregisterServer(mServerIf, mAttributionSource);
-            mServerIf = 0;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Returns a service by UUID, instance and type.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) {
-        for (BluetoothGattService svc : mServices) {
-            if (svc.getType() == type
-                    && svc.getInstanceId() == instanceId
-                    && svc.getUuid().equals(uuid)) {
-                return svc;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Initiate a connection to a Bluetooth GATT capable device.
-     *
-     * <p>The connection may not be established right away, but will be
-     * completed when the remote device is available. A
-     * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
-     * invoked when the connection state changes as a result of this function.
-     *
-     * <p>The autoConnect parameter determines whether to actively connect to
-     * the remote device, or rather passively scan and finalize the connection
-     * when the remote device is in range/available. Generally, the first ever
-     * connection to a device should be direct (autoConnect set to false) and
-     * subsequent connections to known devices should be invoked with the
-     * autoConnect parameter set to true.
-     *
-     * @param autoConnect Whether to directly connect to the remote device (false) or to
-     * automatically connect as soon as the remote device becomes available (true).
-     * @return true, if the connection attempt was initiated successfully
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connect(BluetoothDevice device, boolean autoConnect) {
-        if (DBG) {
-            Log.d(TAG,
-                    "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
-        }
-        if (mService == null || mServerIf == 0) return false;
-
-        try {
-            // autoConnect is inverse of "isDirect"
-            mService.serverConnect(
-                    mServerIf, device.getAddress(), !autoConnect, mTransport, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Disconnects an established connection, or cancels a connection attempt
-     * currently in progress.
-     *
-     * @param device Remote device
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void cancelConnection(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress());
-        if (mService == null || mServerIf == 0) return;
-
-        try {
-            mService.serverDisconnect(mServerIf, device.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Set the preferred connection PHY for this app. Please note that this is just a
-     * recommendation, whether the PHY change will happen depends on other applications peferences,
-     * local and remote controller capabilities. Controller can override these settings. <p> {@link
-     * BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even if
-     * no PHY change happens. It is also triggered when remote device updates the PHY.
-     *
-     * @param device The remote device to send this response to
-     * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}.
-     * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link
-     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
-     * BluetoothDevice#PHY_LE_CODED_MASK}.
-     * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
-     * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
-     * {@link BluetoothDevice#PHY_OPTION_S8}
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setPreferredPhy(BluetoothDevice device, int txPhy, int rxPhy, int phyOptions) {
-        try {
-            mService.serverSetPreferredPhy(mServerIf, device.getAddress(), txPhy, rxPhy,
-                    phyOptions, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
-     * in {@link BluetoothGattServerCallback#onPhyRead}
-     *
-     * @param device The remote device to send this response to
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void readPhy(BluetoothDevice device) {
-        try {
-            mService.serverReadPhy(mServerIf, device.getAddress(), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Send a response to a read or write request to a remote device.
-     *
-     * <p>This function must be invoked in when a remote read/write request
-     * is received by one of these callback methods:
-     *
-     * <ul>
-     * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
-     * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
-     * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
-     * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
-     * </ul>
-     *
-     * @param device The remote device to send this response to
-     * @param requestId The ID of the request that was received with the callback
-     * @param status The status of the request to be sent to the remote devices
-     * @param offset Value offset for partial read/write response
-     * @param value The value of the attribute that was read/written (optional)
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sendResponse(BluetoothDevice device, int requestId,
-            int status, int offset, byte[] value) {
-        if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress());
-        if (mService == null || mServerIf == 0) return false;
-
-        try {
-            mService.sendResponse(mServerIf, device.getAddress(), requestId,
-                    status, offset, value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Send a notification or indication that a local characteristic has been
-     * updated.
-     *
-     * <p>A notification or indication is sent to the remote device to signal
-     * that the characteristic has been updated. This function should be invoked
-     * for every client that requests notifications/indications by writing
-     * to the "Client Configuration" descriptor for the given characteristic.
-     *
-     * @param device The remote device to receive the notification/indication
-     * @param characteristic The local characteristic that has been updated
-     * @param confirm true to request confirmation from the client (indication), false to send a
-     * notification
-     * @return true, if the notification has been triggered successfully
-     * @throws IllegalArgumentException
-     *
-     * @deprecated Use {@link BluetoothGattServer#notifyCharacteristicChanged(BluetoothDevice,
-     * BluetoothGattCharacteristic, boolean, byte[])}  as this is not memory safe.
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean notifyCharacteristicChanged(BluetoothDevice device,
-            BluetoothGattCharacteristic characteristic, boolean confirm) {
-        return notifyCharacteristicChanged(device, characteristic, confirm,
-                characteristic.getValue()) == BluetoothStatusCodes.SUCCESS;
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            BluetoothStatusCodes.SUCCESS,
-            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
-            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
-            BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
-            BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
-            BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
-            BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
-            BluetoothStatusCodes.ERROR_UNKNOWN
-    })
-    public @interface NotifyCharacteristicReturnValues{}
-
-    /**
-     * Send a notification or indication that a local characteristic has been
-     * updated.
-     *
-     * <p>A notification or indication is sent to the remote device to signal
-     * that the characteristic has been updated. This function should be invoked
-     * for every client that requests notifications/indications by writing
-     * to the "Client Configuration" descriptor for the given characteristic.
-     *
-     * @param device the remote device to receive the notification/indication
-     * @param characteristic the local characteristic that has been updated
-     * @param confirm {@code true} to request confirmation from the client (indication) or
-     * {@code false} to send a notification
-     * @param value the characteristic value
-     * @return whether the notification has been triggered successfully
-     * @throws IllegalArgumentException if the characteristic value or service is null
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @NotifyCharacteristicReturnValues
-    public int notifyCharacteristicChanged(@NonNull BluetoothDevice device,
-            @NonNull BluetoothGattCharacteristic characteristic, boolean confirm,
-            @NonNull byte[] value) {
-        if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
-        if (mService == null || mServerIf == 0) {
-            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
-        }
-
-        if (characteristic == null) {
-            throw new IllegalArgumentException("characteristic must not be null");
-        }
-        if (device == null) {
-            throw new IllegalArgumentException("device must not be null");
-        }
-        BluetoothGattService service = characteristic.getService();
-        if (service == null) {
-            throw new IllegalArgumentException("Characteristic must have a non-null service");
-        }
-        if (value == null) {
-            throw new IllegalArgumentException("Characteristic value must not be null");
-        }
-
-        try {
-            return mService.sendNotification(mServerIf, device.getAddress(),
-                    characteristic.getInstanceId(), confirm,
-                    value, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Add a service to the list of services to be hosted.
-     *
-     * <p>Once a service has been addded to the list, the service and its
-     * included characteristics will be provided by the local device.
-     *
-     * <p>If the local device has already exposed services when this function
-     * is called, a service update notification will be sent to all clients.
-     *
-     * <p>The {@link BluetoothGattServerCallback#onServiceAdded} callback will indicate
-     * whether this service has been added successfully. Do not add another service
-     * before this callback.
-     *
-     * @param service Service to be added to the list of services provided by this device.
-     * @return true, if the request to add service has been initiated
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean addService(BluetoothGattService service) {
-        if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
-        if (mService == null || mServerIf == 0) return false;
-
-        mPendingService = service;
-
-        try {
-            mService.addService(mServerIf, service, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Removes a service from the list of services to be provided.
-     *
-     * @param service Service to be removed.
-     * @return true, if the service has been removed
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean removeService(BluetoothGattService service) {
-        if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid());
-        if (mService == null || mServerIf == 0) return false;
-
-        BluetoothGattService intService = getService(service.getUuid(),
-                service.getInstanceId(), service.getType());
-        if (intService == null) return false;
-
-        try {
-            mService.removeService(mServerIf, service.getInstanceId(), mAttributionSource);
-            mServices.remove(intService);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Remove all services from the list of provided services.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void clearServices() {
-        if (DBG) Log.d(TAG, "clearServices()");
-        if (mService == null || mServerIf == 0) return;
-
-        try {
-            mService.clearServices(mServerIf, mAttributionSource);
-            mServices.clear();
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-    }
-
-    /**
-     * Returns a list of GATT services offered by this device.
-     *
-     * <p>An application must call {@link #addService} to add a serice to the
-     * list of services offered by this device.
-     *
-     * @return List of services. Returns an empty list if no services have been added yet.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public List<BluetoothGattService> getServices() {
-        return mServices;
-    }
-
-    /**
-     * Returns a {@link BluetoothGattService} from the list of services offered
-     * by this device.
-     *
-     * <p>If multiple instances of the same service (as identified by UUID)
-     * exist, the first instance of the service is returned.
-     *
-     * @param uuid UUID of the requested service
-     * @return BluetoothGattService if supported, or null if the requested service is not offered by
-     * this device.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresNoPermission
-    public BluetoothGattService getService(UUID uuid) {
-        for (BluetoothGattService service : mServices) {
-            if (service.getUuid().equals(uuid)) {
-                return service;
-            }
-        }
-
-        return null;
-    }
-
-
-    /**
-     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
-     * with {@link BluetoothProfile#GATT} as argument
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    @RequiresNoPermission
-    public int getConnectionState(BluetoothDevice device) {
-        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
-    }
-
-    /**
-     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
-     * with {@link BluetoothProfile#GATT} as argument
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    @RequiresNoPermission
-    public List<BluetoothDevice> getConnectedDevices() {
-        throw new UnsupportedOperationException(
-                "Use BluetoothManager#getConnectedDevices instead.");
-    }
-
-    /**
-     * Not supported - please use
-     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
-     * with {@link BluetoothProfile#GATT} as first argument
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    @RequiresNoPermission
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        throw new UnsupportedOperationException(
-                "Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
deleted file mode 100644
index 0ead5f5..0000000
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- */
-public abstract class BluetoothGattServerCallback {
-
-    /**
-     * Callback indicating when a remote device has been connected or disconnected.
-     *
-     * @param device Remote device that has been connected or disconnected.
-     * @param status Status of the connect or disconnect operation.
-     * @param newState Returns the new connection state. Can be one of {@link
-     * BluetoothProfile#STATE_DISCONNECTED} or {@link BluetoothProfile#STATE_CONNECTED}
-     */
-    public void onConnectionStateChange(BluetoothDevice device, int status,
-            int newState) {
-    }
-
-    /**
-     * Indicates whether a local service has been added successfully.
-     *
-     * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service was added
-     * successfully.
-     * @param service The service that has been added
-     */
-    public void onServiceAdded(int status, BluetoothGattService service) {
-    }
-
-    /**
-     * A remote client has requested to read a local characteristic.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the read operation
-     * @param requestId The Id of the request
-     * @param offset Offset into the value of the characteristic
-     * @param characteristic Characteristic to be read
-     */
-    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
-            int offset, BluetoothGattCharacteristic characteristic) {
-    }
-
-    /**
-     * A remote client has requested to write to a local characteristic.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operation
-     * @param requestId The Id of the request
-     * @param characteristic Characteristic to be written to.
-     * @param preparedWrite true, if this write operation should be queued for later execution.
-     * @param responseNeeded true, if the remote device requires a response
-     * @param offset The offset given for the value
-     * @param value The value the client wants to assign to the characteristic
-     */
-    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
-            BluetoothGattCharacteristic characteristic,
-            boolean preparedWrite, boolean responseNeeded,
-            int offset, byte[] value) {
-    }
-
-    /**
-     * A remote client has requested to read a local descriptor.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the read operation
-     * @param requestId The Id of the request
-     * @param offset Offset into the value of the characteristic
-     * @param descriptor Descriptor to be read
-     */
-    public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
-            int offset, BluetoothGattDescriptor descriptor) {
-    }
-
-    /**
-     * A remote client has requested to write to a local descriptor.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operation
-     * @param requestId The Id of the request
-     * @param descriptor Descriptor to be written to.
-     * @param preparedWrite true, if this write operation should be queued for later execution.
-     * @param responseNeeded true, if the remote device requires a response
-     * @param offset The offset given for the value
-     * @param value The value the client wants to assign to the descriptor
-     */
-    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
-            BluetoothGattDescriptor descriptor,
-            boolean preparedWrite, boolean responseNeeded,
-            int offset, byte[] value) {
-    }
-
-    /**
-     * Execute all pending write operations for this device.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operations
-     * @param requestId The Id of the request
-     * @param execute Whether the pending writes should be executed (true) or cancelled (false)
-     */
-    public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
-    }
-
-    /**
-     * Callback invoked when a notification or indication has been sent to
-     * a remote device.
-     *
-     * <p>When multiple notifications are to be sent, an application must
-     * wait for this callback to be received before sending additional
-     * notifications.
-     *
-     * @param device The remote device the notification has been sent to
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
-     */
-    public void onNotificationSent(BluetoothDevice device, int status) {
-    }
-
-    /**
-     * Callback indicating the MTU for a given device connection has changed.
-     *
-     * <p>This callback will be invoked if a remote client has requested to change
-     * the MTU for a given connection.
-     *
-     * @param device The remote device that requested the MTU change
-     * @param mtu The new MTU size
-     */
-    public void onMtuChanged(BluetoothDevice device, int mtu) {
-    }
-
-    /**
-     * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
-     * of remote device changing the PHY.
-     *
-     * @param device The remote device
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param status Status of the PHY update operation. {@link BluetoothGatt#GATT_SUCCESS} if the
-     * operation succeeds.
-     */
-    public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback triggered as result of {@link BluetoothGattServer#readPhy}
-     *
-     * @param device The remote device that requested the PHY read
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link
-     * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param status Status of the PHY read operation. {@link BluetoothGatt#GATT_SUCCESS} if the
-     * operation succeeds.
-     */
-    public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback indicating the connection parameters were updated.
-     *
-     * @param device The remote device involved
-     * @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from
-     * 6 (7.5ms) to 3200 (4000ms).
-     * @param latency Worker latency for the connection in number of connection events. Valid range
-     * is from 0 to 499
-     * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10
-     * (0.1s) to 3200 (32s)
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
-     * successfully
-     * @hide
-     */
-    public void onConnectionUpdated(BluetoothDevice device, int interval, int latency, int timeout,
-            int status) {
-    }
-
-}
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
deleted file mode 100644
index f64d09f..0000000
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth GATT Service
- *
- * <p> Gatt Service contains a collection of {@link BluetoothGattCharacteristic},
- * as well as referenced services.
- */
-public class BluetoothGattService implements Parcelable {
-
-    /**
-     * Primary service
-     */
-    public static final int SERVICE_TYPE_PRIMARY = 0;
-
-    /**
-     * Secondary service (included by primary services)
-     */
-    public static final int SERVICE_TYPE_SECONDARY = 1;
-
-
-    /**
-     * The remote device this service is associated with.
-     * This applies to client applications only.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    protected BluetoothDevice mDevice;
-
-    /**
-     * The UUID of this service.
-     *
-     * @hide
-     */
-    protected UUID mUuid;
-
-    /**
-     * Instance ID for this service.
-     *
-     * @hide
-     */
-    protected int mInstanceId;
-
-    /**
-     * Handle counter override (for conformance testing).
-     *
-     * @hide
-     */
-    protected int mHandles = 0;
-
-    /**
-     * Service type (Primary/Secondary).
-     *
-     * @hide
-     */
-    protected int mServiceType;
-
-    /**
-     * List of characteristics included in this service.
-     */
-    protected List<BluetoothGattCharacteristic> mCharacteristics;
-
-    /**
-     * List of included services for this service.
-     */
-    protected List<BluetoothGattService> mIncludedServices;
-
-    /**
-     * Whether the service uuid should be advertised.
-     */
-    private boolean mAdvertisePreferred;
-
-    /**
-     * Create a new BluetoothGattService.
-     *
-     * @param uuid The UUID for this service
-     * @param serviceType The type of this service,
-     * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY}
-     * or {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
-     */
-    public BluetoothGattService(UUID uuid, int serviceType) {
-        mDevice = null;
-        mUuid = uuid;
-        mInstanceId = 0;
-        mServiceType = serviceType;
-        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
-        mIncludedServices = new ArrayList<BluetoothGattService>();
-    }
-
-    /**
-     * Create a new BluetoothGattService
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattService(BluetoothDevice device, UUID uuid,
-            int instanceId, int serviceType) {
-        mDevice = device;
-        mUuid = uuid;
-        mInstanceId = instanceId;
-        mServiceType = serviceType;
-        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
-        mIncludedServices = new ArrayList<BluetoothGattService>();
-    }
-
-    /**
-     * Create a new BluetoothGattService
-     *
-     * @hide
-     */
-    public BluetoothGattService(UUID uuid, int instanceId, int serviceType) {
-        mDevice = null;
-        mUuid = uuid;
-        mInstanceId = instanceId;
-        mServiceType = serviceType;
-        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
-        mIncludedServices = new ArrayList<BluetoothGattService>();
-    }
-
-    /**
-     * @hide
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(new ParcelUuid(mUuid), 0);
-        out.writeInt(mInstanceId);
-        out.writeInt(mServiceType);
-        out.writeTypedList(mCharacteristics);
-
-        ArrayList<BluetoothGattIncludedService> includedServices =
-                new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size());
-        for (BluetoothGattService s : mIncludedServices) {
-            includedServices.add(new BluetoothGattIncludedService(s.getUuid(),
-                    s.getInstanceId(), s.getType()));
-        }
-        out.writeTypedList(includedServices);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattService> CREATOR =
-            new Parcelable.Creator<BluetoothGattService>() {
-        public BluetoothGattService createFromParcel(Parcel in) {
-            return new BluetoothGattService(in);
-        }
-
-        public BluetoothGattService[] newArray(int size) {
-            return new BluetoothGattService[size];
-        }
-    };
-
-    private BluetoothGattService(Parcel in) {
-        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
-        mInstanceId = in.readInt();
-        mServiceType = in.readInt();
-
-        mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
-
-        ArrayList<BluetoothGattCharacteristic> chrcs =
-                in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR);
-        if (chrcs != null) {
-            for (BluetoothGattCharacteristic chrc : chrcs) {
-                chrc.setService(this);
-                mCharacteristics.add(chrc);
-            }
-        }
-
-        mIncludedServices = new ArrayList<BluetoothGattService>();
-
-        ArrayList<BluetoothGattIncludedService> inclSvcs =
-                in.createTypedArrayList(BluetoothGattIncludedService.CREATOR);
-        if (chrcs != null) {
-            for (BluetoothGattIncludedService isvc : inclSvcs) {
-                mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(),
-                        isvc.getInstanceId(), isvc.getType()));
-            }
-        }
-    }
-
-    /**
-     * Returns the device associated with this service.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Returns the device associated with this service.
-     *
-     * @hide
-     */
-    /*package*/ void setDevice(BluetoothDevice device) {
-        mDevice = device;
-    }
-
-    /**
-     * Add an included service to this service.
-     *
-     * @param service The service to be added
-     * @return true, if the included service was added to the service
-     */
-    @RequiresLegacyBluetoothPermission
-    public boolean addService(BluetoothGattService service) {
-        mIncludedServices.add(service);
-        return true;
-    }
-
-    /**
-     * Add a characteristic to this service.
-     *
-     * @param characteristic The characteristics to be added
-     * @return true, if the characteristic was added to the service
-     */
-    @RequiresLegacyBluetoothPermission
-    public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
-        mCharacteristics.add(characteristic);
-        characteristic.setService(this);
-        return true;
-    }
-
-    /**
-     * Get characteristic by UUID and instanceId.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) {
-        for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
-            if (uuid.equals(characteristic.getUuid())
-                    && characteristic.getInstanceId() == instanceId) {
-                return characteristic;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Force the instance ID.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setInstanceId(int instanceId) {
-        mInstanceId = instanceId;
-    }
-
-    /**
-     * Get the handle count override (conformance testing.
-     *
-     * @hide
-     */
-    /*package*/ int getHandles() {
-        return mHandles;
-    }
-
-    /**
-     * Force the number of handles to reserve for this service.
-     * This is needed for conformance testing only.
-     *
-     * @hide
-     */
-    public void setHandles(int handles) {
-        mHandles = handles;
-    }
-
-    /**
-     * Add an included service to the internal map.
-     *
-     * @hide
-     */
-    public void addIncludedService(BluetoothGattService includedService) {
-        mIncludedServices.add(includedService);
-    }
-
-    /**
-     * Returns the UUID of this service
-     *
-     * @return UUID of this service
-     */
-    public UUID getUuid() {
-        return mUuid;
-    }
-
-    /**
-     * Returns the instance ID for this service
-     *
-     * <p>If a remote device offers multiple services with the same UUID
-     * (ex. multiple battery services for different batteries), the instance
-     * ID is used to distuinguish services.
-     *
-     * @return Instance ID of this service
-     */
-    public int getInstanceId() {
-        return mInstanceId;
-    }
-
-    /**
-     * Get the type of this service (primary/secondary)
-     */
-    public int getType() {
-        return mServiceType;
-    }
-
-    /**
-     * Get the list of included GATT services for this service.
-     *
-     * @return List of included services or empty list if no included services were discovered.
-     */
-    public List<BluetoothGattService> getIncludedServices() {
-        return mIncludedServices;
-    }
-
-    /**
-     * Returns a list of characteristics included in this service.
-     *
-     * @return Characteristics included in this service
-     */
-    public List<BluetoothGattCharacteristic> getCharacteristics() {
-        return mCharacteristics;
-    }
-
-    /**
-     * Returns a characteristic with a given UUID out of the list of
-     * characteristics offered by this service.
-     *
-     * <p>This is a convenience function to allow access to a given characteristic
-     * without enumerating over the list returned by {@link #getCharacteristics}
-     * manually.
-     *
-     * <p>If a remote service offers multiple characteristics with the same
-     * UUID, the first instance of a characteristic with the given UUID
-     * is returned.
-     *
-     * @return GATT characteristic object or null if no characteristic with the given UUID was
-     * found.
-     */
-    public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
-        for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
-            if (uuid.equals(characteristic.getUuid())) {
-                return characteristic;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns whether the uuid of the service should be advertised.
-     *
-     * @hide
-     */
-    public boolean isAdvertisePreferred() {
-        return mAdvertisePreferred;
-    }
-
-    /**
-     * Set whether the service uuid should be advertised.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void setAdvertisePreferred(boolean advertisePreferred) {
-        mAdvertisePreferred = advertisePreferred;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
deleted file mode 100644
index 1b141c9..0000000
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ /dev/null
@@ -1,1505 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Public API for controlling the Bluetooth Headset Service. This includes both
- * Bluetooth Headset and Handsfree (v1.5) profiles.
- *
- * <p>BluetoothHeadset is a proxy object for controlling the Bluetooth Headset
- * Service via IPC.
- *
- * <p> Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHeadset proxy object. Use
- * {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
- *
- * <p> Android only supports one connected Bluetooth Headset at a time.
- * Each method is protected with its appropriate permission.
- */
-public final class BluetoothHeadset implements BluetoothProfile {
-    private static final String TAG = "BluetoothHeadset";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the Headset
-     * profile.
-     *
-     * <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}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the change in the Audio Connection state of the
-     * HFP profile.
-     *
-     * <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_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED},
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_AUDIO_STATE_CHANGED =
-            "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the selection of a connected device as active.
-     *
-     * <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>
-     * </ul>
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage(trackingBug = 171933273)
-    public static final String ACTION_ACTIVE_DEVICE_CHANGED =
-            "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
-
-    /**
-     * Intent used to broadcast that the headset has posted a
-     * vendor-specific event.
-     *
-     * <p>This intent will have 4 extras and 1 category.
-     * <ul>
-     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device
-     * </li>
-     * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor
-     * specific command </li>
-     * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT
-     * command type which can be one of  {@link #AT_CMD_TYPE_READ},
-     * {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET},
-     * {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li>
-     * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command
-     * arguments. </li>
-     * </ul>
-     *
-     * <p> The category is the Company ID of the vendor defining the
-     * vendor-specific command. {@link BluetoothAssignedNumbers}
-     *
-     * For example, for Plantronics specific events
-     * Category will be {@link #VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY}.55
-     *
-     * <p> For example, an AT+XEVENT=foo,3 will get translated into
-     * <ul>
-     * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li>
-     * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li>
-     * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li>
-     * </ul>
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT =
-            "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
-
-    /**
-     * A String extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
-     * intents that contains the name of the vendor-specific command.
-     */
-    public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD =
-            "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
-
-    /**
-     * An int extra field in {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
-     * intents that contains the AT command type of the vendor-specific command.
-     */
-    public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE =
-            "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
-
-    /**
-     * AT command type READ used with
-     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
-     * For example, AT+VGM?. There are no arguments for this command type.
-     */
-    public static final int AT_CMD_TYPE_READ = 0;
-
-    /**
-     * AT command type TEST used with
-     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
-     * For example, AT+VGM=?. There are no arguments for this command type.
-     */
-    public static final int AT_CMD_TYPE_TEST = 1;
-
-    /**
-     * AT command type SET used with
-     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
-     * For example, AT+VGM=<args>.
-     */
-    public static final int AT_CMD_TYPE_SET = 2;
-
-    /**
-     * AT command type BASIC used with
-     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
-     * For example, ATD. Single character commands and everything following the
-     * character are arguments.
-     */
-    public static final int AT_CMD_TYPE_BASIC = 3;
-
-    /**
-     * AT command type ACTION used with
-     * {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE}
-     * For example, AT+CHUP. There are no arguments for action commands.
-     */
-    public static final int AT_CMD_TYPE_ACTION = 4;
-
-    /**
-     * A Parcelable String array extra field in
-     * {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intents that contains
-     * the arguments to the vendor-specific command.
-     */
-    public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS =
-            "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
-
-    /**
-     * The intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT}
-     * for the companyId
-     */
-    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY =
-            "android.bluetooth.headset.intent.category.companyid";
-
-    /**
-     * A vendor-specific command for unsolicited result code.
-     */
-    public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
-
-    /**
-     * A vendor-specific AT command
-     *
-     * @hide
-     */
-    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XAPL = "+XAPL";
-
-    /**
-     * A vendor-specific AT command
-     *
-     * @hide
-     */
-    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV = "+IPHONEACCEV";
-
-    /**
-     * Battery level indicator associated with
-     * {@link #VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV}
-     *
-     * @hide
-     */
-    public static final int VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL = 1;
-
-    /**
-     * A vendor-specific AT command
-     *
-     * @hide
-     */
-    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT = "+XEVENT";
-
-    /**
-     * Battery level indicator associated with {@link #VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT}
-     *
-     * @hide
-     */
-    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY";
-
-    /**
-     * Headset state when SCO audio is not connected.
-     * This state can be one of
-     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
-     * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
-     */
-    public static final int STATE_AUDIO_DISCONNECTED = 10;
-
-    /**
-     * Headset state when SCO audio is connecting.
-     * This state can be one of
-     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
-     * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
-     */
-    public static final int STATE_AUDIO_CONNECTING = 11;
-
-    /**
-     * Headset state when SCO audio is connected.
-     * This state can be one of
-     * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
-     * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
-     */
-    public static final int STATE_AUDIO_CONNECTED = 12;
-
-    /**
-     * Intent used to broadcast the headset's indicator status
-     *
-     * <p>This intent will have 3 extras:
-     * <ul>
-     * <li> {@link #EXTRA_HF_INDICATORS_IND_ID} - The Assigned number of headset Indicator which
-     * is supported by the headset ( as indicated by AT+BIND command in the SLC
-     * sequence) or whose value is changed (indicated by AT+BIEV command) </li>
-     * <li> {@link #EXTRA_HF_INDICATORS_IND_VALUE} - Updated value of headset indicator. </li>
-     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - Remote device. </li>
-     * </ul>
-     * <p>{@link #EXTRA_HF_INDICATORS_IND_ID} is defined by Bluetooth SIG and each of the indicators
-     * are given an assigned number. Below shows the assigned number of Indicator added so far
-     * - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled
-     * - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_HF_INDICATORS_VALUE_CHANGED =
-            "android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED";
-
-    /**
-     * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED}
-     * intents that contains the assigned number of the headset indicator as defined by
-     * Bluetooth SIG that is being sent. Value range is 0-65535 as defined in HFP 1.7
-     *
-     * @hide
-     */
-    public static final String EXTRA_HF_INDICATORS_IND_ID =
-            "android.bluetooth.headset.extra.HF_INDICATORS_IND_ID";
-
-    /**
-     * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED}
-     * intents that contains the value of the Headset indicator that is being sent.
-     *
-     * @hide
-     */
-    public static final String EXTRA_HF_INDICATORS_IND_VALUE =
-            "android.bluetooth.headset.extra.HF_INDICATORS_IND_VALUE";
-
-    private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100;
-    private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101;
-
-    private final CloseGuard mCloseGuard = new CloseGuard();
-
-    private Context mContext;
-    private ServiceListener mServiceListener;
-    private volatile IBluetoothHeadset mService;
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
-            new IBluetoothStateChangeCallback.Stub() {
-                public void onBluetoothStateChange(boolean up) {
-                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
-                    if (!up) {
-                        doUnbind();
-                    } else {
-                        doBind();
-                    }
-                }
-            };
-
-    /**
-     * Create a BluetoothHeadset proxy object.
-     */
-    /* package */ BluetoothHeadset(Context context, ServiceListener l, BluetoothAdapter adapter) {
-        mContext = context;
-        mServiceListener = l;
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-
-        // Preserve legacy compatibility where apps were depending on
-        // registerStateChangeCallback() performing a permissions check which
-        // has been relaxed in modern platform versions
-        if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
-                && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
-                        != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Need BLUETOOTH permission");
-        }
-
-        IBluetoothManager mgr = mAdapter.getBluetoothManager();
-        if (mgr != null) {
-            try {
-                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-
-        doBind();
-        mCloseGuard.open("close");
-    }
-
-    private boolean doBind() {
-        synchronized (mConnection) {
-            if (mService == null) {
-                if (VDBG) Log.d(TAG, "Binding service...");
-                try {
-                    return mAdapter.getBluetoothManager().bindBluetoothProfileService(
-                            BluetoothProfile.HEADSET, mConnection);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to bind HeadsetService", e);
-                }
-            }
-        }
-        return false;
-    }
-
-    private void doUnbind() {
-        synchronized (mConnection) {
-            if (mService != null) {
-                if (VDBG) Log.d(TAG, "Unbinding service...");
-                try {
-                    mAdapter.getBluetoothManager().unbindBluetoothProfileService(
-                            BluetoothProfile.HEADSET, mConnection);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to unbind HeadsetService", e);
-                } finally {
-                    mService = null;
-                }
-            }
-        }
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothHeadset will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     */
-    @UnsupportedAppUsage
-    /*package*/ void close() {
-        if (VDBG) log("close()");
-
-        IBluetoothManager mgr = mAdapter.getBluetoothManager();
-        if (mgr != null) {
-            try {
-                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
-            } catch (RemoteException re) {
-                Log.e(TAG, "", re);
-            }
-        }
-        mServiceListener = null;
-        doUnbind();
-        mCloseGuard.close();
-    }
-
-    /** {@hide} */
-    @Override
-    protected void finalize() throws Throwable {
-        mCloseGuard.warnIfOpen();
-        close();
-    }
-
-    /**
-     * Initiate connection to a profile of the remote bluetooth device.
-     *
-     * <p> Currently, the system supports only 1 connection to the
-     * headset/handsfree profile. The API will automatically disconnect connected
-     * devices before connecting.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connectWithAttribution(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnectWithAttribution(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothHeadset service = mService;
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevicesWithAttribution(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothHeadset service = mService;
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (VDBG) log("getConnectionState(" + device + ")");
-        final IBluetoothHeadset service = mService;
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionStateWithAttribution(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or
-     * {@link BluetoothProfile#PRIORITY_OFF}
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     * @deprecated Replaced with {@link #setConnectionPolicy(BluetoothDevice, int)}
-     * @removed
-     */
-    @Deprecated
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothHeadset service = mService;
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Checks whether the headset supports some form of noise reduction
-     *
-     * @param device Bluetooth device
-     * @return true if echo cancellation and/or noise reduction is supported, false otherwise
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isNoiseReductionSupported(@NonNull BluetoothDevice device) {
-        if (DBG) log("isNoiseReductionSupported()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isNoiseReductionSupported(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Checks whether the headset supports voice recognition
-     *
-     * @param device Bluetooth device
-     * @return true if voice recognition is supported, false otherwise
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isVoiceRecognitionSupported(@NonNull BluetoothDevice device) {
-        if (DBG) log("isVoiceRecognitionSupported()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isVoiceRecognitionSupported(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Start Bluetooth voice recognition. This methods sends the voice
-     * recognition AT command to the headset and establishes the
-     * audio connection.
-     *
-     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * If this function returns true, this intent will be broadcasted with
-     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
-     *
-     * <p> {@link #EXTRA_STATE} will transition from
-     * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
-     * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
-     * in case of failure to establish the audio connection.
-     *
-     * @param device Bluetooth headset
-     * @return false if there is no headset connected, or the connected headset doesn't support
-     * voice recognition, or voice recognition is already started, or audio channel is occupied,
-     * or on error, true otherwise
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean startVoiceRecognition(BluetoothDevice device) {
-        if (DBG) log("startVoiceRecognition()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.startVoiceRecognition(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Stop Bluetooth Voice Recognition mode, and shut down the
-     * Bluetooth audio path.
-     *
-     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * If this function returns true, this intent will be broadcasted with
-     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
-     *
-     * @param device Bluetooth headset
-     * @return false if there is no headset connected, or voice recognition has not started,
-     * or voice recognition has ended on this headset, or on error, true otherwise
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean stopVoiceRecognition(BluetoothDevice device) {
-        if (DBG) log("stopVoiceRecognition()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.stopVoiceRecognition(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Check if Bluetooth SCO audio is connected.
-     *
-     * @param device Bluetooth headset
-     * @return true if SCO is connected, false otherwise or on error
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isAudioConnected(BluetoothDevice device) {
-        if (VDBG) log("isAudioConnected()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isAudioConnected(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Indicates if current platform supports voice dialing over bluetooth SCO.
-     *
-     * @return true if voice dialing over bluetooth is supported, false otherwise.
-     * @hide
-     */
-    public static boolean isBluetoothVoiceDialingEnabled(Context context) {
-        return context.getResources().getBoolean(
-                com.android.internal.R.bool.config_bluetooth_sco_off_call);
-    }
-
-    /**
-     * Get the current audio state of the Headset.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getAudioState(BluetoothDevice device) {
-        if (VDBG) log("getAudioState");
-        final IBluetoothHeadset service = mService;
-        final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (!isDisabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getAudioState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sets whether audio routing is allowed. When set to {@code false}, the AG will not route any
-     * audio to the HF unless explicitly told to.
-     * This method should be used in cases where the SCO channel is shared between multiple profiles
-     * and must be delegated by a source knowledgeable
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setAudioRouteAllowed(boolean allowed) {
-        if (VDBG) log("setAudioRouteAllowed");
-        final IBluetoothHeadset service = mService;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setAudioRouteAllowed(allowed, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Returns whether audio routing is allowed. see {@link #setAudioRouteAllowed(boolean)}.
-     * Note: This is an internal function and shouldn't be exposed
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean getAudioRouteAllowed() {
-        if (VDBG) log("getAudioRouteAllowed");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getAudioRouteAllowed(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Force SCO audio to be opened regardless any other restrictions
-     *
-     * @param forced Whether or not SCO audio connection should be forced: True to force SCO audio
-     * False to use SCO audio in normal manner
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setForceScoAudio(boolean forced) {
-        if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
-        final IBluetoothHeadset service = mService;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setForceScoAudio(forced, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Check if at least one headset's SCO audio is connected or connecting
-     *
-     * @return true if at least one device's SCO audio is connected or connecting, false otherwise
-     * or on error
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isAudioOn() {
-        if (VDBG) log("isAudioOn()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isAudioOn(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiates a connection of headset audio to the current active device
-     *
-     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * If this function returns true, this intent will be broadcasted with
-     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
-     *
-     * <p> {@link #EXTRA_STATE} will transition from
-     * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
-     * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
-     * in case of failure to establish the audio connection.
-     *
-     * Note that this intent will not be sent if {@link BluetoothHeadset#isAudioOn()} is true
-     * before calling this method
-     *
-     * @return false if there was some error such as there is no active headset
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connectAudio() {
-        if (VDBG) log("connectAudio()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connectAudio(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiates a disconnection of HFP SCO audio.
-     * Tear down voice recognition or virtual voice call if any.
-     *
-     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * If this function returns true, this intent will be broadcasted with
-     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
-     *
-     * @return false if audio is not connected, or on error, true otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnectAudio() {
-        if (VDBG) log("disconnectAudio()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnectAudio(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiates a SCO channel connection as a virtual voice call to the current active device
-     * Active handsfree device will be notified of incoming call and connected call.
-     *
-     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * If this function returns true, this intent will be broadcasted with
-     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
-     *
-     * <p> {@link #EXTRA_STATE} will transition from
-     * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
-     * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
-     * in case of failure to establish the audio connection.
-     *
-     * @return true if successful, false if one of the following case applies
-     *  - SCO audio is not idle (connecting or connected)
-     *  - virtual call has already started
-     *  - there is no active device
-     *  - a Telecom managed call is going on
-     *  - binder is dead or Bluetooth is disabled or other error
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean startScoUsingVirtualVoiceCall() {
-        if (DBG) log("startScoUsingVirtualVoiceCall()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.startScoUsingVirtualVoiceCall(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Terminates an ongoing SCO connection and the associated virtual call.
-     *
-     * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * If this function returns true, this intent will be broadcasted with
-     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
-     *
-     * @return true if successful, false if one of the following case applies
-     *  - virtual voice call is not started or has ended
-     *  - binder is dead or Bluetooth is disabled or other error
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public boolean stopScoUsingVirtualVoiceCall() {
-        if (DBG) log("stopScoUsingVirtualVoiceCall()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.stopScoUsingVirtualVoiceCall(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Notify Headset of phone state change.
-     * This is a backdoor for phone app to call BluetoothHeadset since
-     * there is currently not a good way to get precise call state change outside
-     * of phone app.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
-            int type, String name) {
-        final IBluetoothHeadset service = mService;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                service.phoneStateChanged(numActive, numHeld, callState, number, type, name,
-                        mAttributionSource);
-            } catch (RemoteException  e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Send Headset of CLCC response
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
-            String number, int type) {
-        final IBluetoothHeadset service = mService;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.clccResponse(index, direction, status, mode, mpty, number, type,
-                        mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Sends a vendor-specific unsolicited result code to the headset.
-     *
-     * <p>The actual string to be sent is <code>command + ": " + arg</code>. For example, if {@code
-     * command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg} is {@code "0"}, the
-     * string <code>"+ANDROID: 0"</code> will be sent.
-     *
-     * <p>Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}.
-     *
-     * @param device Bluetooth headset.
-     * @param command A vendor-specific command.
-     * @param arg The argument that will be attached to the command.
-     * @return {@code false} if there is no headset connected, or if the command is not an allowed
-     * vendor-specific unsolicited result code, or on error. {@code true} otherwise.
-     * @throws IllegalArgumentException if {@code command} is {@code null}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sendVendorSpecificResultCode(BluetoothDevice device, String command,
-            String arg) {
-        if (DBG) {
-            log("sendVendorSpecificResultCode()");
-        }
-        if (command == null) {
-            throw new IllegalArgumentException("command is null");
-        }
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.sendVendorSpecificResultCode(device, command, arg,
-                        mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Select a connected device as active.
-     *
-     * The active device selection is per profile. An active device's
-     * purpose is profile-specific. For example, in HFP and HSP profiles,
-     * it is the device used for phone call audio. If a remote device is not
-     * connected, it cannot be selected as active.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is not connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that the
-     * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
-     * with the active device.
-     *
-     * @param device Remote Bluetooth Device, could be null if phone call audio should not be
-     * streamed to a headset
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.MODIFY_PHONE_STATE,
-    })
-    @UnsupportedAppUsage(trackingBug = 171933273)
-    public boolean setActiveDevice(@Nullable BluetoothDevice device) {
-        if (DBG) {
-            Log.d(TAG, "setActiveDevice: " + device);
-        }
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && (device == null || isValidDevice(device))) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setActiveDevice(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the connected device that is active.
-     *
-     * @return the connected device that is active or null if no device
-     * is active.
-     * @hide
-     */
-    @UnsupportedAppUsage(trackingBug = 171933273)
-    @Nullable
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothDevice getActiveDevice() {
-        if (VDBG) Log.d(TAG, "getActiveDevice");
-        final IBluetoothHeadset service = mService;
-        final BluetoothDevice defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<BluetoothDevice> recv =
-                        new SynchronousResultReceiver();
-                service.getActiveDevice(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Check if in-band ringing is currently enabled. In-band ringing could be disabled during an
-     * active connection.
-     *
-     * @return true if in-band ringing is enabled, false if in-band ringing is disabled
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public boolean isInbandRingingEnabled() {
-        if (DBG) log("isInbandRingingEnabled()");
-        final IBluetoothHeadset service = mService;
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isInbandRingingEnabled(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Check if in-band ringing is supported for this platform.
-     *
-     * @return true if in-band ringing is supported, false if in-band ringing is not supported
-     * @hide
-     */
-    public static boolean isInbandRingingSupported(Context context) {
-        return context.getResources().getBoolean(
-                com.android.internal.R.bool.config_bluetooth_hfp_inband_ringing_support);
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final IBluetoothProfileServiceConnection mConnection =
-            new IBluetoothProfileServiceConnection.Stub() {
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothHeadset.Stub.asInterface(service);
-            mHandler.sendMessage(mHandler.obtainMessage(
-                    MESSAGE_HEADSET_SERVICE_CONNECTED));
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            if (DBG) Log.d(TAG, "Proxy object disconnected");
-            doUnbind();
-            mHandler.sendMessage(mHandler.obtainMessage(
-                    MESSAGE_HEADSET_SERVICE_DISCONNECTED));
-        }
-    };
-
-    @UnsupportedAppUsage
-    private boolean isEnabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    private boolean isDisabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_OFF;
-    }
-
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MESSAGE_HEADSET_SERVICE_CONNECTED: {
-                    if (mServiceListener != null) {
-                        mServiceListener.onServiceConnected(BluetoothProfile.HEADSET,
-                                BluetoothHeadset.this);
-                    }
-                    break;
-                }
-                case MESSAGE_HEADSET_SERVICE_DISCONNECTED: {
-                    if (mServiceListener != null) {
-                        mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
-                    }
-                    break;
-                }
-            }
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
deleted file mode 100644
index 7d7a7f7..0000000
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ /dev/null
@@ -1,1356 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Public API to control Hands Free Profile (HFP role only).
- * <p>
- * This class defines methods that shall be used by application to manage profile
- * connection, calls states and calls actions.
- * <p>
- *
- * @hide
- */
-public final class BluetoothHeadsetClient implements BluetoothProfile {
-    private static final String TAG = "BluetoothHeadsetClient";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent sent whenever connection to remote changes.
-     *
-     * <p>It includes two extras:
-     * <code>BluetoothProfile.EXTRA_PREVIOUS_STATE</code>
-     * and <code>BluetoothProfile.EXTRA_STATE</code>, which
-     * are mandatory.
-     * <p>There are also non mandatory feature extras:
-     * {@link #EXTRA_AG_FEATURE_3WAY_CALLING},
-     * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION},
-     * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT},
-     * {@link #EXTRA_AG_FEATURE_REJECT_CALL},
-     * {@link #EXTRA_AG_FEATURE_ECC},
-     * {@link #EXTRA_AG_FEATURE_RESPONSE_AND_HOLD},
-     * {@link #EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL},
-     * {@link #EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL},
-     * {@link #EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT},
-     * {@link #EXTRA_AG_FEATURE_MERGE},
-     * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH},
-     * sent as boolean values only when <code>EXTRA_STATE</code>
-     * is set to <code>STATE_CONNECTED</code>.</p>
-     *
-     * <p>Note that features supported by AG are being sent as
-     * booleans with value <code>true</code>,
-     * and not supported ones are <strong>not</strong> being sent at all.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent sent whenever audio state changes.
-     *
-     * <p>It includes two mandatory extras:
-     * {@link BluetoothProfile#EXTRA_STATE},
-     * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},
-     * with possible values:
-     * {@link #STATE_AUDIO_CONNECTING},
-     * {@link #STATE_AUDIO_CONNECTED},
-     * {@link #STATE_AUDIO_DISCONNECTED}</p>
-     * <p>When <code>EXTRA_STATE</code> is set
-     * to </code>STATE_AUDIO_CONNECTED</code>,
-     * it also includes {@link #EXTRA_AUDIO_WBS}
-     * indicating wide band speech support.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_AUDIO_STATE_CHANGED =
-            "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED";
-
-    /**
-     * Intent sending updates of the Audio Gateway state.
-     * Each extra is being sent only when value it
-     * represents has been changed recently on AG.
-     * <p>It can contain one or more of the following extras:
-     * {@link #EXTRA_NETWORK_STATUS},
-     * {@link #EXTRA_NETWORK_SIGNAL_STRENGTH},
-     * {@link #EXTRA_NETWORK_ROAMING},
-     * {@link #EXTRA_BATTERY_LEVEL},
-     * {@link #EXTRA_OPERATOR_NAME},
-     * {@link #EXTRA_VOICE_RECOGNITION},
-     * {@link #EXTRA_IN_BAND_RING}</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_AG_EVENT =
-            "android.bluetooth.headsetclient.profile.action.AG_EVENT";
-
-    /**
-     * Intent sent whenever state of a call changes.
-     *
-     * <p>It includes:
-     * {@link #EXTRA_CALL},
-     * with value of {@link BluetoothHeadsetClientCall} instance,
-     * representing actual call state.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CALL_CHANGED =
-            "android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED";
-
-    /**
-     * Intent that notifies about the result of the last issued action.
-     * Please note that not every action results in explicit action result code being sent.
-     * Instead other notifications about new Audio Gateway state might be sent,
-     * like <code>ACTION_AG_EVENT</code> with <code>EXTRA_VOICE_RECOGNITION</code> value
-     * when for example user started voice recognition from HF unit.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_RESULT =
-            "android.bluetooth.headsetclient.profile.action.RESULT";
-
-    /**
-     * Intent that notifies about vendor specific event arrival. Events not defined in
-     * HFP spec will be matched with supported vendor event list and this intent will
-     * be broadcasted upon a match. Supported vendor events are of format of
-     * of "+eventCode" or "+eventCode=xxxx" or "+eventCode:=xxxx".
-     * Vendor event can be a response to an vendor specific command or unsolicited.
-     *
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_VENDOR_SPECIFIC_HEADSETCLIENT_EVENT =
-            "android.bluetooth.headsetclient.profile.action.VENDOR_SPECIFIC_EVENT";
-
-    /**
-     * Intent that notifies about the number attached to the last voice tag
-     * recorded on AG.
-     *
-     * <p>It contains:
-     * {@link #EXTRA_NUMBER},
-     * with a <code>String</code> value representing phone number.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_LAST_VTAG =
-            "android.bluetooth.headsetclient.profile.action.LAST_VTAG";
-
-    public static final int STATE_AUDIO_DISCONNECTED = 0;
-    public static final int STATE_AUDIO_CONNECTING = 1;
-    public static final int STATE_AUDIO_CONNECTED = 2;
-
-    /**
-     * Extra with information if connected audio is WBS.
-     * <p>Possible values: <code>true</code>,
-     * <code>false</code>.</p>
-     */
-    public static final String EXTRA_AUDIO_WBS =
-            "android.bluetooth.headsetclient.extra.AUDIO_WBS";
-
-    /**
-     * Extra for AG_EVENT indicates network status.
-     * <p>Value: 0 - network unavailable,
-     * 1 - network available </p>
-     */
-    public static final String EXTRA_NETWORK_STATUS =
-            "android.bluetooth.headsetclient.extra.NETWORK_STATUS";
-    /**
-     * Extra for AG_EVENT intent indicates network signal strength.
-     * <p>Value: <code>Integer</code> representing signal strength.</p>
-     */
-    public static final String EXTRA_NETWORK_SIGNAL_STRENGTH =
-            "android.bluetooth.headsetclient.extra.NETWORK_SIGNAL_STRENGTH";
-    /**
-     * Extra for AG_EVENT intent indicates roaming state.
-     * <p>Value: 0 - no roaming
-     * 1 - active roaming</p>
-     */
-    public static final String EXTRA_NETWORK_ROAMING =
-            "android.bluetooth.headsetclient.extra.NETWORK_ROAMING";
-    /**
-     * Extra for AG_EVENT intent indicates the battery level.
-     * <p>Value: <code>Integer</code> representing signal strength.</p>
-     */
-    public static final String EXTRA_BATTERY_LEVEL =
-            "android.bluetooth.headsetclient.extra.BATTERY_LEVEL";
-    /**
-     * Extra for AG_EVENT intent indicates operator name.
-     * <p>Value: <code>String</code> representing operator name.</p>
-     */
-    public static final String EXTRA_OPERATOR_NAME =
-            "android.bluetooth.headsetclient.extra.OPERATOR_NAME";
-    /**
-     * Extra for AG_EVENT intent indicates voice recognition state.
-     * <p>Value:
-     * 0 - voice recognition stopped,
-     * 1 - voice recognition started.</p>
-     */
-    public static final String EXTRA_VOICE_RECOGNITION =
-            "android.bluetooth.headsetclient.extra.VOICE_RECOGNITION";
-    /**
-     * Extra for AG_EVENT intent indicates in band ring state.
-     * <p>Value:
-     * 0 - in band ring tone not supported, or
-     * 1 - in band ring tone supported.</p>
-     */
-    public static final String EXTRA_IN_BAND_RING =
-            "android.bluetooth.headsetclient.extra.IN_BAND_RING";
-
-    /**
-     * Extra for AG_EVENT intent indicates subscriber info.
-     * <p>Value: <code>String</code> containing subscriber information.</p>
-     */
-    public static final String EXTRA_SUBSCRIBER_INFO =
-            "android.bluetooth.headsetclient.extra.SUBSCRIBER_INFO";
-
-    /**
-     * Extra for AG_CALL_CHANGED intent indicates the
-     * {@link BluetoothHeadsetClientCall} object that has changed.
-     */
-    public static final String EXTRA_CALL =
-            "android.bluetooth.headsetclient.extra.CALL";
-
-    /**
-     * Extra for ACTION_LAST_VTAG intent.
-     * <p>Value: <code>String</code> representing phone number
-     * corresponding to last voice tag recorded on AG</p>
-     */
-    public static final String EXTRA_NUMBER =
-            "android.bluetooth.headsetclient.extra.NUMBER";
-
-    /**
-     * Extra for ACTION_RESULT intent that shows the result code of
-     * last issued action.
-     * <p>Possible results:
-     * {@link #ACTION_RESULT_OK},
-     * {@link #ACTION_RESULT_ERROR},
-     * {@link #ACTION_RESULT_ERROR_NO_CARRIER},
-     * {@link #ACTION_RESULT_ERROR_BUSY},
-     * {@link #ACTION_RESULT_ERROR_NO_ANSWER},
-     * {@link #ACTION_RESULT_ERROR_DELAYED},
-     * {@link #ACTION_RESULT_ERROR_BLACKLISTED},
-     * {@link #ACTION_RESULT_ERROR_CME}</p>
-     */
-    public static final String EXTRA_RESULT_CODE =
-            "android.bluetooth.headsetclient.extra.RESULT_CODE";
-
-    /**
-     * Extra for ACTION_RESULT intent that shows the extended result code of
-     * last issued action.
-     * <p>Value: <code>Integer</code> - error code.</p>
-     */
-    public static final String EXTRA_CME_CODE =
-            "android.bluetooth.headsetclient.extra.CME_CODE";
-
-    /**
-     * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that
-     * indicates vendor ID.
-     */
-    public static final String EXTRA_VENDOR_ID =
-            "android.bluetooth.headsetclient.extra.VENDOR_ID";
-
-     /**
-     * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that
-     * indicates vendor event code.
-     */
-    public static final String EXTRA_VENDOR_EVENT_CODE =
-            "android.bluetooth.headsetclient.extra.VENDOR_EVENT_CODE";
-
-     /**
-     * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that
-     * contains full vendor event including event code and full arguments.
-     */
-    public static final String EXTRA_VENDOR_EVENT_FULL_ARGS =
-            "android.bluetooth.headsetclient.extra.VENDOR_EVENT_FULL_ARGS";
-
-
-    /* Extras for AG_FEATURES, extras type is boolean */
-    // TODO verify if all of those are actually useful
-    /**
-     * AG feature: three way calling.
-     */
-    public static final String EXTRA_AG_FEATURE_3WAY_CALLING =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_3WAY_CALLING";
-    /**
-     * AG feature: voice recognition.
-     */
-    public static final String EXTRA_AG_FEATURE_VOICE_RECOGNITION =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_VOICE_RECOGNITION";
-    /**
-     * AG feature: fetching phone number for voice tagging procedure.
-     */
-    public static final String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT";
-    /**
-     * AG feature: ability to reject incoming call.
-     */
-    public static final String EXTRA_AG_FEATURE_REJECT_CALL =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_REJECT_CALL";
-    /**
-     * AG feature: enhanced call handling (terminate specific call, private consultation).
-     */
-    public static final String EXTRA_AG_FEATURE_ECC =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ECC";
-    /**
-     * AG feature: response and hold.
-     */
-    public static final String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RESPONSE_AND_HOLD";
-    /**
-     * AG call handling feature: accept held or waiting call in three way calling scenarios.
-     */
-    public static final String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL";
-    /**
-     * AG call handling feature: release held or waiting call in three way calling scenarios.
-     */
-    public static final String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL";
-    /**
-     * AG call handling feature: release active call and accept held or waiting call in three way
-     * calling scenarios.
-     */
-    public static final String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT";
-    /**
-     * AG call handling feature: merge two calls, held and active - multi party conference mode.
-     */
-    public static final String EXTRA_AG_FEATURE_MERGE =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE";
-    /**
-     * AG call handling feature: merge calls and disconnect from multi party
-     * conversation leaving peers connected to each other.
-     * Note that this feature needs to be supported by mobile network operator
-     * as it requires connection and billing transfer.
-     */
-    public static final String EXTRA_AG_FEATURE_MERGE_AND_DETACH =
-            "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE_AND_DETACH";
-
-    /* Action result codes */
-    public static final int ACTION_RESULT_OK = 0;
-    public static final int ACTION_RESULT_ERROR = 1;
-    public static final int ACTION_RESULT_ERROR_NO_CARRIER = 2;
-    public static final int ACTION_RESULT_ERROR_BUSY = 3;
-    public static final int ACTION_RESULT_ERROR_NO_ANSWER = 4;
-    public static final int ACTION_RESULT_ERROR_DELAYED = 5;
-    public static final int ACTION_RESULT_ERROR_BLACKLISTED = 6;
-    public static final int ACTION_RESULT_ERROR_CME = 7;
-
-    /* Detailed CME error codes */
-    public static final int CME_PHONE_FAILURE = 0;
-    public static final int CME_NO_CONNECTION_TO_PHONE = 1;
-    public static final int CME_OPERATION_NOT_ALLOWED = 3;
-    public static final int CME_OPERATION_NOT_SUPPORTED = 4;
-    public static final int CME_PHSIM_PIN_REQUIRED = 5;
-    public static final int CME_PHFSIM_PIN_REQUIRED = 6;
-    public static final int CME_PHFSIM_PUK_REQUIRED = 7;
-    public static final int CME_SIM_NOT_INSERTED = 10;
-    public static final int CME_SIM_PIN_REQUIRED = 11;
-    public static final int CME_SIM_PUK_REQUIRED = 12;
-    public static final int CME_SIM_FAILURE = 13;
-    public static final int CME_SIM_BUSY = 14;
-    public static final int CME_SIM_WRONG = 15;
-    public static final int CME_INCORRECT_PASSWORD = 16;
-    public static final int CME_SIM_PIN2_REQUIRED = 17;
-    public static final int CME_SIM_PUK2_REQUIRED = 18;
-    public static final int CME_MEMORY_FULL = 20;
-    public static final int CME_INVALID_INDEX = 21;
-    public static final int CME_NOT_FOUND = 22;
-    public static final int CME_MEMORY_FAILURE = 23;
-    public static final int CME_TEXT_STRING_TOO_LONG = 24;
-    public static final int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25;
-    public static final int CME_DIAL_STRING_TOO_LONG = 26;
-    public static final int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27;
-    public static final int CME_NO_NETWORK_SERVICE = 30;
-    public static final int CME_NETWORK_TIMEOUT = 31;
-    public static final int CME_EMERGENCY_SERVICE_ONLY = 32;
-    public static final int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33;
-    public static final int CME_NOT_SUPPORTED_FOR_VOIP = 34;
-    public static final int CME_SIP_RESPONSE_CODE = 35;
-    public static final int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40;
-    public static final int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41;
-    public static final int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42;
-    public static final int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43;
-    public static final int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44;
-    public static final int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45;
-    public static final int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46;
-    public static final int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47;
-    public static final int CME_HIDDEN_KEY_REQUIRED = 48;
-    public static final int CME_EAP_NOT_SUPPORTED = 49;
-    public static final int CME_INCORRECT_PARAMETERS = 50;
-
-    /* Action policy for other calls when accepting call */
-    public static final int CALL_ACCEPT_NONE = 0;
-    public static final int CALL_ACCEPT_HOLD = 1;
-    public static final int CALL_ACCEPT_TERMINATE = 2;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT,
-                    "BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {
-                @Override
-                public IBluetoothHeadsetClient getServiceInterface(IBinder service) {
-                    return IBluetoothHeadsetClient.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothHeadsetClient proxy object.
-     */
-    /* package */ BluetoothHeadsetClient(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothHeadsetClient will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     */
-    /*package*/ void close() {
-        if (VDBG) log("close()");
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothHeadsetClient getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Connects to remote device.
-     *
-     * Currently, the system supports only 1 connection. So, in case of the
-     * second connection, this implementation will disconnect already connected
-     * device automatically and will process the new one.
-     *
-     * @param device a remote device we want connect to
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Disconnects remote device
-     *
-     * @param device a remote device we want disconnect
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Return the list of connected remote devices
-     *
-     * @return list of connected devices; empty list if nothing is connected.
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothHeadsetClient service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns list of remote devices in a particular state
-     *
-     * @param states collection of states
-     * @return list of devices that state matches the states listed in <code>states</code>; empty
-     * list if nothing matches the <code>states</code>
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothHeadsetClient service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns state of the <code>device</code>
-     *
-     * @param device a remote device
-     * @return the state of connection of the device
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (VDBG) log("getConnectionState(" + device + ")");
-        final IBluetoothHeadsetClient service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothHeadsetClient service = getService();
-        final @ConnectionPolicy int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Starts voice recognition.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_AG_EVENT} intent.
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature
-     * is not supported.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean startVoiceRecognition(BluetoothDevice device) {
-        if (DBG) log("startVoiceRecognition()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.startVoiceRecognition(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send vendor specific AT command.
-     *
-     * @param device remote device
-     * @param vendorId vendor number by Bluetooth SIG
-     * @param atCommand command to be sent. It start with + prefix and only one command at one time.
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sendVendorAtCommand(BluetoothDevice device, int vendorId, String atCommand) {
-        if (DBG) log("sendVendorSpecificCommand()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.sendVendorAtCommand(device, vendorId, atCommand, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Stops voice recognition.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_AG_EVENT} intent.
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature
-     * is not supported.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean stopVoiceRecognition(BluetoothDevice device) {
-        if (DBG) log("stopVoiceRecognition()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.stopVoiceRecognition(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns list of all calls in any state.
-     *
-     * @param device remote device
-     * @return list of calls; empty list if none call exists
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
-        if (DBG) log("getCurrentCalls()");
-        final IBluetoothHeadsetClient service = getService();
-        final List<BluetoothHeadsetClientCall> defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothHeadsetClientCall>> recv =
-                        new SynchronousResultReceiver();
-                service.getCurrentCalls(device, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns list of current values of AG indicators.
-     *
-     * @param device remote device
-     * @return bundle of AG  indicators; null if device is not in CONNECTED state
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public Bundle getCurrentAgEvents(BluetoothDevice device) {
-        if (DBG) log("getCurrentAgEvents()");
-        final IBluetoothHeadsetClient service = getService();
-        final Bundle defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Bundle> recv = new SynchronousResultReceiver();
-                service.getCurrentAgEvents(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Accepts a call
-     *
-     * @param device remote device
-     * @param flag action policy while accepting a call. Possible values {@link #CALL_ACCEPT_NONE},
-     * {@link #CALL_ACCEPT_HOLD}, {@link #CALL_ACCEPT_TERMINATE}
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean acceptCall(BluetoothDevice device, int flag) {
-        if (DBG) log("acceptCall()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.acceptCall(device, flag, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Holds a call.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean holdCall(BluetoothDevice device) {
-        if (DBG) log("holdCall()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.holdCall(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Rejects a call.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_REJECT_CALL}. This method invocation will fail silently when feature is not
-     * supported.</p>
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean rejectCall(BluetoothDevice device) {
-        if (DBG) log("rejectCall()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.rejectCall(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Terminates a specified call.
-     *
-     * Works only when Extended Call Control is supported by Audio Gateway.
-     *
-     * @param device remote device
-     * @param call Handle of call obtained in {@link #dial(BluetoothDevice, String)} or obtained via
-     * {@link #ACTION_CALL_CHANGED}. {@code call} may be null in which case we will hangup all active
-     * calls.
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not
-     * supported.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
-        if (DBG) log("terminateCall()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.terminateCall(device, call, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Enters private mode with a specified call.
-     *
-     * Works only when Extended Call Control is supported by Audio Gateway.
-     *
-     * @param device remote device
-     * @param index index of the call to connect in private mode
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not
-     * supported.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean enterPrivateMode(BluetoothDevice device, int index) {
-        if (DBG) log("enterPrivateMode()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.enterPrivateMode(device, index, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Performs explicit call transfer.
-     *
-     * That means connect other calls and disconnect.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. This method invocation will fail silently when feature
-     * is not supported.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean explicitCallTransfer(BluetoothDevice device) {
-        if (DBG) log("explicitCallTransfer()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.explicitCallTransfer(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Places a call with specified number.
-     *
-     * @param device remote device
-     * @param number valid phone number
-     * @return <code>{@link BluetoothHeadsetClientCall} call</code> if command has been issued
-     * successfully; <code>{@link null}</code> otherwise; upon completion HFP sends {@link
-     * #ACTION_CALL_CHANGED} intent in case of success; {@link #ACTION_RESULT} is sent otherwise;
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
-        if (DBG) log("dial()");
-        final IBluetoothHeadsetClient service = getService();
-        final BluetoothHeadsetClientCall defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<BluetoothHeadsetClientCall> recv =
-                        new SynchronousResultReceiver();
-                service.dial(device, number, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sends DTMF code.
-     *
-     * Possible code values : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,#
-     *
-     * @param device remote device
-     * @param code ASCII code
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_RESULT} intent;
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sendDTMF(BluetoothDevice device, byte code) {
-        if (DBG) log("sendDTMF()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.sendDTMF(device, code, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get a number corresponding to last voice tag recorded on AG.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_LAST_VTAG} or {@link #ACTION_RESULT}
-     * intent;
-     *
-     * <p>Feature required for successful execution is being reported by: {@link
-     * #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}. This method invocation will fail silently when
-     * feature is not supported.</p>
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean getLastVoiceTagNumber(BluetoothDevice device) {
-        if (DBG) log("getLastVoiceTagNumber()");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getLastVoiceTagNumber(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns current audio state of Audio Gateway.
-     *
-     * Note: This is an internal function and shouldn't be exposed
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getAudioState(BluetoothDevice device) {
-        if (VDBG) log("getAudioState");
-        final IBluetoothHeadsetClient service = getService();
-        final int defaultValue = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getAudioState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        } else {
-            return defaultValue;
-        }
-        return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
-    }
-
-    /**
-     * Sets whether audio routing is allowed.
-     *
-     * @param device remote device
-     * @param allowed if routing is allowed to the device Note: This is an internal function and
-     * shouldn't be exposed
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
-        if (VDBG) log("setAudioRouteAllowed");
-        final IBluetoothHeadsetClient service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setAudioRouteAllowed(device, allowed, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Returns whether audio routing is allowed.
-     *
-     * @param device remote device
-     * @return whether the command succeeded Note: This is an internal function and shouldn't be
-     * exposed
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean getAudioRouteAllowed(BluetoothDevice device) {
-        if (VDBG) log("getAudioRouteAllowed");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getAudioRouteAllowed(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiates a connection of audio channel.
-     *
-     * It setup SCO channel with remote connected Handsfree AG device.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connectAudio(BluetoothDevice device) {
-        if (VDBG) log("connectAudio");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connectAudio(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Disconnects audio channel.
-     *
-     * It tears down the SCO channel from remote AG device.
-     *
-     * @param device remote device
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnectAudio(BluetoothDevice device) {
-        if (VDBG) log("disconnectAudio");
-        final IBluetoothHeadsetClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnectAudio(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get Audio Gateway features
-     *
-     * @param device remote device
-     * @return bundle of AG features; null if no service or AG not connected
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public Bundle getCurrentAgFeatures(BluetoothDevice device) {
-        if (VDBG) log("getCurrentAgFeatures");
-        final IBluetoothHeadsetClient service = getService();
-        final Bundle defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Bundle> recv = new SynchronousResultReceiver();
-                service.getCurrentAgFeatures(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    private static boolean isValidDevice(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/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
deleted file mode 100644
index 032b507..0000000
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-
-import java.util.UUID;
-
-/**
- * This class represents a single call, its state and properties.
- * It implements {@link Parcelable} for inter-process message passing.
- *
- * @hide
- */
-public final class BluetoothHeadsetClientCall implements Parcelable, Attributable {
-
-    /* Call state */
-    /**
-     * Call is active.
-     */
-    public static final int CALL_STATE_ACTIVE = 0;
-    /**
-     * Call is in held state.
-     */
-    public static final int CALL_STATE_HELD = 1;
-    /**
-     * Outgoing call that is being dialed right now.
-     */
-    public static final int CALL_STATE_DIALING = 2;
-    /**
-     * Outgoing call that remote party has already been alerted about.
-     */
-    public static final int CALL_STATE_ALERTING = 3;
-    /**
-     * Incoming call that can be accepted or rejected.
-     */
-    public static final int CALL_STATE_INCOMING = 4;
-    /**
-     * Waiting call state when there is already an active call.
-     */
-    public static final int CALL_STATE_WAITING = 5;
-    /**
-     * Call that has been held by response and hold
-     * (see Bluetooth specification for further references).
-     */
-    public static final int CALL_STATE_HELD_BY_RESPONSE_AND_HOLD = 6;
-    /**
-     * Call that has been already terminated and should not be referenced as a valid call.
-     */
-    public static final int CALL_STATE_TERMINATED = 7;
-
-    private final BluetoothDevice mDevice;
-    private final int mId;
-    private int mState;
-    private String mNumber;
-    private boolean mMultiParty;
-    private final boolean mOutgoing;
-    private final UUID mUUID;
-    private final long mCreationElapsedMilli;
-    private final boolean mInBandRing;
-
-    /**
-     * Creates BluetoothHeadsetClientCall instance.
-     */
-    public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number,
-            boolean multiParty, boolean outgoing, boolean inBandRing) {
-        this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing, inBandRing);
-    }
-
-    public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state,
-            String number, boolean multiParty, boolean outgoing, boolean inBandRing) {
-        mDevice = device;
-        mId = id;
-        mUUID = uuid;
-        mState = state;
-        mNumber = number != null ? number : "";
-        mMultiParty = multiParty;
-        mOutgoing = outgoing;
-        mInBandRing = inBandRing;
-        mCreationElapsedMilli = SystemClock.elapsedRealtime();
-    }
-
-    /** {@hide} */
-    public void setAttributionSource(@NonNull AttributionSource attributionSource) {
-        Attributable.setAttributionSource(mDevice, attributionSource);
-    }
-
-    /**
-     * Sets call's state.
-     *
-     * <p>Note: This is an internal function and shouldn't be exposed</p>
-     *
-     * @param state new call state.
-     */
-    public void setState(int state) {
-        mState = state;
-    }
-
-    /**
-     * Sets call's number.
-     *
-     * <p>Note: This is an internal function and shouldn't be exposed</p>
-     *
-     * @param number String representing phone number.
-     */
-    public void setNumber(String number) {
-        mNumber = number;
-    }
-
-    /**
-     * Sets this call as multi party call.
-     *
-     * <p>Note: This is an internal function and shouldn't be exposed</p>
-     *
-     * @param multiParty if <code>true</code> sets this call as a part of multi party conference.
-     */
-    public void setMultiParty(boolean multiParty) {
-        mMultiParty = multiParty;
-    }
-
-    /**
-     * Gets call's device.
-     *
-     * @return call device.
-     */
-    public BluetoothDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Gets call's Id.
-     *
-     * @return call id.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int getId() {
-        return mId;
-    }
-
-    /**
-     * Gets call's UUID.
-     *
-     * @return call uuid
-     * @hide
-     */
-    public UUID getUUID() {
-        return mUUID;
-    }
-
-    /**
-     * Gets call's current state.
-     *
-     * @return state of this particular phone call.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int getState() {
-        return mState;
-    }
-
-    /**
-     * Gets call's number.
-     *
-     * @return string representing phone number.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public String getNumber() {
-        return mNumber;
-    }
-
-    /**
-     * Gets call's creation time in millis since epoch.
-     *
-     * @return long representing the creation time.
-     */
-    public long getCreationElapsedMilli() {
-        return mCreationElapsedMilli;
-    }
-
-    /**
-     * Checks if call is an active call in a conference mode (aka multi party).
-     *
-     * @return <code>true</code> if call is a multi party call, <code>false</code> otherwise.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean isMultiParty() {
-        return mMultiParty;
-    }
-
-    /**
-     * Checks if this call is an outgoing call.
-     *
-     * @return <code>true</code> if its outgoing call, <code>false</code> otherwise.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean isOutgoing() {
-        return mOutgoing;
-    }
-
-    /**
-     * Checks if the ringtone will be generated by the connected phone
-     *
-     * @return <code>true</code> if in band ring is enabled, <code>false</code> otherwise.
-     */
-    public boolean isInBandRing() {
-        return mInBandRing;
-    }
-
-
-    @Override
-    public String toString() {
-        return toString(false);
-    }
-
-    /**
-     * Generate a log string for this call
-     * @param loggable whether device address should be logged
-     * @return log string
-     */
-    public String toString(boolean loggable) {
-        StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mDevice: ");
-        builder.append(loggable ? mDevice : mDevice.hashCode());
-        builder.append(", mId: ");
-        builder.append(mId);
-        builder.append(", mUUID: ");
-        builder.append(mUUID);
-        builder.append(", mState: ");
-        switch (mState) {
-            case CALL_STATE_ACTIVE:
-                builder.append("ACTIVE");
-                break;
-            case CALL_STATE_HELD:
-                builder.append("HELD");
-                break;
-            case CALL_STATE_DIALING:
-                builder.append("DIALING");
-                break;
-            case CALL_STATE_ALERTING:
-                builder.append("ALERTING");
-                break;
-            case CALL_STATE_INCOMING:
-                builder.append("INCOMING");
-                break;
-            case CALL_STATE_WAITING:
-                builder.append("WAITING");
-                break;
-            case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
-                builder.append("HELD_BY_RESPONSE_AND_HOLD");
-                break;
-            case CALL_STATE_TERMINATED:
-                builder.append("TERMINATED");
-                break;
-            default:
-                builder.append(mState);
-                break;
-        }
-        builder.append(", mNumber: ");
-        builder.append(loggable ? mNumber : mNumber.hashCode());
-        builder.append(", mMultiParty: ");
-        builder.append(mMultiParty);
-        builder.append(", mOutgoing: ");
-        builder.append(mOutgoing);
-        builder.append(", mInBandRing: ");
-        builder.append(mInBandRing);
-        builder.append("}");
-        return builder.toString();
-    }
-
-    /**
-     * {@link Parcelable.Creator} interface implementation.
-     */
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHeadsetClientCall> CREATOR =
-            new Parcelable.Creator<BluetoothHeadsetClientCall>() {
-                @Override
-                public BluetoothHeadsetClientCall createFromParcel(Parcel in) {
-                    return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null),
-                            in.readInt(), UUID.fromString(in.readString()), in.readInt(),
-                            in.readString(), in.readInt() == 1, in.readInt() == 1,
-                            in.readInt() == 1);
-                }
-
-                @Override
-                public BluetoothHeadsetClientCall[] newArray(int size) {
-                    return new BluetoothHeadsetClientCall[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(mDevice, 0);
-        out.writeInt(mId);
-        out.writeString(mUUID.toString());
-        out.writeInt(mState);
-        out.writeString(mNumber);
-        out.writeInt(mMultiParty ? 1 : 0);
-        out.writeInt(mOutgoing ? 1 : 0);
-        out.writeInt(mInBandRing ? 1 : 0);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
deleted file mode 100644
index 65f68a9..0000000
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Public API for Bluetooth Health Profile.
- *
- * <p>BluetoothHealth is a proxy object for controlling the Bluetooth
- * Service via IPC.
- *
- * <p> How to connect to a health device which is acting in the source role.
- * <li> Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHealth proxy object. </li>
- * <li> Create an {@link BluetoothHealth} callback and call
- * {@link #registerSinkAppConfiguration} to register an application
- * configuration </li>
- * <li> Pair with the remote device. This currently needs to be done manually
- * from Bluetooth Settings </li>
- * <li> Connect to a health device using {@link #connectChannelToSource}. Some
- * devices will connect the channel automatically. The {@link BluetoothHealth}
- * callback will inform the application of channel state change. </li>
- * <li> Use the file descriptor provided with a connected channel to read and
- * write data to the health channel. </li>
- * <li> The received data needs to be interpreted using a health manager which
- * implements the IEEE 11073-xxxxx specifications.
- * <li> When done, close the health channel by calling {@link #disconnectChannel}
- * and unregister the application configuration calling
- * {@link #unregisterAppConfiguration}
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New apps
- * should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
-@Deprecated
-public final class BluetoothHealth implements BluetoothProfile {
-    private static final String TAG = "BluetoothHealth";
-    /**
-     * Health Profile Source Role - the health device.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int SOURCE_ROLE = 1 << 0;
-
-    /**
-     * Health Profile Sink Role the device talking to the health device.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int SINK_ROLE = 1 << 1;
-
-    /**
-     * Health Profile - Channel Type used - Reliable
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int CHANNEL_TYPE_RELIABLE = 10;
-
-    /**
-     * Health Profile - Channel Type used - Streaming
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int CHANNEL_TYPE_STREAMING = 11;
-
-    /**
-     * Hide auto-created default constructor
-     * @hide
-     */
-    BluetoothHealth() {}
-
-    /**
-     * Register an application configuration that acts as a Health SINK.
-     * This is the configuration that will be used to communicate with health devices
-     * which will act as the {@link #SOURCE_ROLE}. This is an asynchronous call and so
-     * the callback is used to notify success or failure if the function returns true.
-     *
-     * @param name The friendly name associated with the application or configuration.
-     * @param dataType The dataType of the Source role of Health Profile to which the sink wants to
-     * connect to.
-     * @param callback A callback to indicate success or failure of the registration and all
-     * operations done on this application configuration.
-     * @return If true, callback will be called.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public boolean registerSinkAppConfiguration(String name, int dataType,
-            BluetoothHealthCallback callback) {
-        Log.e(TAG, "registerSinkAppConfiguration(): BluetoothHealth is deprecated");
-        return false;
-    }
-
-    /**
-     * Unregister an application configuration that has been registered using
-     * {@link #registerSinkAppConfiguration}
-     *
-     * @param config The health app configuration
-     * @return Success or failure.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
-        Log.e(TAG, "unregisterAppConfiguration(): BluetoothHealth is deprecated");
-        return false;
-    }
-
-    /**
-     * Connect to a health device which has the {@link #SOURCE_ROLE}.
-     * This is an asynchronous call. If this function returns true, the callback
-     * associated with the application configuration will be called.
-     *
-     * @param device The remote Bluetooth device.
-     * @param config The application configuration which has been registered using {@link
-     * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
-     * @return If true, the callback associated with the application config will be called.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public boolean connectChannelToSource(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        Log.e(TAG, "connectChannelToSource(): BluetoothHealth is deprecated");
-        return false;
-    }
-
-    /**
-     * Disconnect a connected health channel.
-     * This is an asynchronous call. If this function returns true, the callback
-     * associated with the application configuration will be called.
-     *
-     * @param device The remote Bluetooth device.
-     * @param config The application configuration which has been registered using {@link
-     * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
-     * @param channelId The channel id associated with the channel
-     * @return If true, the callback associated with the application config will be called.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public boolean disconnectChannel(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config, int channelId) {
-        Log.e(TAG, "disconnectChannel(): BluetoothHealth is deprecated");
-        return false;
-    }
-
-    /**
-     * Get the file descriptor of the main channel associated with the remote device
-     * and application configuration.
-     *
-     * <p> Its the responsibility of the caller to close the ParcelFileDescriptor
-     * when done.
-     *
-     * @param device The remote Bluetooth health device
-     * @param config The application configuration
-     * @return null on failure, ParcelFileDescriptor on success.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
-            BluetoothHealthAppConfiguration config) {
-        Log.e(TAG, "getMainChannelFd(): BluetoothHealth is deprecated");
-        return null;
-    }
-
-    /**
-     * Get the current connection state of the profile.
-     *
-     * This is not specific to any application configuration but represents the connection
-     * state of the local Bluetooth adapter with the remote device. This can be used
-     * by applications like status bar which would just like to know the state of the
-     * local adapter.
-     *
-     * @param device Remote bluetooth device.
-     * @return State of the profile connection. One of {@link #STATE_CONNECTED}, {@link
-     * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
-     */
-    @Override
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public int getConnectionState(BluetoothDevice device) {
-        Log.e(TAG, "getConnectionState(): BluetoothHealth is deprecated");
-        return STATE_DISCONNECTED;
-    }
-
-    /**
-     * Get connected devices for the health profile.
-     *
-     * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
-     *
-     * This is not specific to any application configuration but represents the connection
-     * state of the local Bluetooth adapter for this profile. This can be used
-     * by applications like status bar which would just like to know the state of the
-     * local adapter.
-     *
-     * @return List of devices. The list will be empty on error.
-     */
-    @Override
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public List<BluetoothDevice> getConnectedDevices() {
-        Log.e(TAG, "getConnectedDevices(): BluetoothHealth is deprecated");
-        return new ArrayList<>();
-    }
-
-    /**
-     * Get a list of devices that match any of the given connection
-     * states.
-     *
-     * <p> If none of the devices match any of the given states,
-     * an empty list will be returned.
-     *
-     * <p>This is not specific to any application configuration but represents the connection
-     * state of the local Bluetooth adapter for this profile. This can be used
-     * by applications like status bar which would just like to know the state of the
-     * local adapter.
-     *
-     * @param states Array of states. States can be one of {@link #STATE_CONNECTED}, {@link
-     * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
-     * @return List of devices. The list will be empty on error.
-     */
-    @Override
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        Log.e(TAG, "getDevicesMatchingConnectionStates(): BluetoothHealth is deprecated");
-        return new ArrayList<>();
-    }
-
-    /** Health Channel Connection State - Disconnected
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int STATE_CHANNEL_DISCONNECTED = 0;
-    /** Health Channel Connection State - Connecting
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int STATE_CHANNEL_CONNECTING = 1;
-    /** Health Channel Connection State - Connected
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int STATE_CHANNEL_CONNECTED = 2;
-    /** Health Channel Connection State - Disconnecting
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int STATE_CHANNEL_DISCONNECTING = 3;
-
-    /** Health App Configuration registration success
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0;
-    /** Health App Configuration registration failure
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int APP_CONFIG_REGISTRATION_FAILURE = 1;
-    /** Health App Configuration un-registration success
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2;
-    /** Health App Configuration un-registration failure
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3;
-}
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
deleted file mode 100644
index 2f66df2..0000000
--- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * The Bluetooth Health Application Configuration that is used in conjunction with
- * the {@link BluetoothHealth} class. This class represents an application configuration
- * that the Bluetooth Health third party application will register to communicate with the
- * remote Bluetooth health device.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
-@Deprecated
-public final class BluetoothHealthAppConfiguration implements Parcelable {
-
-    /**
-     * Hide auto-created default constructor
-     * @hide
-     */
-    BluetoothHealthAppConfiguration() {}
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Return the data type associated with this application configuration.
-     *
-     * @return dataType
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public int getDataType() {
-        return 0;
-    }
-
-    /**
-     * Return the name of the application configuration.
-     *
-     * @return String name
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public String getName() {
-        return null;
-    }
-
-    /**
-     * Return the role associated with this application configuration.
-     *
-     * @return One of {@link BluetoothHealth#SOURCE_ROLE} or {@link BluetoothHealth#SINK_ROLE}
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public int getRole() {
-        return 0;
-    }
-
-    /**
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR =
-            new Parcelable.Creator<BluetoothHealthAppConfiguration>() {
-                @Override
-                public BluetoothHealthAppConfiguration createFromParcel(Parcel in) {
-                    return new BluetoothHealthAppConfiguration();
-                }
-
-                @Override
-                public BluetoothHealthAppConfiguration[] newArray(int size) {
-                    return new BluetoothHealthAppConfiguration[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {}
-}
diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java
deleted file mode 100644
index 4769212..0000000
--- a/core/java/android/bluetooth/BluetoothHealthCallback.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.BinderThread;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-/**
- * This abstract class is used to implement {@link BluetoothHealth} callbacks.
- *
- * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
- * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
- * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
- * {@link BluetoothDevice#createL2capChannel(int)}
- */
-@Deprecated
-public abstract class BluetoothHealthCallback {
-    private static final String TAG = "BluetoothHealthCallback";
-
-    /**
-     * Callback to inform change in registration state of the health
-     * application.
-     * <p> This callback is called on the binder thread (not on the UI thread)
-     *
-     * @param config Bluetooth Health app configuration
-     * @param status Success or failure of the registration or unregistration calls. Can be one of
-     * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_SUCCESS} or {@link
-     * BluetoothHealth#APP_CONFIG_REGISTRATION_FAILURE} or
-     * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS}
-     * or {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE}
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @BinderThread
-    @Deprecated
-    public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
-            int status) {
-        Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + "Status: " + status);
-    }
-
-    /**
-     * Callback to inform change in channel state.
-     * <p> Its the responsibility of the implementor of this callback to close the
-     * parcel file descriptor when done. This callback is called on the Binder
-     * thread (not the UI thread)
-     *
-     * @param config The Health app configutation
-     * @param device The Bluetooth Device
-     * @param prevState The previous state of the channel
-     * @param newState The new state of the channel.
-     * @param fd The Parcel File Descriptor when the channel state is connected.
-     * @param channelId The id associated with the channel. This id will be used in future calls
-     * like when disconnecting the channel.
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()(int)}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @BinderThread
-    @Deprecated
-    public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
-            BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd,
-            int channelId) {
-        Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device
-                + "prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd
-                + "ChannelId:" + channelId);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
deleted file mode 100644
index 339a75f..0000000
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-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.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Hearing Aid profile.
- *
- * <p>BluetoothHearingAid is a proxy object for controlling the Bluetooth Hearing Aid
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHearingAid proxy object.
- *
- * <p> Android only supports one set of connected Bluetooth Hearing Aid device at a time. Each
- * method is protected with its appropriate permission.
- */
-public final class BluetoothHearingAid implements BluetoothProfile {
-    private static final String TAG = "BluetoothHearingAid";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the Hearing Aid
-     * profile. Please note that in the binaural case, there will be two different LE devices for
-     * the left and right side and each device will have their own connection state changes.S
-     *
-     * <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}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the selection of a connected device as active.
-     *
-     * <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>
-     * </ul>
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_ACTIVE_DEVICE_CHANGED =
-            "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
-
-    /**
-     * This device represents Left Hearing Aid.
-     *
-     * @hide
-     */
-    public static final int SIDE_LEFT = IBluetoothHearingAid.SIDE_LEFT;
-
-    /**
-     * This device represents Right Hearing Aid.
-     *
-     * @hide
-     */
-    public static final int SIDE_RIGHT = IBluetoothHearingAid.SIDE_RIGHT;
-
-    /**
-     * This device is Monaural.
-     *
-     * @hide
-     */
-    public static final int MODE_MONAURAL = IBluetoothHearingAid.MODE_MONAURAL;
-
-    /**
-     * This device is Binaural (should receive only left or right audio).
-     *
-     * @hide
-     */
-    public static final int MODE_BINAURAL = IBluetoothHearingAid.MODE_BINAURAL;
-
-    /**
-     * Indicates the HiSyncID could not be read and is unavailable.
-     *
-     * @hide
-     */
-    public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID,
-                    "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) {
-                @Override
-                public IBluetoothHearingAid getServiceInterface(IBinder service) {
-                    return IBluetoothHearingAid.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothHearingAid proxy object for interacting with the local
-     * Bluetooth Hearing Aid service.
-     */
-    /* package */ BluetoothHearingAid(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /*package*/ void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothHearingAid getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Initiate connection to a profile of the remote bluetooth device.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothHearingAid service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothHearingAid service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothHearingAid service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
-    @NonNull int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothHearingAid service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @BluetoothProfile.BtProfileState int getConnectionState(
-    @NonNull BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        final IBluetoothHearingAid service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Select a connected device as active.
-     *
-     * The active device selection is per profile. An active device's
-     * purpose is profile-specific. For example, Hearing Aid audio
-     * streaming is to the active Hearing Aid device. If a remote device
-     * is not connected, it cannot be selected as active.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is not connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that the
-     * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
-     * with the active device.
-     *
-     * @param device the remote Bluetooth device. Could be null to clear
-     * the active device and stop streaming audio to a Bluetooth device.
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean setActiveDevice(@Nullable BluetoothDevice device) {
-        if (DBG) log("setActiveDevice(" + device + ")");
-        final IBluetoothHearingAid service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && ((device == null) || isValidDevice(device))) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setActiveDevice(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the connected physical Hearing Aid devices that are active
-     *
-     * @return the list of active devices. The first element is the left active
-     * device; the second element is the right active device. If either or both side
-     * is not active, it will be null on that position. Returns empty list on error.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getActiveDevices() {
-        if (VDBG) log("getActiveDevices()");
-        final IBluetoothHearingAid service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getActiveDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        verifyDeviceNotNull(device, "setConnectionPolicy");
-        final IBluetoothHearingAid service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                    && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                        || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        verifyDeviceNotNull(device, "getConnectionPolicy");
-        final IBluetoothHearingAid service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Helper for converting a state to a string.
-     *
-     * For debug use only - strings are not internationalized.
-     *
-     * @hide
-     */
-    public static String stateToString(int state) {
-        switch (state) {
-            case STATE_DISCONNECTED:
-                return "disconnected";
-            case STATE_CONNECTING:
-                return "connecting";
-            case STATE_CONNECTED:
-                return "connected";
-            case STATE_DISCONNECTING:
-                return "disconnecting";
-            default:
-                return "<unknown state " + state + ">";
-        }
-    }
-
-    /**
-     * Tells remote device to set an absolute volume.
-     *
-     * @param volume Absolute volume to be set on remote
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void setVolume(int volume) {
-        if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
-        final IBluetoothHearingAid service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setVolume(volume, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Get the HiSyncId (unique hearing aid device identifier) of the device.
-     *
-     * <a href=https://source.android.com/devices/bluetooth/asha#hisyncid>HiSyncId documentation
-     * can be found here</a>
-     *
-     * @param device Bluetooth device
-     * @return the HiSyncId of the device
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public long getHiSyncId(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getHiSyncId(" + device + ")");
-        verifyDeviceNotNull(device, "getConnectionPolicy");
-        final IBluetoothHearingAid service = getService();
-        final long defaultValue = HI_SYNC_ID_INVALID;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Long> recv = new SynchronousResultReceiver();
-                service.getHiSyncId(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the side of the device.
-     *
-     * @param device Bluetooth device.
-     * @return SIDE_LEFT or SIDE_RIGHT
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getDeviceSide(BluetoothDevice device) {
-        if (VDBG) log("getDeviceSide(" + device + ")");
-        final IBluetoothHearingAid service = getService();
-        final int defaultValue = SIDE_LEFT;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getDeviceSide(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the mode of the device.
-     *
-     * @param device Bluetooth device
-     * @return MODE_MONAURAL or MODE_BINAURAL
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getDeviceMode(BluetoothDevice device) {
-        if (VDBG) log("getDeviceMode(" + device + ")");
-        final IBluetoothHearingAid service = getService();
-        final int defaultValue = MODE_MONAURAL;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getDeviceMode(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
-    }
-
-    private void verifyDeviceNotNull(BluetoothDevice device, String methodName) {
-        if (device == null) {
-            Log.e(TAG, methodName + ": device param is null");
-            throw new IllegalArgumentException("Device cannot be null");
-        }
-    }
-
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
deleted file mode 100644
index 44a355b..0000000
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ /dev/null
@@ -1,848 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Provides the public APIs to control the Bluetooth HID Device profile.
- *
- * <p>BluetoothHidDevice is a proxy object for controlling the Bluetooth HID Device Service via IPC.
- * Use {@link BluetoothAdapter#getProfileProxy} to get the BluetoothHidDevice proxy object.
- */
-public final class BluetoothHidDevice implements BluetoothProfile {
-    private static final String TAG = BluetoothHidDevice.class.getSimpleName();
-    private static final boolean DBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the Input Host profile.
-     *
-     * <p>This intent will have 3 extras:
-     *
-     * <ul>
-     *   <li>{@link #EXTRA_STATE} - The current state of the profile.
-     *   <li>{@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
-     *   <li>{@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
-     * </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}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Constant representing unspecified HID device subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS1_NONE = (byte) 0x00;
-    /**
-     * Constant representing keyboard subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40;
-    /**
-     * Constant representing mouse subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS1_MOUSE = (byte) 0x80;
-    /**
-     * Constant representing combo keyboard and mouse subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS1_COMBO = (byte) 0xC0;
-
-    /**
-     * Constant representing uncategorized HID device subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_UNCATEGORIZED = (byte) 0x00;
-    /**
-     * Constant representing joystick subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_JOYSTICK = (byte) 0x01;
-    /**
-     * Constant representing gamepad subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
-    /**
-     * Constant representing remote control subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
-    /**
-     * Constant representing sensing device subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
-    /**
-     * Constant representing digitizer tablet subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
-    /**
-     * Constant representing card reader subclass.
-     *
-     * @see #registerApp (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     *     BluetoothHidDeviceAppQosSettings, Executor, Callback)
-     */
-    public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
-
-    /**
-     * Constant representing HID Input Report type.
-     *
-     * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
-     */
-    public static final byte REPORT_TYPE_INPUT = (byte) 1;
-    /**
-     * Constant representing HID Output Report type.
-     *
-     * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
-     */
-    public static final byte REPORT_TYPE_OUTPUT = (byte) 2;
-    /**
-     * Constant representing HID Feature Report type.
-     *
-     * @see Callback#onGetReport(BluetoothDevice, byte, byte, int)
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     * @see Callback#onInterruptData(BluetoothDevice, byte, byte[])
-     */
-    public static final byte REPORT_TYPE_FEATURE = (byte) 3;
-
-    /**
-     * Constant representing success response for Set Report.
-     *
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     */
-    public static final byte ERROR_RSP_SUCCESS = (byte) 0;
-    /**
-     * Constant representing error response for Set Report due to "not ready".
-     *
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     */
-    public static final byte ERROR_RSP_NOT_READY = (byte) 1;
-    /**
-     * Constant representing error response for Set Report due to "invalid report ID".
-     *
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     */
-    public static final byte ERROR_RSP_INVALID_RPT_ID = (byte) 2;
-    /**
-     * Constant representing error response for Set Report due to "unsupported request".
-     *
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     */
-    public static final byte ERROR_RSP_UNSUPPORTED_REQ = (byte) 3;
-    /**
-     * Constant representing error response for Set Report due to "invalid parameter".
-     *
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     */
-    public static final byte ERROR_RSP_INVALID_PARAM = (byte) 4;
-    /**
-     * Constant representing error response for Set Report with unknown reason.
-     *
-     * @see Callback#onSetReport(BluetoothDevice, byte, byte, byte[])
-     */
-    public static final byte ERROR_RSP_UNKNOWN = (byte) 14;
-
-    /**
-     * Constant representing boot protocol mode used set by host. Default is always {@link
-     * #PROTOCOL_REPORT_MODE} unless notified otherwise.
-     *
-     * @see Callback#onSetProtocol(BluetoothDevice, byte)
-     */
-    public static final byte PROTOCOL_BOOT_MODE = (byte) 0;
-    /**
-     * Constant representing report protocol mode used set by host. Default is always {@link
-     * #PROTOCOL_REPORT_MODE} unless notified otherwise.
-     *
-     * @see Callback#onSetProtocol(BluetoothDevice, byte)
-     */
-    public static final byte PROTOCOL_REPORT_MODE = (byte) 1;
-
-    /**
-     * The template class that applications use to call callback functions on events from the HID
-     * host. Callback functions are wrapped in this class and registered to the Android system
-     * during app registration.
-     */
-    public abstract static class Callback {
-
-        private static final String TAG = "BluetoothHidDevCallback";
-
-        /**
-         * Callback called when application registration state changes. Usually it's called due to
-         * either {@link BluetoothHidDevice#registerApp (String, String, String, byte, byte[],
-         * Executor, Callback)} or {@link BluetoothHidDevice#unregisterApp()} , but can be also
-         * unsolicited in case e.g. Bluetooth was turned off in which case application is
-         * unregistered automatically.
-         *
-         * @param pluggedDevice {@link BluetoothDevice} object which represents host that currently
-         *     has Virtual Cable established with device. Only valid when application is registered,
-         *     can be <code>null</code>.
-         * @param registered <code>true</code> if application is registered, <code>false</code>
-         *     otherwise.
-         */
-        public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
-            Log.d(
-                    TAG,
-                    "onAppStatusChanged: pluggedDevice="
-                            + pluggedDevice
-                            + " registered="
-                            + registered);
-        }
-
-        /**
-         * Callback called when connection state with remote host was changed. Application can
-         * assume than Virtual Cable is established when called with {@link
-         * BluetoothProfile#STATE_CONNECTED} <code>state</code>.
-         *
-         * @param device {@link BluetoothDevice} object representing host device which connection
-         *     state was changed.
-         * @param state Connection state as defined in {@link BluetoothProfile}.
-         */
-        public void onConnectionStateChanged(BluetoothDevice device, int state) {
-            Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state);
-        }
-
-        /**
-         * Callback called when GET_REPORT is received from remote host. Should be replied by
-         * application using {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte,
-         * byte[])}.
-         *
-         * @param type Requested Report Type.
-         * @param id Requested Report Id, can be 0 if no Report Id are defined in descriptor.
-         * @param bufferSize Requested buffer size, application shall respond with at least given
-         *     number of bytes.
-         */
-        public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
-            Log.d(
-                    TAG,
-                    "onGetReport: device="
-                            + device
-                            + " type="
-                            + type
-                            + " id="
-                            + id
-                            + " bufferSize="
-                            + bufferSize);
-        }
-
-        /**
-         * Callback called when SET_REPORT is received from remote host. In case received data are
-         * invalid, application shall respond with {@link
-         * BluetoothHidDevice#reportError(BluetoothDevice, byte)}.
-         *
-         * @param type Report Type.
-         * @param id Report Id.
-         * @param data Report data.
-         */
-        public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
-            Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
-        }
-
-        /**
-         * Callback called when SET_PROTOCOL is received from remote host. Application shall use
-         * this information to send only reports valid for given protocol mode. By default, {@link
-         * BluetoothHidDevice#PROTOCOL_REPORT_MODE} shall be assumed.
-         *
-         * @param protocol Protocol Mode.
-         */
-        public void onSetProtocol(BluetoothDevice device, byte protocol) {
-            Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
-        }
-
-        /**
-         * Callback called when report data is received over interrupt channel. Report Type is
-         * assumed to be {@link BluetoothHidDevice#REPORT_TYPE_OUTPUT}.
-         *
-         * @param reportId Report Id.
-         * @param data Report data.
-         */
-        public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
-            Log.d(TAG, "onInterruptData: device=" + device + " reportId=" + reportId);
-        }
-
-        /**
-         * Callback called when Virtual Cable is removed. After this callback is received connection
-         * will be disconnected automatically.
-         */
-        public void onVirtualCableUnplug(BluetoothDevice device) {
-            Log.d(TAG, "onVirtualCableUnplug: device=" + device);
-        }
-    }
-
-    private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
-
-        private final Executor mExecutor;
-        private final Callback mCallback;
-        private final AttributionSource mAttributionSource;
-
-        CallbackWrapper(Executor executor, Callback callback, AttributionSource attributionSource) {
-            mExecutor = executor;
-            mCallback = callback;
-            mAttributionSource = attributionSource;
-        }
-
-        @Override
-        public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered) {
-            Attributable.setAttributionSource(pluggedDevice, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onAppStatusChanged(pluggedDevice, registered));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onConnectionStateChanged(BluetoothDevice device, int state) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onConnectionStateChanged(device, state));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onGetReport(device, type, id, bufferSize));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onSetReport(device, type, id, data));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onSetProtocol(BluetoothDevice device, byte protocol) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onSetProtocol(device, protocol));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onInterruptData(BluetoothDevice device, byte reportId, byte[] data) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onInterruptData(device, reportId, data));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void onVirtualCableUnplug(BluetoothDevice device) {
-            Attributable.setAttributionSource(device, mAttributionSource);
-            final long token = clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onVirtualCableUnplug(device));
-            } finally {
-                restoreCallingIdentity(token);
-            }
-        }
-    }
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE,
-                    "BluetoothHidDevice", IBluetoothHidDevice.class.getName()) {
-                @Override
-                public IBluetoothHidDevice getServiceInterface(IBinder service) {
-                    return IBluetoothHidDevice.Stub.asInterface(service);
-                }
-    };
-
-    BluetoothHidDevice(Context context, ServiceListener listener, BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothHidDevice getService() {
-        return mProfileConnector.getService();
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        final IBluetoothHidDevice service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        final IBluetoothHidDevice service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        final IBluetoothHidDevice service = getService();
-        final int defaultValue = STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Registers application to be used for HID device. Connections to HID Device are only possible
-     * when application is registered. Only one application can be registered at one time. When an
-     * application is registered, the HID Host service will be disabled until it is unregistered.
-     * When no longer used, application should be unregistered using {@link #unregisterApp()}. The
-     * app will be automatically unregistered if it is not foreground. The registration status
-     * should be tracked by the application by handling callback from Callback#onAppStatusChanged.
-     * The app registration status is not related to the return value of this method.
-     *
-     * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record. The HID
-     *     Device SDP record is required.
-     * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings. The
-     *     Incoming QoS Settings is not required. Use null or default
-     *     BluetoothHidDeviceAppQosSettings.Builder for default values.
-     * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings. The
-     *     Outgoing QoS Settings is not required. Use null or default
-     *     BluetoothHidDeviceAppQosSettings.Builder for default values.
-     * @param executor {@link Executor} object on which callback will be executed. The Executor
-     *     object is required.
-     * @param callback {@link Callback} object to which callback messages will be sent. The Callback
-     *     object is required.
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean registerApp(
-            BluetoothHidDeviceAppSdpSettings sdp,
-            BluetoothHidDeviceAppQosSettings inQos,
-            BluetoothHidDeviceAppQosSettings outQos,
-            Executor executor,
-            Callback callback) {
-        boolean result = false;
-
-        if (sdp == null) {
-            throw new IllegalArgumentException("sdp parameter cannot be null");
-        }
-
-        if (executor == null) {
-            throw new IllegalArgumentException("executor parameter cannot be null");
-        }
-
-        if (callback == null) {
-            throw new IllegalArgumentException("callback parameter cannot be null");
-        }
-
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = result;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                CallbackWrapper cbw = new CallbackWrapper(executor, callback, mAttributionSource);
-                service.registerApp(sdp, inQos, outQos, cbw, mAttributionSource, recv);
-                result = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Unregisters application. Active connection will be disconnected and no new connections will
-     * be allowed until registered again using {@link #registerApp
-     * (BluetoothHidDeviceAppQosSettings, BluetoothHidDeviceAppQosSettings,
-     * BluetoothHidDeviceAppQosSettings, Executor, Callback)}. The registration status should be
-     * tracked by the application by handling callback from Callback#onAppStatusChanged. The app
-     * registration status is not related to the return value of this method.
-     *
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean unregisterApp() {
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.unregisterApp(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sends report to remote host using interrupt channel.
-     *
-     * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in
-     *     descriptor.
-     * @param data Report data, not including Report Id.
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.sendReport(device, id, data, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sends report to remote host as reply for GET_REPORT request from {@link
-     * Callback#onGetReport(BluetoothDevice, byte, byte, int)}.
-     *
-     * @param type Report Type, as in request.
-     * @param id Report Id, as in request.
-     * @param data Report data, not including Report Id.
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.replyReport(device, type, id, data, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Sends error handshake message as reply for invalid SET_REPORT request from {@link
-     * Callback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
-     *
-     * @param error Error to be sent for SET_REPORT via HANDSHAKE.
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean reportError(BluetoothDevice device, byte error) {
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.reportError(device, error, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Gets the application name of the current HidDeviceService user.
-     *
-     * @return the current user name, or empty string if cannot get the name
-     * {@hide}
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public String getUserAppName() {
-        final IBluetoothHidDevice service = getService();
-        final String defaultValue = "";
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<String> recv = new SynchronousResultReceiver();
-                service.getUserAppName(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiates connection to host which is currently paired with this device. If the application
-     * is not registered, #connect(BluetoothDevice) will fail. The connection state should be
-     * tracked by the application by handling callback from Callback#onConnectionStateChanged. The
-     * connection state is not related to the return value of this method.
-     *
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connect(BluetoothDevice device) {
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Disconnects from currently connected host. The connection state should be tracked by the
-     * application by handling callback from Callback#onConnectionStateChanged. The connection state
-     * is not related to the return value of this method.
-     *
-     * @return true if the command is successfully sent; otherwise false.
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Connects Hid Device if connectionPolicy is {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED}
-     * and disconnects Hid device if connectionPolicy is
-     * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN}.
-     *
-     * <p> The device should already be paired.
-     * Connection policy can be one of:
-     * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED},
-     * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN},
-     * {@link BluetoothProfile#CONNECTION_POLICY_UNKNOWN}
-     *
-     * @param device Paired bluetooth device
-     * @param connectionPolicy determines whether hid device should be connected or disconnected
-     * @return true if hid device is connected or disconnected, false otherwise
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothHidDevice service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
-    }
-
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
-    }
-
-    private static void log(String msg) {
-        if (DBG) {
-            Log.d(TAG, msg);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
deleted file mode 100644
index b21ebe5..0000000
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents the Quality of Service (QoS) settings for a Bluetooth HID Device application.
- *
- * <p>The BluetoothHidDevice framework will update the L2CAP QoS settings for the app during
- * registration.
- *
- * <p>{@see BluetoothHidDevice}
- */
-public final class BluetoothHidDeviceAppQosSettings implements Parcelable {
-
-    private final int mServiceType;
-    private final int mTokenRate;
-    private final int mTokenBucketSize;
-    private final int mPeakBandwidth;
-    private final int mLatency;
-    private final int mDelayVariation;
-
-    public static final int SERVICE_NO_TRAFFIC = 0x00;
-    public static final int SERVICE_BEST_EFFORT = 0x01;
-    public static final int SERVICE_GUARANTEED = 0x02;
-
-    public static final int MAX = (int) 0xffffffff;
-
-    /**
-     * Create a BluetoothHidDeviceAppQosSettings object for the Bluetooth L2CAP channel. The QoS
-     * Settings is optional. Please refer to Bluetooth HID Specfication v1.1.1 Section 5.2 and
-     * Appendix D for parameters.
-     *
-     * @param serviceType L2CAP service type, default = SERVICE_BEST_EFFORT
-     * @param tokenRate L2CAP token rate, default = 0
-     * @param tokenBucketSize L2CAP token bucket size, default = 0
-     * @param peakBandwidth L2CAP peak bandwidth, default = 0
-     * @param latency L2CAP latency, default = MAX
-     * @param delayVariation L2CAP delay variation, default = MAX
-     */
-    public BluetoothHidDeviceAppQosSettings(
-            int serviceType,
-            int tokenRate,
-            int tokenBucketSize,
-            int peakBandwidth,
-            int latency,
-            int delayVariation) {
-        mServiceType = serviceType;
-        mTokenRate = tokenRate;
-        mTokenBucketSize = tokenBucketSize;
-        mPeakBandwidth = peakBandwidth;
-        mLatency = latency;
-        mDelayVariation = delayVariation;
-    }
-
-    public int getServiceType() {
-        return mServiceType;
-    }
-
-    public int getTokenRate() {
-        return mTokenRate;
-    }
-
-    public int getTokenBucketSize() {
-        return mTokenBucketSize;
-    }
-
-    public int getPeakBandwidth() {
-        return mPeakBandwidth;
-    }
-
-    public int getLatency() {
-        return mLatency;
-    }
-
-    public int getDelayVariation() {
-        return mDelayVariation;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHidDeviceAppQosSettings> CREATOR =
-            new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() {
-
-                @Override
-                public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) {
-
-                    return new BluetoothHidDeviceAppQosSettings(
-                            in.readInt(),
-                            in.readInt(),
-                            in.readInt(),
-                            in.readInt(),
-                            in.readInt(),
-                            in.readInt());
-                }
-
-                @Override
-                public BluetoothHidDeviceAppQosSettings[] newArray(int size) {
-                    return new BluetoothHidDeviceAppQosSettings[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mServiceType);
-        out.writeInt(mTokenRate);
-        out.writeInt(mTokenBucketSize);
-        out.writeInt(mPeakBandwidth);
-        out.writeInt(mLatency);
-        out.writeInt(mDelayVariation);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
deleted file mode 100644
index 4e1a2aa..0000000
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.EventLog;
-
-
-/**
- * Represents the Service Discovery Protocol (SDP) settings for a Bluetooth HID Device application.
- *
- * <p>The BluetoothHidDevice framework adds the SDP record during app registration, so that the
- * Android device can be discovered as a Bluetooth HID Device.
- *
- * <p>{@see BluetoothHidDevice}
- */
-public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
-
-    private static final int MAX_DESCRIPTOR_SIZE = 2048;
-
-    private final String mName;
-    private final String mDescription;
-    private final String mProvider;
-    private final byte mSubclass;
-    private final byte[] mDescriptors;
-
-    /**
-     * Create a BluetoothHidDeviceAppSdpSettings object for the Bluetooth SDP record.
-     *
-     * @param name Name of this Bluetooth HID device. Maximum length is 50 bytes.
-     * @param description Description for this Bluetooth HID device. Maximum length is 50 bytes.
-     * @param provider Provider of this Bluetooth HID device. Maximum length is 50 bytes.
-     * @param subclass Subclass of this Bluetooth HID device. See <a
-     *     href="www.usb.org/developers/hidpage/HID1_11.pdf">
-     *     www.usb.org/developers/hidpage/HID1_11.pdf Section 4.2</a>
-     * @param descriptors Descriptors of this Bluetooth HID device. See <a
-     *     href="www.usb.org/developers/hidpage/HID1_11.pdf">
-     *     www.usb.org/developers/hidpage/HID1_11.pdf Chapter 6</a> Maximum length is 2048 bytes.
-     */
-    public BluetoothHidDeviceAppSdpSettings(
-            String name, String description, String provider, byte subclass, byte[] descriptors) {
-        mName = name;
-        mDescription = description;
-        mProvider = provider;
-        mSubclass = subclass;
-
-        if (descriptors == null || descriptors.length > MAX_DESCRIPTOR_SIZE) {
-            EventLog.writeEvent(0x534e4554, "119819889", -1, "");
-            throw new IllegalArgumentException("descriptors must be not null and shorter than "
-                    + MAX_DESCRIPTOR_SIZE);
-        }
-        mDescriptors = descriptors.clone();
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public String getDescription() {
-        return mDescription;
-    }
-
-    public String getProvider() {
-        return mProvider;
-    }
-
-    public byte getSubclass() {
-        return mSubclass;
-    }
-
-    public byte[] getDescriptors() {
-        return mDescriptors;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothHidDeviceAppSdpSettings> CREATOR =
-            new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() {
-
-                @Override
-                public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) {
-
-                    return new BluetoothHidDeviceAppSdpSettings(
-                            in.readString(),
-                            in.readString(),
-                            in.readString(),
-                            in.readByte(),
-                            in.createByteArray());
-                }
-
-                @Override
-                public BluetoothHidDeviceAppSdpSettings[] newArray(int size) {
-                    return new BluetoothHidDeviceAppSdpSettings[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(mName);
-        out.writeString(mDescription);
-        out.writeString(mProvider);
-        out.writeByte(mSubclass);
-        out.writeByteArray(mDescriptors);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
deleted file mode 100644
index ecbeddf..0000000
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ /dev/null
@@ -1,831 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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 static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-
-/**
- * This class provides the public APIs to control the Bluetooth Input
- * Device Profile.
- *
- * <p>BluetoothHidHost is a proxy object for controlling the Bluetooth
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothHidHost proxy object.
- *
- * <p>Each method is protected with its appropriate permission.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothHidHost implements BluetoothProfile {
-    private static final String TAG = "BluetoothHidHost";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the Input
-     * Device profile.
-     *
-     * <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}.
-     */
-    @SuppressLint("ActionValue")
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PROTOCOL_MODE_CHANGED =
-            "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
-
-    /**
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_HANDSHAKE =
-            "android.bluetooth.input.profile.action.HANDSHAKE";
-
-    /**
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_REPORT =
-            "android.bluetooth.input.profile.action.REPORT";
-
-    /**
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
-            "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
-
-    /**
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_IDLE_TIME_CHANGED =
-            "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED";
-
-    /**
-     * Return codes for the connect and disconnect Bluez / Dbus calls.
-     *
-     * @hide
-     */
-    public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
-
-    /**
-     * @hide
-     */
-    public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
-
-    /**
-     * @hide
-     */
-    public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
-
-    /**
-     * @hide
-     */
-    public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
-
-    /**
-     * @hide
-     */
-    public static final int INPUT_OPERATION_SUCCESS = 5004;
-
-    /**
-     * @hide
-     */
-    public static final int PROTOCOL_REPORT_MODE = 0;
-
-    /**
-     * @hide
-     */
-    public static final int PROTOCOL_BOOT_MODE = 1;
-
-    /**
-     * @hide
-     */
-    public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
-
-    /*  int reportType, int reportType, int bufferSize */
-    /**
-     * @hide
-     */
-    public static final byte REPORT_TYPE_INPUT = 1;
-
-    /**
-     * @hide
-     */
-    public static final byte REPORT_TYPE_OUTPUT = 2;
-
-    /**
-     * @hide
-     */
-    public static final byte REPORT_TYPE_FEATURE = 3;
-
-    /**
-     * @hide
-     */
-    public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
-
-    /**
-     * @hide
-     */
-    public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_PROTOCOL_MODE =
-            "android.bluetooth.BluetoothHidHost.extra.PROTOCOL_MODE";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_REPORT_TYPE =
-            "android.bluetooth.BluetoothHidHost.extra.REPORT_TYPE";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_REPORT_ID =
-            "android.bluetooth.BluetoothHidHost.extra.REPORT_ID";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_REPORT_BUFFER_SIZE =
-            "android.bluetooth.BluetoothHidHost.extra.REPORT_BUFFER_SIZE";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_REPORT = "android.bluetooth.BluetoothHidHost.extra.REPORT";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_STATUS = "android.bluetooth.BluetoothHidHost.extra.STATUS";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_VIRTUAL_UNPLUG_STATUS =
-            "android.bluetooth.BluetoothHidHost.extra.VIRTUAL_UNPLUG_STATUS";
-
-    /**
-     * @hide
-     */
-    public static final String EXTRA_IDLE_TIME =
-            "android.bluetooth.BluetoothHidHost.extra.IDLE_TIME";
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST,
-                    "BluetoothHidHost", IBluetoothHidHost.class.getName()) {
-                @Override
-                public IBluetoothHidHost getServiceInterface(IBinder service) {
-                    return IBluetoothHidHost.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothHidHost proxy object for interacting with the local
-     * Bluetooth Service which handles the InputDevice profile
-     */
-    /* package */ BluetoothHidHost(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /*package*/ void close() {
-        if (VDBG) log("close()");
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothHidHost getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Initiate connection to a profile of the remote bluetooth device.
-     *
-     * <p> The system supports connection to multiple input devices.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @SystemApi
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothHidHost service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothHidHost service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @SystemApi
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        if (device == null) {
-            throw new IllegalArgumentException("device must not be null");
-        }
-        final IBluetoothHidHost service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        if (device == null) {
-            throw new IllegalArgumentException("device must not be null");
-        }
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        if (device == null) {
-            throw new IllegalArgumentException("device must not be null");
-        }
-        final IBluetoothHidHost service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-
-    /**
-     * Initiate virtual unplug for a HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean virtualUnplug(BluetoothDevice device) {
-        if (DBG) log("virtualUnplug(" + device + ")");
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.virtualUnplug(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Get_Protocol_Mode command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean getProtocolMode(BluetoothDevice device) {
-        if (VDBG) log("getProtocolMode(" + device + ")");
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getProtocolMode(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Set_Protocol_Mode command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
-        if (DBG) log("setProtocolMode(" + device + ")");
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setProtocolMode(device, protocolMode, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Get_Report command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @param reportType Report type
-     * @param reportId Report ID
-     * @param bufferSize Report receiving buffer size
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean getReport(BluetoothDevice device, byte reportType, byte reportId,
-            int bufferSize) {
-        if (VDBG) {
-            log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
-                    + "bufferSize=" + bufferSize);
-        }
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getReport(device, reportType, reportId, bufferSize, mAttributionSource,
-                        recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Set_Report command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @param reportType Report type
-     * @param report Report receiving buffer size
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setReport(BluetoothDevice device, byte reportType, String report) {
-        if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setReport(device, reportType, report, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Send_Data command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @param report Report to send
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean sendData(BluetoothDevice device, String report) {
-        if (DBG) log("sendData(" + device + "), report=" + report);
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.sendData(device, report, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Get_Idle_Time command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean getIdleTime(BluetoothDevice device) {
-        if (DBG) log("getIdletime(" + device + ")");
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getIdleTime(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send Set_Idle_Time command to the connected HID input device.
-     *
-     * @param device Remote Bluetooth Device
-     * @param idleTime Idle time to be set on HID Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
-        if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
-        final IBluetoothHidHost service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setIdleTime(device, idleTime, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothInputStream.java b/core/java/android/bluetooth/BluetoothInputStream.java
deleted file mode 100644
index 95f9229..0000000
--- a/core/java/android/bluetooth/BluetoothInputStream.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.SuppressLint;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * BluetoothInputStream.
- *
- * Used to write to a Bluetooth socket.
- *
- * @hide
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-/*package*/ final class BluetoothInputStream extends InputStream {
-    private BluetoothSocket mSocket;
-
-    /*package*/ BluetoothInputStream(BluetoothSocket s) {
-        mSocket = s;
-    }
-
-    /**
-     * Return number of bytes available before this stream will block.
-     */
-    public int available() throws IOException {
-        return mSocket.available();
-    }
-
-    public void close() throws IOException {
-        mSocket.close();
-    }
-
-    /**
-     * Reads a single byte from this stream and returns it as an integer in the
-     * range from 0 to 255. Returns -1 if the end of the stream has been
-     * reached. Blocks until one byte has been read, the end of the source
-     * stream is detected or an exception is thrown.
-     *
-     * @return the byte read or -1 if the end of stream has been reached.
-     * @throws IOException if the stream is closed or another IOException occurs.
-     * @since Android 1.5
-     */
-    public int read() throws IOException {
-        byte[] b = new byte[1];
-        int ret = mSocket.read(b, 0, 1);
-        if (ret == 1) {
-            return (int) b[0] & 0xff;
-        } else {
-            return -1;
-        }
-    }
-
-    /**
-     * Reads at most {@code length} bytes from this stream and stores them in
-     * the byte array {@code b} starting at {@code offset}.
-     *
-     * @param b the byte array in which to store the bytes read.
-     * @param offset the initial position in {@code buffer} to store the bytes read from this
-     * stream.
-     * @param length the maximum number of bytes to store in {@code b}.
-     * @return the number of bytes actually read or -1 if the end of the stream has been reached.
-     * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code length < 0}, or if {@code
-     * offset + length} is greater than the length of {@code b}.
-     * @throws IOException if the stream is closed or another IOException occurs.
-     * @since Android 1.5
-     */
-    public int read(byte[] b, int offset, int length) throws IOException {
-        if (b == null) {
-            throw new NullPointerException("byte array is null");
-        }
-        if ((offset | length) < 0 || length > b.length - offset) {
-            throw new ArrayIndexOutOfBoundsException("invalid offset or length");
-        }
-        return mSocket.read(b, offset, length);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
deleted file mode 100644
index 15db686..0000000
--- a/core/java/android/bluetooth/BluetoothLeAudio.java
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Copyright 2020 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 static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the LeAudio profile.
- *
- * <p>BluetoothLeAudio is a proxy object for controlling the Bluetooth LE Audio
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothLeAudio proxy object.
- *
- * <p> Android only supports one set of connected Bluetooth LeAudio device at a time. Each
- * method is protected with its appropriate permission.
- */
-public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
-    private static final String TAG = "BluetoothLeAudio";
-    private static final boolean DBG = false;
-    private static final boolean VDBG = false;
-
-    private CloseGuard mCloseGuard;
-
-    /**
-     * Intent used to broadcast the change in connection state of the LeAudio
-     * profile. Please note that in the binaural case, there will be two different LE devices for
-     * the left and right side and each device will have their own connection state changes.
-     *
-     * <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}.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
-
-    /**
-     * Intent used to broadcast the selection of a connected device as active.
-     *
-     * <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>
-     * </ul>
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED =
-            "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 unspecified audio content.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_UNSPECIFIED = 0x0001;
-
-    /**
-     * 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;
-
-    /**
-     * Indicates instructional audio as, for example, in navigation, traffic announcements
-     * or user guidance.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_INSTRUCTIONAL = 0x0008;
-
-    /**
-     * Indicates attention seeking audio as, for example, in beeps signalling arrival of a message
-     * or keyboard clicks.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_ATTENTION_SEEKING = 0x0010;
-
-    /**
-     * Indicates immediate alerts as, for example, in a low battery alarm, timer expiry or alarm
-     * clock.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_IMMEDIATE_ALERT = 0x0020;
-
-    /**
-     * Indicates man machine communication as, for example, with voice recognition or virtual
-     * assistant.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_MAN_MACHINE = 0x0040;
-
-    /**
-     * Indicates emergency alerts as, for example, with fire alarms or other urgent alerts.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_EMERGENCY_ALERT = 0x0080;
-
-    /**
-     * Indicates ringtone as in a call alert.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_RINGTONE = 0x0100;
-
-    /**
-     * Indicates audio associated with a television program and/or with metadata conforming to the
-     * Bluetooth Broadcast TV profile.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_TV = 0x0200;
-
-    /**
-     * Indicates audio associated with a low latency live audio stream.
-     *
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_LIVE = 0x0400;
-
-    /**
-     * Indicates audio associated with a video game stream.
-     * @hide
-     */
-    public static final int CONTEXT_TYPE_GAME = 0x0800;
-
-    /**
-     * 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_ACTIVE} </li>
-     * <li> {@link #GROUP_STATUS_INACTIVE} </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 final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    /**
-     * Indicating that group is Active ( Audio device is available )
-     * @hide
-     */
-    public static final int GROUP_STATUS_ACTIVE = IBluetoothLeAudio.GROUP_STATUS_ACTIVE;
-
-    /**
-     * Indicating that group is Inactive ( Audio device is not available )
-     * @hide
-     */
-    public static final int GROUP_STATUS_INACTIVE = IBluetoothLeAudio.GROUP_STATUS_INACTIVE;
-
-    /**
-     * Indicating that node has been added to the group.
-     * @hide
-     */
-    public static final int GROUP_NODE_ADDED = IBluetoothLeAudio.GROUP_NODE_ADDED;
-
-    /**
-     * Indicating that node has been removed from the group.
-     * @hide
-     */
-    public static final int GROUP_NODE_REMOVED = IBluetoothLeAudio.GROUP_NODE_REMOVED;
-
-    private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio",
-                    IBluetoothLeAudio.class.getName()) {
-                @Override
-                public IBluetoothLeAudio getServiceInterface(IBinder service) {
-                    return IBluetoothLeAudio.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothLeAudio proxy object for interacting with the local
-     * Bluetooth LeAudio service.
-     */
-    /* package */ BluetoothLeAudio(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-        mCloseGuard = new CloseGuard();
-        mCloseGuard.open("close");
-    }
-
-    /**
-     * @hide
-     */
-    public void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothLeAudio getService() {
-        return mProfileConnector.getService();
-    }
-
-    protected void finalize() {
-        if (mCloseGuard != null) {
-            mCloseGuard.warnIfOpen();
-        }
-        close();
-    }
-
-    /**
-     * Initiate connection to a profile of the remote bluetooth device.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean connect(@Nullable BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothLeAudio service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(@Nullable BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothLeAudio service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothLeAudio service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
-            @NonNull int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothLeAudio service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        final IBluetoothLeAudio service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Select a connected device as active.
-     *
-     * The active device selection is per profile. An active device's
-     * purpose is profile-specific. For example, LeAudio audio
-     * streaming is to the active LeAudio device. If a remote device
-     * is not connected, it cannot be selected as active.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is not connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that the
-     * {@link #ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
-     * with the active device.
-     *
-     *
-     * @param device the remote Bluetooth device. Could be null to clear
-     * the active device and stop streaming audio to a Bluetooth device.
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean setActiveDevice(@Nullable BluetoothDevice device) {
-        if (DBG) log("setActiveDevice(" + device + ")");
-        final IBluetoothLeAudio service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled() && ((device == null) || isValidDevice(device))) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setActiveDevice(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the connected LeAudio devices that are active
-     *
-     * @return the list of active devices. Returns empty list on error.
-     * @hide
-     */
-    @NonNull
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getActiveDevices() {
-        if (VDBG) log("getActiveDevice()");
-        final IBluetoothLeAudio service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getActiveDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get device group id. Devices with same group id belong to same group (i.e left and right
-     * earbud)
-     * @param device LE Audio capable device
-     * @return group id that this device currently belongs to
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getGroupId(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getGroupId()");
-        final IBluetoothLeAudio service = getService();
-        final int defaultValue = GROUP_ID_INVALID;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getGroupId(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set volume for the streaming devices
-     *
-     * @param volume volume to set
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED})
-    public void setVolume(int volume) {
-        if (VDBG) log("setVolume(vol: " + volume + " )");
-        final IBluetoothLeAudio service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setVolume(volume, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Add device to the given group.
-     * @param group_id group ID the device is being added to
-     * @param device the active device
-     * @return true on success, otherwise false
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED
-    })
-    public boolean groupAddNode(int group_id, @NonNull BluetoothDevice device) {
-        if (VDBG) log("groupAddNode()");
-        final IBluetoothLeAudio service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.groupAddNode(group_id, device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Remove device from a given group.
-     * @param group_id group ID the device is being removed from
-     * @param device the active device
-     * @return true on success, otherwise false
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED
-    })
-    public boolean groupRemoveNode(int group_id, @NonNull BluetoothDevice device) {
-        if (VDBG) log("groupRemoveNode()");
-        final IBluetoothLeAudio service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.groupRemoveNode(group_id, device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothLeAudio service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled() && isValidDevice(device)
-                    && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                        || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothLeAudio service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (mAdapter.isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-
-    /**
-     * Helper for converting a state to a string.
-     *
-     * For debug use only - strings are not internationalized.
-     *
-     * @hide
-     */
-    public static String stateToString(int state) {
-        switch (state) {
-            case STATE_DISCONNECTED:
-                return "disconnected";
-            case STATE_CONNECTING:
-                return "connecting";
-            case STATE_CONNECTED:
-                return "connected";
-            case STATE_DISCONNECTING:
-                return "disconnecting";
-            default:
-                return "<unknown state " + state + ">";
-        }
-    }
-
-    private boolean isValidDevice(@Nullable BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
deleted file mode 100644
index dcaf4b6..0000000
--- a/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Represents the codec configuration for a Bluetooth LE Audio source device.
- * <p>Contains the source codec type.
- * <p>The source codec type values are the same as those supported by the
- * device hardware.
- *
- * {@see BluetoothLeAudioCodecConfig}
- */
-public final class BluetoothLeAudioCodecConfig {
-    // Add an entry for each source codec here.
-
-    /** @hide */
-    @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
-            SOURCE_CODEC_TYPE_LC3,
-            SOURCE_CODEC_TYPE_INVALID
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SourceCodecType {};
-
-    public static final int SOURCE_CODEC_TYPE_LC3 = 0;
-    public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
-
-    /**
-     * Represents the count of valid source codec types. Can be accessed via
-     * {@link #getMaxCodecType}.
-     */
-    private static final int SOURCE_CODEC_TYPE_MAX = 1;
-
-    private final @SourceCodecType int mCodecType;
-
-    /**
-     * Creates a new BluetoothLeAudioCodecConfig.
-     *
-     * @param codecType the source codec type
-     */
-    private BluetoothLeAudioCodecConfig(@SourceCodecType int codecType) {
-        mCodecType = codecType;
-    }
-
-    @Override
-    public String toString() {
-        return "{codecName:" + getCodecName() + "}";
-    }
-
-    /**
-     * Gets the codec type.
-     *
-     * @return the codec type
-     */
-    public @SourceCodecType int getCodecType() {
-        return mCodecType;
-    }
-
-    /**
-     * Returns the valid codec types count.
-     */
-    public static int getMaxCodecType() {
-        return SOURCE_CODEC_TYPE_MAX;
-    }
-
-    /**
-     * Gets the codec name.
-     *
-     * @return the codec name
-     */
-    public @NonNull String getCodecName() {
-        switch (mCodecType) {
-            case SOURCE_CODEC_TYPE_LC3:
-                return "LC3";
-            case SOURCE_CODEC_TYPE_INVALID:
-                return "INVALID CODEC";
-            default:
-                break;
-        }
-        return "UNKNOWN CODEC(" + mCodecType + ")";
-    }
-
-    /**
-     * Builder for {@link BluetoothLeAudioCodecConfig}.
-     * <p> By default, the codec type will be set to
-     * {@link BluetoothLeAudioCodecConfig#SOURCE_CODEC_TYPE_INVALID}
-     */
-    public static final class Builder {
-        private int mCodecType = BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
-
-        /**
-         * Set codec type for Bluetooth codec config.
-         *
-         * @param codecType of this codec
-         * @return the same Builder instance
-         */
-        public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
-            mCodecType = codecType;
-            return this;
-        }
-
-        /**
-         * Build {@link BluetoothLeAudioCodecConfig}.
-         * @return new BluetoothLeAudioCodecConfig built
-         */
-        public @NonNull BluetoothLeAudioCodecConfig build() {
-            return new BluetoothLeAudioCodecConfig(mCodecType);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcast.java b/core/java/android/bluetooth/BluetoothLeBroadcast.java
deleted file mode 100644
index fed9f91..0000000
--- a/core/java/android/bluetooth/BluetoothLeBroadcast.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.content.Context;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * This class provides the public APIs to control the Bluetooth LE Broadcast Source profile.
- *
- * <p>BluetoothLeBroadcast is a proxy object for controlling the Bluetooth LE Broadcast
- * Source Service via IPC. Use {@link BluetoothAdapter#getProfileProxy}
- * to get the BluetoothLeBroadcast proxy object.
- *
- * @hide
- */
-public final class BluetoothLeBroadcast implements BluetoothProfile {
-    private static final String TAG = "BluetoothLeBroadcast";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Constants used by the LE Audio Broadcast profile for the Broadcast state
-     *
-     * @hide
-     */
-    @IntDef(prefix = {"LE_AUDIO_BROADCAST_STATE_"}, value = {
-      LE_AUDIO_BROADCAST_STATE_DISABLED,
-      LE_AUDIO_BROADCAST_STATE_ENABLING,
-      LE_AUDIO_BROADCAST_STATE_ENABLED,
-      LE_AUDIO_BROADCAST_STATE_DISABLING,
-      LE_AUDIO_BROADCAST_STATE_PLAYING,
-      LE_AUDIO_BROADCAST_STATE_NOT_PLAYING
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LeAudioBroadcastState {}
-
-    /**
-     * Indicates that LE Audio Broadcast mode is currently disabled
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_STATE_DISABLED = 10;
-
-    /**
-     * Indicates that LE Audio Broadcast mode is being enabled
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_STATE_ENABLING = 11;
-
-    /**
-     * Indicates that LE Audio Broadcast mode is currently enabled
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_STATE_ENABLED = 12;
-    /**
-     * Indicates that LE Audio Broadcast mode is being disabled
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_STATE_DISABLING = 13;
-
-    /**
-     * Indicates that an LE Audio Broadcast mode is currently playing
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_STATE_PLAYING = 14;
-
-    /**
-     * Indicates that LE Audio Broadcast is currently not playing
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_STATE_NOT_PLAYING = 15;
-
-    /**
-     * Constants used by the LE Audio Broadcast profile for encryption key length
-     *
-     * @hide
-     */
-    @IntDef(prefix = {"LE_AUDIO_BROADCAST_ENCRYPTION_KEY_"}, value = {
-      LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT,
-      LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LeAudioEncryptionKeyLength {}
-
-    /**
-     * Indicates that the LE Audio Broadcast encryption key size is 32 bits.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT = 16;
-
-    /**
-     * Indicates that the LE Audio Broadcast encryption key size is 128 bits.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT = 17;
-
-    /**
-     * Interface for receiving events related to broadcasts
-     */
-    public interface Callback {
-        /**
-         * Called when broadcast state has changed
-         *
-         * @param prevState broadcast state before the change
-         * @param newState broadcast state after the change
-         */
-        @LeAudioBroadcastState
-        void onBroadcastStateChange(int prevState, int newState);
-        /**
-         * Called when encryption key has been updated
-         *
-         * @param success true if the key was updated successfully, false otherwise
-         */
-        void onEncryptionKeySet(boolean success);
-    }
-
-    /**
-     * Create a BluetoothLeBroadcast proxy object for interacting with the local
-     * LE Audio Broadcast Source service.
-     *
-     * @hide
-     */
-    /*package*/ BluetoothLeBroadcast(Context context,
-                                     BluetoothProfile.ServiceListener listener) {
-    }
-
-    /**
-     * Not supported since LE Audio Broadcasts do not establish a connection
-     *
-     * @throws UnsupportedOperationException
-     *
-     * @hide
-     */
-    @Override
-    public int getConnectionState(BluetoothDevice device) {
-        throw new UnsupportedOperationException(
-                   "LE Audio Broadcasts are not connection-oriented.");
-    }
-
-    /**
-     * Not supported since LE Audio Broadcasts do not establish a connection
-     *
-     * @throws UnsupportedOperationException
-     *
-     * @hide
-     */
-    @Override
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        throw new UnsupportedOperationException(
-                   "LE Audio Broadcasts are not connection-oriented.");
-    }
-
-    /**
-     * Not supported since LE Audio Broadcasts do not establish a connection
-     *
-     * @throws UnsupportedOperationException
-     *
-     * @hide
-     */
-    @Override
-    public List<BluetoothDevice> getConnectedDevices() {
-        throw new UnsupportedOperationException(
-                   "LE Audio Broadcasts are not connection-oriented.");
-    }
-
-    /**
-     * Enable LE Audio Broadcast mode.
-     *
-     * Generates a new broadcast ID and enables sending of encrypted or unencrypted
-     * isochronous PDUs
-     *
-     * @hide
-     */
-    public int enableBroadcastMode() {
-        if (DBG) log("enableBroadcastMode");
-        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
-    }
-
-    /**
-     * Disable LE Audio Broadcast mode.
-     *
-     * @hide
-     */
-    public int disableBroadcastMode() {
-        if (DBG) log("disableBroadcastMode");
-        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
-    }
-
-    /**
-     * Get the current LE Audio broadcast state
-     *
-     * @hide
-     */
-    @LeAudioBroadcastState
-    public int getBroadcastState() {
-        if (DBG) log("getBroadcastState");
-        return LE_AUDIO_BROADCAST_STATE_DISABLED;
-    }
-
-    /**
-     * Enable LE Audio broadcast encryption
-     *
-     * @param keyLength if useExisting is true, this specifies the length of the key that should
-     *                  be generated
-     * @param useExisting true, if an existing key should be used
-     *                    false, if a new key should be generated
-     *
-     * @hide
-     */
-    @LeAudioEncryptionKeyLength
-    public int enableEncryption(boolean useExisting, int keyLength) {
-        if (DBG) log("enableEncryption useExisting=" + useExisting + " keyLength=" + keyLength);
-        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED;
-    }
-
-    /**
-     * Disable LE Audio broadcast encryption
-     *
-     * @param removeExisting true, if the existing key should be removed
-     *                       false, otherwise
-     *
-     * @hide
-     */
-    public int disableEncryption(boolean removeExisting) {
-        if (DBG) log("disableEncryption removeExisting=" + removeExisting);
-        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED;
-    }
-
-    /**
-     * Enable or disable LE Audio broadcast encryption
-     *
-     * @param key use the provided key if non-null, generate a new key if null
-     * @param keyLength 0 if encryption is disabled, 4 bytes (low security),
-     *                  16 bytes (high security)
-     *
-     * @hide
-     */
-    @LeAudioEncryptionKeyLength
-    public int setEncryptionKey(byte[] key, int keyLength) {
-        if (DBG) log("setEncryptionKey key=" + key + " keyLength=" + keyLength);
-        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED;
-    }
-
-
-    /**
-     * Get the encryption key that was set before
-     *
-     * @return encryption key as a byte array or null if no encryption key was set
-     *
-     * @hide
-     */
-    public byte[] getEncryptionKey() {
-        if (DBG) log("getEncryptionKey");
-        return null;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java b/core/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
deleted file mode 100644
index b866cce..0000000
--- a/core/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.bluetooth.le.ScanResult;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * This class provides a set of callbacks that are invoked when scanning for Broadcast Sources is
- * offloaded to a Broadcast Assistant.
- *
- * <p>An LE Audio Broadcast Assistant can help a Broadcast Sink to scan for available Broadcast
- * Sources. The Broadcast Sink achieves this by offloading the scan to a Broadcast Assistant. This
- * is facilitated by the Broadcast Audio Scan Service (BASS). A BASS server is a GATT server that is
- * part of the Scan Delegator on a Broadcast Sink. A BASS client instead runs on the Broadcast
- * Assistant.
- *
- * <p>Once a GATT connection is established between the BASS client and the BASS server, the
- * Broadcast Sink can offload the scans to the Broadcast Assistant. Upon finding new Broadcast
- * Sources, the Broadcast Assistant then notifies the Broadcast Sink about these over the
- * established GATT connection. The Scan Delegator on the Broadcast Sink can also notify the
- * Assistant about changes such as addition and removal of Broadcast Sources.
- *
- * @hide
- */
-public abstract class BluetoothLeBroadcastAssistantCallback {
-
-    /**
-     * Broadcast Audio Scan Service (BASS) codes returned by a BASS Server
-     *
-     * @hide
-     */
-    @IntDef(
-            prefix = "BASS_STATUS_",
-            value = {
-                BASS_STATUS_SUCCESS,
-                BASS_STATUS_FAILURE,
-                BASS_STATUS_INVALID_GATT_HANDLE,
-                BASS_STATUS_TXN_TIMEOUT,
-                BASS_STATUS_INVALID_SOURCE_ID,
-                BASS_STATUS_COLOCATED_SRC_UNAVAILABLE,
-                BASS_STATUS_INVALID_SOURCE_SELECTED,
-                BASS_STATUS_SOURCE_UNAVAILABLE,
-                BASS_STATUS_DUPLICATE_ADDITION,
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface BassStatus {}
-
-    public static final int BASS_STATUS_SUCCESS = 0x00;
-    public static final int BASS_STATUS_FAILURE = 0x01;
-    public static final int BASS_STATUS_INVALID_GATT_HANDLE = 0x02;
-    public static final int BASS_STATUS_TXN_TIMEOUT = 0x03;
-
-    public static final int BASS_STATUS_INVALID_SOURCE_ID = 0x04;
-    public static final int BASS_STATUS_COLOCATED_SRC_UNAVAILABLE = 0x05;
-    public static final int BASS_STATUS_INVALID_SOURCE_SELECTED = 0x06;
-    public static final int BASS_STATUS_SOURCE_UNAVAILABLE = 0x07;
-    public static final int BASS_STATUS_DUPLICATE_ADDITION = 0x08;
-    public static final int BASS_STATUS_NO_EMPTY_SLOT = 0x09;
-    public static final int BASS_STATUS_INVALID_GROUP_OP = 0x10;
-
-    /**
-     * Callback invoked when a new LE Audio Broadcast Source is found.
-     *
-     * @param result {@link ScanResult} scan result representing a Broadcast Source
-     */
-    public void onBluetoothLeBroadcastSourceFound(@NonNull ScanResult result) {}
-
-    /**
-     * Callback invoked when the Broadcast Assistant synchronizes with Periodic Advertisements (PAs)
-     * of an LE Audio Broadcast Source.
-     *
-     * @param source the selected Broadcast Source
-     */
-    public void onBluetoothLeBroadcastSourceSelected(
-            @NonNull BluetoothLeBroadcastSourceInfo source, @BassStatus int status) {}
-
-    /**
-     * Callback invoked when the Broadcast Assistant loses synchronization with an LE Audio
-     * Broadcast Source.
-     *
-     * @param source the Broadcast Source with which synchronization was lost
-     */
-    public void onBluetoothLeBroadcastSourceLost(
-            @NonNull BluetoothLeBroadcastSourceInfo source, @BassStatus int status) {}
-
-    /**
-     * Callback invoked when a new LE Audio Broadcast Source has been successfully added to the Scan
-     * Delegator (within a Broadcast Sink, for example).
-     *
-     * @param sink Scan Delegator device on which a new Broadcast Source has been added
-     * @param source the added Broadcast Source
-     */
-    public void onBluetoothLeBroadcastSourceAdded(
-            @NonNull BluetoothDevice sink,
-            @NonNull BluetoothLeBroadcastSourceInfo source,
-            @BassStatus int status) {}
-
-    /**
-     * Callback invoked when an existing LE Audio Broadcast Source within a remote Scan Delegator
-     * has been updated.
-     *
-     * @param sink Scan Delegator device on which a Broadcast Source has been updated
-     * @param source the updated Broadcast Source
-     */
-    public void onBluetoothLeBroadcastSourceUpdated(
-            @NonNull BluetoothDevice sink,
-            @NonNull BluetoothLeBroadcastSourceInfo source,
-            @BassStatus int status) {}
-
-    /**
-     * Callback invoked when an LE Audio Broadcast Source has been successfully removed from the
-     * Scan Delegator (within a Broadcast Sink, for example).
-     *
-     * @param sink Scan Delegator device from which a Broadcast Source has been removed
-     * @param source the removed Broadcast Source
-     */
-    public void onBluetoothLeBroadcastSourceRemoved(
-            @NonNull BluetoothDevice sink,
-            @NonNull BluetoothLeBroadcastSourceInfo source,
-            @BassStatus int status) {}
-}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java b/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java
deleted file mode 100644
index cb47280..0000000
--- a/core/java/android/bluetooth/BluetoothLeBroadcastSourceInfo.java
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class represents an LE Audio Broadcast Source and the associated information that is needed
- * by Broadcast Audio Scan Service (BASS) residing on a Scan Delegator.
- *
- * <p>For example, the Scan Delegator on an LE Audio Broadcast Sink can use the information
- * contained within an instance of this class to synchronize with an LE Audio Broadcast Source in
- * order to listen to a Broadcast Audio Stream.
- *
- * <p>BroadcastAssistant has a BASS client which facilitates scanning and discovery of Broadcast
- * Sources on behalf of say a Broadcast Sink. Upon successful discovery of one or more Broadcast
- * sources, this information needs to be communicated to the BASS Server residing within the Scan
- * Delegator on a Broadcast Sink. This is achieved using the Periodic Advertising Synchronization
- * Transfer (PAST) procedure. This procedure uses information contained within an instance of this
- * class.
- *
- * @hide
- */
-public final class BluetoothLeBroadcastSourceInfo implements Parcelable {
-    private static final String TAG = "BluetoothLeBroadcastSourceInfo";
-    private static final boolean DBG = true;
-
-    /**
-     * Constants representing Broadcast Source address types
-     *
-     * @hide
-     */
-    @IntDef(
-            prefix = "LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_",
-            value = {
-                LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_PUBLIC,
-                LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_RANDOM,
-                LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LeAudioBroadcastSourceAddressType {}
-
-    /**
-     * Represents a public address used by an LE Audio Broadcast Source
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_PUBLIC = 0;
-
-    /**
-     * Represents a random address used by an LE Audio Broadcast Source
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_RANDOM = 1;
-
-    /**
-     * Represents an invalid address used by an LE Audio Broadcast Seurce
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID = 0xFFFF;
-
-    /**
-     * Periodic Advertising Synchronization state
-     *
-     * <p>Periodic Advertising (PA) enables the LE Audio Broadcast Assistant to discover broadcast
-     * audio streams as well as the audio stream configuration on behalf of an LE Audio Broadcast
-     * Sink. This information can then be transferred to the LE Audio Broadcast Sink using the
-     * Periodic Advertising Synchronizaton Transfer (PAST) procedure.
-     *
-     * @hide
-     */
-    @IntDef(
-            prefix = "LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_",
-            value = {
-                LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IDLE,
-                LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNCINFO_REQ,
-                LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IN_SYNC,
-                LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNC_FAIL,
-                LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_NO_PAST
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LeAudioBroadcastSinkPaSyncState {}
-
-    /**
-     * Indicates that the Broadcast Sink is not synchronized with the Periodic Advertisements (PA)
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IDLE = 0;
-
-    /**
-     * Indicates that the Broadcast Sink requested the Broadcast Assistant to synchronize with the
-     * Periodic Advertisements (PA).
-     *
-     * <p>This is also known as scan delegation or scan offloading.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNCINFO_REQ = 1;
-
-    /**
-     * Indicates that the Broadcast Sink is synchronized with the Periodic Advertisements (PA).
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_IN_SYNC = 2;
-
-    /**
-     * Indicates that the Broadcast Sink was unable to synchronize with the Periodic Advertisements
-     * (PA).
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_SYNC_FAIL = 3;
-
-    /**
-     * Indicates that the Broadcast Sink should be synchronized with the Periodic Advertisements
-     * (PA) using the Periodic Advertisements Synchronization Transfert (PAST) procedure.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_NO_PAST = 4;
-
-    /**
-     * Indicates that the Broadcast Sink synchornization state is invalid.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID = 0xFFFF;
-
-    /** @hide */
-    @IntDef(
-            prefix = "LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_",
-            value = {
-                LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED,
-                LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_SYNCHRONIZED
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LeAudioBroadcastSinkAudioSyncState {}
-
-    /**
-     * Indicates that the Broadcast Sink is not synchronized with a Broadcast Audio Stream.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED = 0;
-
-    /**
-     * Indicates that the Broadcast Sink is synchronized with a Broadcast Audio Stream.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_SYNCHRONIZED = 1;
-
-    /**
-     * Indicates that the Broadcast Sink audio synchronization state is invalid.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID = 0xFFFF;
-
-    /** @hide */
-    @IntDef(
-            prefix = "LE_AUDIO_BROADCAST_SINK_ENC_STATE_",
-            value = {
-                LE_AUDIO_BROADCAST_SINK_ENC_STATE_NOT_ENCRYPTED,
-                LE_AUDIO_BROADCAST_SINK_ENC_STATE_CODE_REQUIRED,
-                LE_AUDIO_BROADCAST_SINK_ENC_STATE_DECRYPTING,
-                LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LeAudioBroadcastSinkEncryptionState {}
-
-    /**
-     * Indicates that the Broadcast Sink is synchronized with an unencrypted audio stream.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_NOT_ENCRYPTED = 0;
-
-    /**
-     * Indicates that the Broadcast Sink needs a Broadcast Code to synchronize with the audio
-     * stream.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_CODE_REQUIRED = 1;
-
-    /**
-     * Indicates that the Broadcast Sink is synchronized with an encrypted audio stream.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_DECRYPTING = 2;
-
-    /**
-     * Indicates that the Broadcast Sink is unable to decrypt an audio stream due to an incorrect
-     * Broadcast Code
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE = 3;
-
-    /**
-     * Indicates that the Broadcast Sink encryption state is invalid.
-     *
-     * @hide
-     */
-    public static final int LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID = 0xFF;
-
-    /**
-     * Represents an invalid LE Audio Broadcast Source ID
-     *
-     * @hide
-     */
-    public static final byte LE_AUDIO_BROADCAST_SINK_INVALID_SOURCE_ID = (byte) 0x00;
-
-    /**
-     * Represents an invalid Broadcast ID of a Broadcast Source
-     *
-     * @hide
-     */
-    public static final int INVALID_BROADCAST_ID = 0xFFFFFF;
-
-    private byte mSourceId;
-    private @LeAudioBroadcastSourceAddressType int mSourceAddressType;
-    private BluetoothDevice mSourceDevice;
-    private byte mSourceAdvSid;
-    private int mBroadcastId;
-    private @LeAudioBroadcastSinkPaSyncState int mPaSyncState;
-    private @LeAudioBroadcastSinkEncryptionState int mEncryptionStatus;
-    private @LeAudioBroadcastSinkAudioSyncState int mAudioSyncState;
-    private byte[] mBadBroadcastCode;
-    private byte mNumSubGroups;
-    private Map<Integer, Integer> mSubgroupBisSyncState = new HashMap<Integer, Integer>();
-    private Map<Integer, byte[]> mSubgroupMetadata = new HashMap<Integer, byte[]>();
-
-    private String mBroadcastCode;
-    private static final int BIS_NO_PREF = 0xFFFFFFFF;
-    private static final int BROADCAST_CODE_SIZE = 16;
-
-    /**
-     * Constructor to create an Empty object of {@link BluetoothLeBroadcastSourceInfo } with the
-     * given Source Id.
-     *
-     * <p>This is mainly used to represent the Empty Broadcast Source entries
-     *
-     * @param sourceId Source Id for this Broadcast Source info object
-     * @hide
-     */
-    public BluetoothLeBroadcastSourceInfo(byte sourceId) {
-        mSourceId = sourceId;
-        mSourceAddressType = LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID;
-        mSourceDevice = null;
-        mSourceAdvSid = (byte) 0x00;
-        mBroadcastId = INVALID_BROADCAST_ID;
-        mPaSyncState = LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID;
-        mAudioSyncState = LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID;
-        mEncryptionStatus = LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID;
-        mBadBroadcastCode = null;
-        mNumSubGroups = 0;
-        mBroadcastCode = null;
-    }
-
-    /*package*/ BluetoothLeBroadcastSourceInfo(
-            byte sourceId,
-            @LeAudioBroadcastSourceAddressType int addressType,
-            @NonNull BluetoothDevice device,
-            byte advSid,
-            int broadcastId,
-            @LeAudioBroadcastSinkPaSyncState int paSyncstate,
-            @LeAudioBroadcastSinkEncryptionState int encryptionStatus,
-            @LeAudioBroadcastSinkAudioSyncState int audioSyncstate,
-            @Nullable byte[] badCode,
-            byte numSubGroups,
-            @NonNull Map<Integer, Integer> bisSyncState,
-            @Nullable Map<Integer, byte[]> subgroupMetadata,
-            @NonNull String broadcastCode) {
-        mSourceId = sourceId;
-        mSourceAddressType = addressType;
-        mSourceDevice = device;
-        mSourceAdvSid = advSid;
-        mBroadcastId = broadcastId;
-        mPaSyncState = paSyncstate;
-        mEncryptionStatus = encryptionStatus;
-        mAudioSyncState = audioSyncstate;
-
-        if (badCode != null && badCode.length != 0) {
-            mBadBroadcastCode = new byte[badCode.length];
-            System.arraycopy(badCode, 0, mBadBroadcastCode, 0, badCode.length);
-        }
-        mNumSubGroups = numSubGroups;
-        mSubgroupBisSyncState = new HashMap<Integer, Integer>(bisSyncState);
-        mSubgroupMetadata = new HashMap<Integer, byte[]>(subgroupMetadata);
-        mBroadcastCode = broadcastCode;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o instanceof BluetoothLeBroadcastSourceInfo) {
-            BluetoothLeBroadcastSourceInfo other = (BluetoothLeBroadcastSourceInfo) o;
-            return (other.mSourceId == mSourceId
-                    && other.mSourceAddressType == mSourceAddressType
-                    && other.mSourceDevice == mSourceDevice
-                    && other.mSourceAdvSid == mSourceAdvSid
-                    && other.mBroadcastId == mBroadcastId
-                    && other.mPaSyncState == mPaSyncState
-                    && other.mEncryptionStatus == mEncryptionStatus
-                    && other.mAudioSyncState == mAudioSyncState
-                    && Arrays.equals(other.mBadBroadcastCode, mBadBroadcastCode)
-                    && other.mNumSubGroups == mNumSubGroups
-                    && mSubgroupBisSyncState.equals(other.mSubgroupBisSyncState)
-                    && mSubgroupMetadata.equals(other.mSubgroupMetadata)
-                    && other.mBroadcastCode == mBroadcastCode);
-        }
-        return false;
-    }
-
-    /**
-     * Checks if an instance of {@link BluetoothLeBroadcastSourceInfo} is empty.
-     *
-     * @hide
-     */
-    public boolean isEmpty() {
-        boolean ret = false;
-        if (mSourceAddressType == LE_AUDIO_BROADCAST_SOURCE_ADDRESS_TYPE_INVALID
-                && mSourceDevice == null
-                && mSourceAdvSid == (byte) 0
-                && mPaSyncState == LE_AUDIO_BROADCAST_SINK_PA_SYNC_STATE_INVALID
-                && mEncryptionStatus == LE_AUDIO_BROADCAST_SINK_ENC_STATE_INVALID
-                && mAudioSyncState == LE_AUDIO_BROADCAST_SINK_AUDIO_SYNC_STATE_INVALID
-                && mBadBroadcastCode == null
-                && mNumSubGroups == 0
-                && mSubgroupBisSyncState.size() == 0
-                && mSubgroupMetadata.size() == 0
-                && mBroadcastCode == null) {
-            ret = true;
-        }
-        return ret;
-    }
-
-    /**
-     * Compares an instance of {@link BluetoothLeBroadcastSourceInfo} with the provided instance.
-     *
-     * @hide
-     */
-    public boolean matches(BluetoothLeBroadcastSourceInfo srcInfo) {
-        boolean ret = false;
-        if (srcInfo == null) {
-            ret = false;
-        } else {
-            if (mSourceDevice == null) {
-                if (mSourceAdvSid == srcInfo.getAdvertisingSid()
-                        && mSourceAddressType == srcInfo.getAdvAddressType()) {
-                    ret = true;
-                }
-            } else {
-                if (mSourceDevice.equals(srcInfo.getSourceDevice())
-                        && mSourceAdvSid == srcInfo.getAdvertisingSid()
-                        && mSourceAddressType == srcInfo.getAdvAddressType()
-                        && mBroadcastId == srcInfo.getBroadcastId()) {
-                    ret = true;
-                }
-            }
-        }
-        return ret;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(
-                mSourceId,
-                mSourceAddressType,
-                mSourceDevice,
-                mSourceAdvSid,
-                mBroadcastId,
-                mPaSyncState,
-                mEncryptionStatus,
-                mAudioSyncState,
-                mBadBroadcastCode,
-                mNumSubGroups,
-                mSubgroupBisSyncState,
-                mSubgroupMetadata,
-                mBroadcastCode);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public String toString() {
-        return "{BluetoothLeBroadcastSourceInfo : mSourceId"
-                + mSourceId
-                + " addressType: "
-                + mSourceAddressType
-                + " sourceDevice: "
-                + mSourceDevice
-                + " mSourceAdvSid:"
-                + mSourceAdvSid
-                + " mBroadcastId:"
-                + mBroadcastId
-                + " mPaSyncState:"
-                + mPaSyncState
-                + " mEncryptionStatus:"
-                + mEncryptionStatus
-                + " mAudioSyncState:"
-                + mAudioSyncState
-                + " mBadBroadcastCode:"
-                + mBadBroadcastCode
-                + " mNumSubGroups:"
-                + mNumSubGroups
-                + " mSubgroupBisSyncState:"
-                + mSubgroupBisSyncState
-                + " mSubgroupMetadata:"
-                + mSubgroupMetadata
-                + " mBroadcastCode:"
-                + mBroadcastCode
-                + "}";
-    }
-
-    /**
-     * Get the Source Id
-     *
-     * @return byte representing the Source Id, {@link
-     *     #LE_AUDIO_BROADCAST_ASSISTANT_INVALID_SOURCE_ID} if invalid
-     * @hide
-     */
-    public byte getSourceId() {
-        return mSourceId;
-    }
-
-    /**
-     * Set the Source Id
-     *
-     * @param sourceId source Id
-     * @hide
-     */
-    public void setSourceId(byte sourceId) {
-        mSourceId = sourceId;
-    }
-
-    /**
-     * Set the Broadcast Source device
-     *
-     * @param sourceDevice the Broadcast Source BluetoothDevice
-     * @hide
-     */
-    public void setSourceDevice(@NonNull BluetoothDevice sourceDevice) {
-        mSourceDevice = sourceDevice;
-    }
-
-    /**
-     * Get the Broadcast Source BluetoothDevice
-     *
-     * @return Broadcast Source BluetoothDevice
-     * @hide
-     */
-    public @NonNull BluetoothDevice getSourceDevice() {
-        return mSourceDevice;
-    }
-
-    /**
-     * Set the address type of the Broadcast Source advertisements
-     *
-     * @hide
-     */
-    public void setAdvAddressType(@LeAudioBroadcastSourceAddressType int addressType) {
-        mSourceAddressType = addressType;
-    }
-
-    /**
-     * Get the address type used by advertisements from the Broadcast Source.
-     * BluetoothLeBroadcastSourceInfo Object
-     *
-     * @hide
-     */
-    @LeAudioBroadcastSourceAddressType
-    public int getAdvAddressType() {
-        return mSourceAddressType;
-    }
-
-    /**
-     * Set the advertising SID of the Broadcast Source advertisement.
-     *
-     * @param advSid advertising SID of the Broadcast Source
-     * @hide
-     */
-    public void setAdvertisingSid(byte advSid) {
-        mSourceAdvSid = advSid;
-    }
-
-    /**
-     * Get the advertising SID of the Broadcast Source advertisement.
-     *
-     * @return advertising SID of the Broadcast Source
-     * @hide
-     */
-    public byte getAdvertisingSid() {
-        return mSourceAdvSid;
-    }
-
-    /**
-     * Get the Broadcast ID of the Broadcast Source.
-     *
-     * @return broadcast ID
-     * @hide
-     */
-    public int getBroadcastId() {
-        return mBroadcastId;
-    }
-
-    /**
-     * Set the Periodic Advertising (PA) Sync State.
-     *
-     * @hide
-     */
-    /*package*/ void setPaSyncState(@LeAudioBroadcastSinkPaSyncState int paSyncState) {
-        mPaSyncState = paSyncState;
-    }
-
-    /**
-     * Get the Periodic Advertising (PA) Sync State
-     *
-     * @hide
-     */
-    public @LeAudioBroadcastSinkPaSyncState int getMetadataSyncState() {
-        return mPaSyncState;
-    }
-
-    /**
-     * Set the audio sync state
-     *
-     * @hide
-     */
-    /*package*/ void setAudioSyncState(@LeAudioBroadcastSinkAudioSyncState int audioSyncState) {
-        mAudioSyncState = audioSyncState;
-    }
-
-    /**
-     * Get the audio sync state
-     *
-     * @hide
-     */
-    public @LeAudioBroadcastSinkAudioSyncState int getAudioSyncState() {
-        return mAudioSyncState;
-    }
-
-    /**
-     * Set the encryption status
-     *
-     * @hide
-     */
-    /*package*/ void setEncryptionStatus(
-            @LeAudioBroadcastSinkEncryptionState int encryptionStatus) {
-        mEncryptionStatus = encryptionStatus;
-    }
-
-    /**
-     * Get the encryption status
-     *
-     * @hide
-     */
-    public @LeAudioBroadcastSinkEncryptionState int getEncryptionStatus() {
-        return mEncryptionStatus;
-    }
-
-    /**
-     * Get the incorrect broadcast code that the Scan delegator used to decrypt the Broadcast Audio
-     * Stream and failed.
-     *
-     * <p>This code is valid only if {@link #getEncryptionStatus} returns {@link
-     * #LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE}
-     *
-     * @return byte array containing bad broadcast value, null if the current encryption status is
-     *     not {@link #LE_AUDIO_BROADCAST_SINK_ENC_STATE_BAD_CODE}
-     * @hide
-     */
-    public @Nullable byte[] getBadBroadcastCode() {
-        return mBadBroadcastCode;
-    }
-
-    /**
-     * Get the number of subgroups.
-     *
-     * @return number of subgroups
-     * @hide
-     */
-    public byte getNumberOfSubGroups() {
-        return mNumSubGroups;
-    }
-
-    public @NonNull Map<Integer, Integer> getSubgroupBisSyncState() {
-        return mSubgroupBisSyncState;
-    }
-
-    public void setSubgroupBisSyncState(@NonNull Map<Integer, Integer> bisSyncState) {
-        mSubgroupBisSyncState = new HashMap<Integer, Integer>(bisSyncState);
-    }
-
-    /*package*/ void setBroadcastCode(@NonNull String broadcastCode) {
-        mBroadcastCode = broadcastCode;
-    }
-
-    /**
-     * Get the broadcast code
-     *
-     * @return
-     * @hide
-     */
-    public @NonNull String getBroadcastCode() {
-        return mBroadcastCode;
-    }
-
-    /**
-     * Set the broadcast ID
-     *
-     * @param broadcastId broadcast ID of the Broadcast Source
-     * @hide
-     */
-    public void setBroadcastId(int broadcastId) {
-        mBroadcastId = broadcastId;
-    }
-
-    private void writeSubgroupBisSyncStateToParcel(
-            @NonNull Parcel dest, @NonNull Map<Integer, Integer> subgroupBisSyncState) {
-        dest.writeInt(subgroupBisSyncState.size());
-        for (Map.Entry<Integer, Integer> entry : subgroupBisSyncState.entrySet()) {
-            dest.writeInt(entry.getKey());
-            dest.writeInt(entry.getValue());
-        }
-    }
-
-    private static void readSubgroupBisSyncStateFromParcel(
-            @NonNull Parcel in, @NonNull Map<Integer, Integer> subgroupBisSyncState) {
-        int size = in.readInt();
-
-        for (int i = 0; i < size; i++) {
-            Integer key = in.readInt();
-            Integer value = in.readInt();
-            subgroupBisSyncState.put(key, value);
-        }
-    }
-
-    private void writeSubgroupMetadataToParcel(
-            @NonNull Parcel dest, @Nullable Map<Integer, byte[]> subgroupMetadata) {
-        if (subgroupMetadata == null) {
-            dest.writeInt(0);
-            return;
-        }
-
-        dest.writeInt(subgroupMetadata.size());
-        for (Map.Entry<Integer, byte[]> entry : subgroupMetadata.entrySet()) {
-            dest.writeInt(entry.getKey());
-            byte[] metadata = entry.getValue();
-            if (metadata != null) {
-                dest.writeInt(metadata.length);
-                dest.writeByteArray(metadata);
-            }
-        }
-    }
-
-    private static void readSubgroupMetadataFromParcel(
-            @NonNull Parcel in, @NonNull Map<Integer, byte[]> subgroupMetadata) {
-        int size = in.readInt();
-
-        for (int i = 0; i < size; i++) {
-            Integer key = in.readInt();
-            Integer metaDataLen = in.readInt();
-            byte[] metadata = null;
-            if (metaDataLen != 0) {
-                metadata = new byte[metaDataLen];
-                in.readByteArray(metadata);
-            }
-            subgroupMetadata.put(key, metadata);
-        }
-    }
-
-    public static final @NonNull Parcelable.Creator<BluetoothLeBroadcastSourceInfo> CREATOR =
-            new Parcelable.Creator<BluetoothLeBroadcastSourceInfo>() {
-                public @NonNull BluetoothLeBroadcastSourceInfo createFromParcel(
-                        @NonNull Parcel in) {
-                    final byte sourceId = in.readByte();
-                    final int sourceAddressType = in.readInt();
-                    final BluetoothDevice sourceDevice =
-                            in.readTypedObject(BluetoothDevice.CREATOR);
-                    final byte sourceAdvSid = in.readByte();
-                    final int broadcastId = in.readInt();
-                    final int paSyncState = in.readInt();
-                    final int audioSyncState = in.readInt();
-                    final int encryptionStatus = in.readInt();
-                    final int badBroadcastLen = in.readInt();
-                    byte[] badBroadcastCode = null;
-
-                    if (badBroadcastLen > 0) {
-                        badBroadcastCode = new byte[badBroadcastLen];
-                        in.readByteArray(badBroadcastCode);
-                    }
-                    final byte numSubGroups = in.readByte();
-                    final String broadcastCode = in.readString();
-                    Map<Integer, Integer> subgroupBisSyncState = new HashMap<Integer, Integer>();
-                    readSubgroupBisSyncStateFromParcel(in, subgroupBisSyncState);
-                    Map<Integer, byte[]> subgroupMetadata = new HashMap<Integer, byte[]>();
-                    readSubgroupMetadataFromParcel(in, subgroupMetadata);
-
-                    BluetoothLeBroadcastSourceInfo srcInfo =
-                            new BluetoothLeBroadcastSourceInfo(
-                                    sourceId,
-                                    sourceAddressType,
-                                    sourceDevice,
-                                    sourceAdvSid,
-                                    broadcastId,
-                                    paSyncState,
-                                    encryptionStatus,
-                                    audioSyncState,
-                                    badBroadcastCode,
-                                    numSubGroups,
-                                    subgroupBisSyncState,
-                                    subgroupMetadata,
-                                    broadcastCode);
-                    return srcInfo;
-                }
-
-                public @NonNull BluetoothLeBroadcastSourceInfo[] newArray(int size) {
-                    return new BluetoothLeBroadcastSourceInfo[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeByte(mSourceId);
-        out.writeInt(mSourceAddressType);
-        out.writeTypedObject(mSourceDevice, 0);
-        out.writeByte(mSourceAdvSid);
-        out.writeInt(mBroadcastId);
-        out.writeInt(mPaSyncState);
-        out.writeInt(mAudioSyncState);
-        out.writeInt(mEncryptionStatus);
-
-        if (mBadBroadcastCode != null) {
-            out.writeInt(mBadBroadcastCode.length);
-            out.writeByteArray(mBadBroadcastCode);
-        } else {
-            // zero indicates that there is no "bad broadcast code"
-            out.writeInt(0);
-        }
-        out.writeByte(mNumSubGroups);
-        out.writeString(mBroadcastCode);
-        writeSubgroupBisSyncStateToParcel(out, mSubgroupBisSyncState);
-        writeSubgroupMetadataToParcel(out, mSubgroupMetadata);
-    }
-
-    private static void log(@NonNull String msg) {
-        if (DBG) {
-            Log.d(TAG, msg);
-        }
-    }
-}
-;
diff --git a/core/java/android/bluetooth/BluetoothLeCall.java b/core/java/android/bluetooth/BluetoothLeCall.java
deleted file mode 100644
index fb7789d..0000000
--- a/core/java/android/bluetooth/BluetoothLeCall.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * 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.annotation.IntDef;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.ParcelUuid;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * Representation of Call
- *
- * @hide
- */
-public final class BluetoothLeCall implements Parcelable {
-
-    /** @hide */
-    @IntDef(prefix = "STATE_", value = {
-            STATE_INCOMING,
-            STATE_DIALING,
-            STATE_ALERTING,
-            STATE_ACTIVE,
-            STATE_LOCALLY_HELD,
-            STATE_REMOTELY_HELD,
-            STATE_LOCALLY_AND_REMOTELY_HELD
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface State {
-    }
-
-    /**
-     * A remote party is calling (incoming call).
-     *
-     * @hide
-     */
-    public static final int STATE_INCOMING = 0x00;
-
-    /**
-     * The process to call the remote party has started but the remote party is not
-     * being alerted (outgoing call).
-     *
-     * @hide
-     */
-    public static final int STATE_DIALING = 0x01;
-
-    /**
-     * A remote party is being alerted (outgoing call).
-     *
-     * @hide
-     */
-    public static final int STATE_ALERTING = 0x02;
-
-    /**
-     * The call is in an active conversation.
-     *
-     * @hide
-     */
-    public static final int STATE_ACTIVE = 0x03;
-
-    /**
-     * The call is connected but held locally. “Locally Held” implies that either
-     * the server or the client can affect the state.
-     *
-     * @hide
-     */
-    public static final int STATE_LOCALLY_HELD = 0x04;
-
-    /**
-     * The call is connected but held remotely. “Remotely Held” means that the state
-     * is controlled by the remote party of a call.
-     *
-     * @hide
-     */
-    public static final int STATE_REMOTELY_HELD = 0x05;
-
-    /**
-     * The call is connected but held both locally and remotely.
-     *
-     * @hide
-     */
-    public static final int STATE_LOCALLY_AND_REMOTELY_HELD = 0x06;
-
-    /**
-     * Whether the call direction is outgoing.
-     *
-     * @hide
-     */
-    public static final int FLAG_OUTGOING_CALL = 0x00000001;
-
-    /**
-     * Whether the call URI and Friendly Name are withheld by server.
-     *
-     * @hide
-     */
-    public static final int FLAG_WITHHELD_BY_SERVER = 0x00000002;
-
-    /**
-     * Whether the call URI and Friendly Name are withheld by network.
-     *
-     * @hide
-     */
-    public static final int FLAG_WITHHELD_BY_NETWORK = 0x00000004;
-
-    /** Unique UUID that identifies this call */
-    private UUID mUuid;
-
-    /** Remote Caller URI */
-    private String mUri;
-
-    /** Caller friendly name */
-    private String mFriendlyName;
-
-    /** Call state */
-    private @State int mState;
-
-    /** Call flags */
-    private int mCallFlags;
-
-    /** @hide */
-    public BluetoothLeCall(@NonNull BluetoothLeCall that) {
-        mUuid = new UUID(that.getUuid().getMostSignificantBits(),
-                that.getUuid().getLeastSignificantBits());
-        mUri = that.mUri;
-        mFriendlyName = that.mFriendlyName;
-        mState = that.mState;
-        mCallFlags = that.mCallFlags;
-    }
-
-    /** @hide */
-    public BluetoothLeCall(@NonNull UUID uuid, @NonNull String uri, @NonNull String friendlyName,
-            @State int state, int callFlags) {
-        mUuid = uuid;
-        mUri = uri;
-        mFriendlyName = friendlyName;
-        mState = state;
-        mCallFlags = callFlags;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o)
-            return true;
-        if (o == null || getClass() != o.getClass())
-            return false;
-        BluetoothLeCall that = (BluetoothLeCall) o;
-        return mUuid.equals(that.mUuid) && mUri.equals(that.mUri)
-                && mFriendlyName.equals(that.mFriendlyName) && mState == that.mState
-                && mCallFlags == that.mCallFlags;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mUuid, mUri, mFriendlyName, mState, mCallFlags);
-    }
-
-    /**
-     * Returns a string representation of this BluetoothLeCall.
-     *
-     * <p>
-     * Currently this is the UUID.
-     *
-     * @return string representation of this BluetoothLeCall
-     */
-    @Override
-    public String toString() {
-        return mUuid.toString();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeParcelable(new ParcelUuid(mUuid), 0);
-        out.writeString(mUri);
-        out.writeString(mFriendlyName);
-        out.writeInt(mState);
-        out.writeInt(mCallFlags);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothLeCall> CREATOR =
-    						    new Parcelable.Creator<BluetoothLeCall>() {
-        public BluetoothLeCall createFromParcel(Parcel in) {
-            return new BluetoothLeCall(in);
-        }
-
-        public BluetoothLeCall[] newArray(int size) {
-            return new BluetoothLeCall[size];
-        }
-    };
-
-    private BluetoothLeCall(Parcel in) {
-        mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
-        mUri = in.readString();
-        mFriendlyName = in.readString();
-        mState = in.readInt();
-        mCallFlags = in.readInt();
-    }
-
-    /**
-     * Returns an UUID of this BluetoothLeCall.
-     *
-     * <p>
-     * An UUID is unique identifier of a BluetoothLeCall.
-     *
-     * @return UUID of this BluetoothLeCall
-     * @hide
-     */
-    public @NonNull UUID getUuid() {
-        return mUuid;
-    }
-
-    /**
-     * Returns a URI of the remote party of this BluetoothLeCall.
-     *
-     * @return string representation of this BluetoothLeCall
-     * @hide
-     */
-    public @NonNull String getUri() {
-        return mUri;
-    }
-
-    /**
-     * Returns a friendly name of the call.
-     *
-     * @return friendly name representation of this BluetoothLeCall
-     * @hide
-     */
-    public @NonNull String getFriendlyName() {
-        return mFriendlyName;
-    }
-
-    /**
-     * Returns the call state.
-     *
-     * @return the state of this BluetoothLeCall
-     * @hide
-     */
-    public @State int getState() {
-        return mState;
-    }
-
-    /**
-     * Returns the call flags.
-     *
-     * @return call flags
-     * @hide
-     */
-    public int getCallFlags() {
-        return mCallFlags;
-    }
-
-    /**
-     * Whether the call direction is incoming.
-     *
-     * @return true if incoming call, false otherwise
-     * @hide
-     */
-    public boolean isIncomingCall() {
-        return (mCallFlags & FLAG_OUTGOING_CALL) == 0;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothLeCallControl.java b/core/java/android/bluetooth/BluetoothLeCallControl.java
deleted file mode 100644
index fb080c9..0000000
--- a/core/java/android/bluetooth/BluetoothLeCallControl.java
+++ /dev/null
@@ -1,899 +0,0 @@
-/*
- * Copyright 2019 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.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-import android.annotation.SuppressLint;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-
-/**
- * This class provides the APIs to control the Call Control profile.
- *
- * <p>
- * This class provides Bluetooth Telephone Bearer Service functionality,
- * allowing applications to expose a GATT Service based interface to control the
- * state of the calls by remote devices such as LE audio devices.
- *
- * <p>
- * BluetoothLeCallControl is a proxy object for controlling the Bluetooth Telephone Bearer
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
- * BluetoothLeCallControl proxy object.
- *
- * @hide
- */
-public final class BluetoothLeCallControl implements BluetoothProfile {
-    private static final String TAG = "BluetoothLeCallControl";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /** @hide */
-    @IntDef(prefix = "RESULT_", value = {
-            RESULT_SUCCESS,
-            RESULT_ERROR_UNKNOWN_CALL_ID,
-            RESULT_ERROR_INVALID_URI,
-            RESULT_ERROR_APPLICATION
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Result {
-    }
-
-    /**
-     * Opcode write was successful.
-     *
-     * @hide
-     */
-    public static final int RESULT_SUCCESS = 0;
-
-    /**
-     * Unknown call Id has been used in the operation.
-     *
-     * @hide
-     */
-    public static final int RESULT_ERROR_UNKNOWN_CALL_ID = 1;
-
-    /**
-     * The URI provided in {@link Callback#onPlaceCallRequest} is invalid.
-     *
-     * @hide
-     */
-    public static final int RESULT_ERROR_INVALID_URI = 2;
-
-    /**
-     * Application internal error.
-     *
-     * @hide
-     */
-    public static final int RESULT_ERROR_APPLICATION = 3;
-
-    /** @hide */
-    @IntDef(prefix = "TERMINATION_REASON_", value = {
-            TERMINATION_REASON_INVALID_URI,
-            TERMINATION_REASON_FAIL,
-            TERMINATION_REASON_REMOTE_HANGUP,
-            TERMINATION_REASON_SERVER_HANGUP,
-            TERMINATION_REASON_LINE_BUSY,
-            TERMINATION_REASON_NETWORK_CONGESTION,
-            TERMINATION_REASON_CLIENT_HANGUP,
-            TERMINATION_REASON_NO_SERVICE,
-            TERMINATION_REASON_NO_ANSWER
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface TerminationReason {
-    }
-
-    /**
-     * Remote Caller ID value used to place a call was formed improperly.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_INVALID_URI = 0x00;
-
-    /**
-     * Call fail.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_FAIL = 0x01;
-
-    /**
-     * Remote party ended call.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_REMOTE_HANGUP = 0x02;
-
-    /**
-     * Call ended from the server.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_SERVER_HANGUP = 0x03;
-
-    /**
-     * Line busy.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_LINE_BUSY = 0x04;
-
-    /**
-     * Network congestion.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_NETWORK_CONGESTION = 0x05;
-
-    /**
-     * Client terminated.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_CLIENT_HANGUP = 0x06;
-
-    /**
-     * No service.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_NO_SERVICE = 0x07;
-
-    /**
-     * No answer.
-     *
-     * @hide
-     */
-    public static final int TERMINATION_REASON_NO_ANSWER = 0x08;
-
-    /*
-     * Flag indicating support for hold/unhold call feature.
-     *
-     * @hide
-     */
-    public static final int CAPABILITY_HOLD_CALL = 0x00000001;
-
-    /**
-     * Flag indicating support for joining calls feature.
-     *
-     * @hide
-     */
-    public static final int CAPABILITY_JOIN_CALLS = 0x00000002;
-
-    private static final int MESSAGE_TBS_SERVICE_CONNECTED = 102;
-    private static final int MESSAGE_TBS_SERVICE_DISCONNECTED = 103;
-
-    private static final int REG_TIMEOUT = 10000;
-
-    /**
-     * The template class is used to call callback functions on events from the TBS
-     * server. Callback functions are wrapped in this class and registered to the
-     * Android system during app registration.
-     *
-     * @hide
-     */
-    public abstract static class Callback {
-
-        private static final String TAG = "BluetoothLeCallControl.Callback";
-
-        /**
-         * Called when a remote client requested to accept the call.
-         *
-         * <p>
-         * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
-         * request.
-         *
-         * @param requestId The Id of the request
-         * @param callId    The call Id requested to be accepted
-         * @hide
-         */
-        public abstract void onAcceptCall(int requestId, @NonNull UUID callId);
-
-        /**
-         * A remote client has requested to terminate the call.
-         *
-         * <p>
-         * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
-         * request.
-         *
-         * @param requestId The Id of the request
-         * @param callId    The call Id requested to terminate
-         * @hide
-         */
-        public abstract void onTerminateCall(int requestId, @NonNull UUID callId);
-
-        /**
-         * A remote client has requested to hold the call.
-         *
-         * <p>
-         * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
-         * request.
-         *
-         * @param requestId The Id of the request
-         * @param callId    The call Id requested to be put on hold
-         * @hide
-         */
-        public void onHoldCall(int requestId, @NonNull UUID callId) {
-            Log.e(TAG, "onHoldCall: unimplemented, however CAPABILITY_HOLD_CALL is set!");
-        }
-
-        /**
-         * A remote client has requested to unhold the call.
-         *
-         * <p>
-         * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
-         * request.
-         *
-         * @param requestId The Id of the request
-         * @param callId    The call Id requested to unhold
-         * @hide
-         */
-        public void onUnholdCall(int requestId, @NonNull UUID callId) {
-            Log.e(TAG, "onUnholdCall: unimplemented, however CAPABILITY_HOLD_CALL is set!");
-        }
-
-        /**
-         * A remote client has requested to place a call.
-         *
-         * <p>
-         * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
-         * request.
-         *
-         * @param requestId The Id of the request
-         * @param callId    The Id to be assigned for the new call
-         * @param uri       The caller URI requested
-         * @hide
-         */
-        public abstract void onPlaceCall(int requestId, @NonNull UUID callId, @NonNull String uri);
-
-        /**
-         * A remote client has requested to join the calls.
-         *
-         * <p>
-         * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
-         * request.
-         *
-         * @param requestId The Id of the request
-         * @param callIds   The call Id list requested to join
-         * @hide
-         */
-        public void onJoinCalls(int requestId, @NonNull List<UUID> callIds) {
-            Log.e(TAG, "onJoinCalls: unimplemented, however CAPABILITY_JOIN_CALLS is set!");
-        }
-    }
-
-    private class CallbackWrapper extends IBluetoothLeCallControlCallback.Stub {
-
-        private final Executor mExecutor;
-        private final Callback mCallback;
-
-        CallbackWrapper(Executor executor, Callback callback) {
-            mExecutor = executor;
-            mCallback = callback;
-        }
-
-        @Override
-        public void onBearerRegistered(int ccid) {
-            if (mCallback != null) {
-                mCcid = ccid;
-            } else {
-                // registration timeout
-                Log.e(TAG, "onBearerRegistered: mCallback is null");
-            }
-        }
-
-        @Override
-        public void onAcceptCall(int requestId, ParcelUuid uuid) {
-            final long identityToken = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onAcceptCall(requestId, uuid.getUuid()));
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-
-        @Override
-        public void onTerminateCall(int requestId, ParcelUuid uuid) {
-            final long identityToken = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onTerminateCall(requestId, uuid.getUuid()));
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-
-        @Override
-        public void onHoldCall(int requestId, ParcelUuid uuid) {
-            final long identityToken = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onHoldCall(requestId, uuid.getUuid()));
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-
-        @Override
-        public void onUnholdCall(int requestId, ParcelUuid uuid) {
-            final long identityToken = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onUnholdCall(requestId, uuid.getUuid()));
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-
-        @Override
-        public void onPlaceCall(int requestId, ParcelUuid uuid, String uri) {
-            final long identityToken = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onPlaceCall(requestId, uuid.getUuid(), uri));
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-
-        @Override
-        public void onJoinCalls(int requestId, List<ParcelUuid> parcelUuids) {
-            List<UUID> uuids = new ArrayList<>();
-            for (ParcelUuid parcelUuid : parcelUuids) {
-                uuids.add(parcelUuid.getUuid());
-            }
-
-            final long identityToken = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onJoinCalls(requestId, uuids));
-            } finally {
-                Binder.restoreCallingIdentity(identityToken);
-            }
-        }
-    };
-
-    private Context mContext;
-    private ServiceListener mServiceListener;
-    private volatile IBluetoothLeCallControl mService;
-    private BluetoothAdapter mAdapter;
-    private int mCcid = 0;
-    private String mToken;
-    private Callback mCallback = null;
-
-    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
-        new IBluetoothStateChangeCallback.Stub() {
-        public void onBluetoothStateChange(boolean up) {
-            if (DBG)
-                Log.d(TAG, "onBluetoothStateChange: up=" + up);
-            if (!up) {
-                doUnbind();
-            } else {
-                doBind();
-            }
-        }
-    };
-
-    /**
-     * Create a BluetoothLeCallControl proxy object for interacting with the local Bluetooth
-     * telephone bearer service.
-     */
-    /* package */ BluetoothLeCallControl(Context context, ServiceListener listener) {
-        mContext = context;
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mServiceListener = listener;
-
-        IBluetoothManager mgr = mAdapter.getBluetoothManager();
-        if (mgr != null) {
-            try {
-                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-
-        doBind();
-    }
-
-    private boolean doBind() {
-        synchronized (mConnection) {
-            if (mService == null) {
-                if (VDBG)
-                    Log.d(TAG, "Binding service...");
-                try {
-                    return mAdapter.getBluetoothManager().
-                            bindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
-                            mConnection);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to bind TelephoneBearerService", e);
-                }
-            }
-        }
-        return false;
-    }
-
-    private void doUnbind() {
-        synchronized (mConnection) {
-            if (mService != null) {
-                if (VDBG)
-                    Log.d(TAG, "Unbinding service...");
-                try {
-                    mAdapter.getBluetoothManager().
-                        unbindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
-                        mConnection);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to unbind TelephoneBearerService", e);
-                } finally {
-                    mService = null;
-                }
-            }
-        }
-    }
-
-    /* package */ void close() {
-        if (VDBG)
-            log("close()");
-        unregisterBearer();
-
-        IBluetoothManager mgr = mAdapter.getBluetoothManager();
-        if (mgr != null) {
-            try {
-                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
-            } catch (RemoteException re) {
-                Log.e(TAG, "", re);
-            }
-        }
-        mServiceListener = null;
-        doUnbind();
-    }
-
-    private IBluetoothLeCallControl getService() {
-        return mService;
-    }
-
-    /**
-     * Not supported
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public int getConnectionState(@Nullable BluetoothDevice device) {
-        throw new UnsupportedOperationException("not supported");
-    }
-
-    /**
-     * Not supported
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        throw new UnsupportedOperationException("not supported");
-    }
-
-    /**
-     * Not supported
-     *
-     * @throws UnsupportedOperationException
-     */
-    @Override
-    public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
-        @NonNull int[] states) {
-        throw new UnsupportedOperationException("not supported");
-    }
-
-    /**
-     * Register Telephone Bearer exposing the interface that allows remote devices
-     * to track and control the call states.
-     *
-     * <p>
-     * This is an asynchronous call. The callback is used to notify success or
-     * failure if the function returns true.
-     *
-     * <p>
-     * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
-     *
-     * <!-- The UCI is a String identifier of the telephone bearer as defined at
-     * https://www.bluetooth.com/specifications/assigned-numbers/uniform-caller-identifiers
-     * (login required). -->
-     *
-     * <!-- The examples of common URI schemes can be found in
-     * https://iana.org/assignments/uri-schemes/uri-schemes.xhtml -->
-     *
-     * <!-- The Technology is an integer value. The possible values are defined at
-     * https://www.bluetooth.com/specifications/assigned-numbers (login required).
-     * -->
-     *
-     * @param uci          Bearer Unique Client Identifier
-     * @param uriSchemes   URI Schemes supported list
-     * @param capabilities bearer capabilities
-     * @param provider     Network provider name
-     * @param technology   Network technology
-     * @param executor     {@link Executor} object on which callback will be
-     *                     executed. The Executor object is required.
-     * @param callback     {@link Callback} object to which callback messages will
-     *                     be sent. The Callback object is required.
-     * @return true on success, false otherwise
-     * @hide
-     */
-    @SuppressLint("ExecutorRegistration")
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public boolean registerBearer(@Nullable String uci,
-                    @NonNull List<String> uriSchemes, int capabilities,
-                    @NonNull String provider, int technology,
-                    @NonNull Executor executor, @NonNull Callback callback) {
-        if (DBG) {
-            Log.d(TAG, "registerBearer");
-        }
-        if (callback == null) {
-            throw new IllegalArgumentException("null parameter: " + callback);
-        }
-        if (mCcid != 0) {
-            return false;
-        }
-
-        mToken = uci;
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            if (mCallback != null) {
-                Log.e(TAG, "Bearer can be opened only once");
-                return false;
-            }
-
-            mCallback = callback;
-            try {
-                CallbackWrapper callbackWrapper = new CallbackWrapper(executor, callback);
-                service.registerBearer(mToken, callbackWrapper, uci, uriSchemes, capabilities,
-                                        provider, technology);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-                mCallback = null;
-                return false;
-            }
-
-            if (mCcid == 0) {
-                mCallback = null;
-                return false;
-            }
-
-            return true;
-        }
-
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-        }
-
-        return false;
-    }
-
-    /**
-     * Unregister Telephone Bearer Service and destroy all the associated data.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void unregisterBearer() {
-        if (DBG) {
-            Log.d(TAG, "unregisterBearer");
-        }
-        if (mCcid == 0) {
-            return;
-        }
-
-        int ccid = mCcid;
-        mCcid = 0;
-        mCallback = null;
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.unregisterBearer(mToken);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-        }
-    }
-
-    /**
-     * Get the Content Control ID (CCID) value.
-     *
-     * @return ccid Content Control ID value
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public int getContentControlId() {
-        return mCcid;
-    }
-
-    /**
-     * Notify about the newly added call.
-     *
-     * <p>
-     * This shall be called as early as possible after the call has been added.
-     *
-     * <p>
-     * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
-     *
-     * @param call Newly added call
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void onCallAdded(@NonNull BluetoothLeCall call) {
-        if (DBG) {
-            Log.d(TAG, "onCallAdded: call=" + call);
-        }
-        if (mCcid == 0) {
-            return;
-        }
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.callAdded(mCcid, call);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-        }
-    }
-
-    /**
-     * Notify about the removed call.
-     *
-     * <p>
-     * This shall be called as early as possible after the call has been removed.
-     *
-     * <p>
-     * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
-     *
-     * @param callId The Id of a call that has been removed
-     * @param reason Call termination reason
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void onCallRemoved(@NonNull UUID callId, @TerminationReason int reason) {
-        if (DBG) {
-            Log.d(TAG, "callRemoved: callId=" + callId);
-        }
-        if (mCcid == 0) {
-            return;
-        }
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.callRemoved(mCcid, new ParcelUuid(callId), reason);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-        }
-    }
-
-    /**
-     * Notify the call state change
-     *
-     * <p>
-     * This shall be called as early as possible after the state of the call has
-     * changed.
-     *
-     * <p>
-     * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
-     *
-     * @param callId The call Id that state has been changed
-     * @param state  Call state
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void onCallStateChanged(@NonNull UUID callId, @BluetoothLeCall.State int state) {
-        if (DBG) {
-            Log.d(TAG, "callStateChanged: callId=" + callId + " state=" + state);
-        }
-        if (mCcid == 0) {
-            return;
-        }
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.callStateChanged(mCcid, new ParcelUuid(callId), state);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-        }
-    }
-
-    /**
-     * Provide the current calls list
-     *
-     * <p>
-     * This function must be invoked after registration if application has any
-     * calls.
-     *
-     * @param calls current calls list
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-     public void currentCallsList(@NonNull List<BluetoothLeCall> calls) {
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.currentCallsList(mCcid, calls);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-    }
-
-    /**
-     * Provide the network current status
-     *
-     * <p>
-     * This function must be invoked on change of network state.
-     *
-     * <p>
-     * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
-     *
-     * <!-- The Technology is an integer value. The possible values are defined at
-     * https://www.bluetooth.com/specifications/assigned-numbers (login required).
-     * -->
-     *
-     * @param provider   Network provider name
-     * @param technology Network technology
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void networkStateChanged(@NonNull String provider, int technology) {
-        if (DBG) {
-            Log.d(TAG, "networkStateChanged: provider=" + provider + ", technology=" + technology);
-        }
-        if (mCcid == 0) {
-            return;
-        }
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.networkStateChanged(mCcid, provider, technology);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-        }
-    }
-
-    /**
-     * Send a response to a call control request to a remote device.
-     *
-     * <p>
-     * This function must be invoked in when a request is received by one of these
-     * callback methods:
-     *
-     * <ul>
-     * <li>{@link Callback#onAcceptCall}
-     * <li>{@link Callback#onTerminateCall}
-     * <li>{@link Callback#onHoldCall}
-     * <li>{@link Callback#onUnholdCall}
-     * <li>{@link Callback#onPlaceCall}
-     * <li>{@link Callback#onJoinCalls}
-     * </ul>
-     *
-     * @param requestId The ID of the request that was received with the callback
-     * @param result    The result of the request to be sent to the remote devices
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void requestResult(int requestId, @Result int result) {
-        if (DBG) {
-            Log.d(TAG, "requestResult: requestId=" + requestId + " result=" + result);
-        }
-        if (mCcid == 0) {
-            return;
-        }
-
-        final IBluetoothLeCallControl service = getService();
-        if (service != null) {
-            try {
-                service.requestResult(mCcid, requestId, result);
-            } catch (RemoteException e) {
-                Log.e(TAG, "", e);
-            }
-        }
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    private static boolean isValidDevice(@Nullable BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private final IBluetoothProfileServiceConnection mConnection =
-                                    new IBluetoothProfileServiceConnection.Stub() {
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            if (DBG) {
-                Log.d(TAG, "Proxy object connected");
-            }
-            mService = IBluetoothLeCallControl.Stub.asInterface(Binder.allowBlocking(service));
-            mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_CONNECTED));
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            if (DBG) {
-                Log.d(TAG, "Proxy object disconnected");
-            }
-            doUnbind();
-            mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_DISCONNECTED));
-        }
-    };
-
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MESSAGE_TBS_SERVICE_CONNECTED: {
-                if (mServiceListener != null) {
-                    mServiceListener.onServiceConnected(BluetoothProfile.LE_CALL_CONTROL,
-                        BluetoothLeCallControl.this);
-                }
-                break;
-            }
-            case MESSAGE_TBS_SERVICE_DISCONNECTED: {
-                if (mServiceListener != null) {
-                    mServiceListener.onServiceDisconnected(BluetoothProfile.LE_CALL_CONTROL);
-                }
-                break;
-            }
-            }
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
deleted file mode 100644
index fef6f22..0000000
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.RequiresFeature;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemService;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * High level manager used to obtain an instance of an {@link BluetoothAdapter}
- * and to conduct overall Bluetooth Management.
- * <p>
- * Use {@link android.content.Context#getSystemService(java.lang.String)}
- * with {@link Context#BLUETOOTH_SERVICE} to create an {@link BluetoothManager},
- * then call {@link #getAdapter} to obtain the {@link BluetoothAdapter}.
- * </p>
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>
- * For more information about using BLUETOOTH, read the <a href=
- * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
- * guide.
- * </p>
- * </div>
- *
- * @see Context#getSystemService
- * @see BluetoothAdapter#getDefaultAdapter()
- */
-@SystemService(Context.BLUETOOTH_SERVICE)
-@RequiresFeature(PackageManager.FEATURE_BLUETOOTH)
-public final class BluetoothManager {
-    private static final String TAG = "BluetoothManager";
-    private static final boolean DBG = false;
-
-    private final AttributionSource mAttributionSource;
-    private final BluetoothAdapter mAdapter;
-
-    /**
-     * @hide
-     */
-    public BluetoothManager(Context context) {
-        mAttributionSource = (context != null) ? context.getAttributionSource() :
-                AttributionSource.myAttributionSource();
-        mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
-    }
-
-    /**
-     * Get the BLUETOOTH Adapter for this device.
-     *
-     * @return the BLUETOOTH Adapter
-     */
-    @RequiresNoPermission
-    public BluetoothAdapter getAdapter() {
-        return mAdapter;
-    }
-
-    /**
-     * Get the current connection state of the profile to the remote device.
-     *
-     * <p>This is not specific to any application configuration but represents
-     * the connection state of the local Bluetooth adapter for certain profile.
-     * This can be used by applications like status bar which would just like
-     * to know the state of Bluetooth.
-     *
-     * @param device Remote bluetooth device.
-     * @param profile GATT or GATT_SERVER
-     * @return State of the profile connection. One of {@link BluetoothProfile#STATE_CONNECTED},
-     * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED},
-     * {@link BluetoothProfile#STATE_DISCONNECTING}
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device, int profile) {
-        if (DBG) Log.d(TAG, "getConnectionState()");
-
-        List<BluetoothDevice> connectedDevices = getConnectedDevices(profile);
-        for (BluetoothDevice connectedDevice : connectedDevices) {
-            if (device.equals(connectedDevice)) {
-                return BluetoothProfile.STATE_CONNECTED;
-            }
-        }
-
-        return BluetoothProfile.STATE_DISCONNECTED;
-    }
-
-    /**
-     * Get connected devices for the specified profile.
-     *
-     * <p> Return the set of devices which are in state {@link BluetoothProfile#STATE_CONNECTED}
-     *
-     * <p>This is not specific to any application configuration but represents
-     * the connection state of Bluetooth for this profile.
-     * This can be used by applications like status bar which would just like
-     * to know the state of Bluetooth.
-     *
-     * @param profile GATT or GATT_SERVER
-     * @return List of devices. The list will be empty on error.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices(int profile) {
-        if (DBG) Log.d(TAG, "getConnectedDevices");
-        return getDevicesMatchingConnectionStates(profile, new int[] {
-                BluetoothProfile.STATE_CONNECTED
-        });
-    }
-
-    /**
-     * Get a list of devices that match any of the given connection
-     * states.
-     *
-     * <p> If none of the devices match any of the given states,
-     * an empty list will be returned.
-     *
-     * <p>This is not specific to any application configuration but represents
-     * the connection state of the local Bluetooth adapter for this profile.
-     * This can be used by applications like status bar which would just like
-     * to know the state of the local adapter.
-     *
-     * @param profile GATT or GATT_SERVER
-     * @param states Array of states. States can be one of {@link BluetoothProfile#STATE_CONNECTED},
-     * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED},
-     * {@link BluetoothProfile#STATE_DISCONNECTING},
-     * @return List of devices. The list will be empty on error.
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) {
-        if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates");
-
-        if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
-            throw new IllegalArgumentException("Profile not supported: " + profile);
-        }
-
-        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
-
-        try {
-            IBluetoothManager managerService = mAdapter.getBluetoothManager();
-            IBluetoothGatt iGatt = managerService.getBluetoothGatt();
-            if (iGatt == null) return devices;
-            devices = Attributable.setAttributionSource(
-                    iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
-                    mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-
-        return devices;
-    }
-
-    /**
-     * Open a GATT Server
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as the results of any other GATT server operations.
-     * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
-     * to conduct GATT server operations.
-     *
-     * @param context App context
-     * @param callback GATT server callback handler that will receive asynchronous callbacks.
-     * @return BluetoothGattServer instance
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGattServer openGattServer(Context context,
-            BluetoothGattServerCallback callback) {
-
-        return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO));
-    }
-
-    /**
-     * Open a GATT Server
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as the results of any other GATT server operations.
-     * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
-     * to conduct GATT server operations.
-     *
-     * @param context App context
-     * @param callback GATT server callback handler that will receive asynchronous callbacks.
-     * @param eatt_support idicates if server should use eatt channel for notifications.
-     * @return BluetoothGattServer instance
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGattServer openGattServer(Context context,
-            BluetoothGattServerCallback callback, boolean eatt_support) {
-        return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO, eatt_support));
-    }
-
-    /**
-     * Open a GATT Server
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as the results of any other GATT server operations.
-     * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
-     * to conduct GATT server operations.
-     *
-     * @param context App context
-     * @param callback GATT server callback handler that will receive asynchronous callbacks.
-     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
-     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
-     * BluetoothDevice#TRANSPORT_LE}
-     * @return BluetoothGattServer instance
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGattServer openGattServer(Context context,
-            BluetoothGattServerCallback callback, int transport) {
-        return (openGattServer(context, callback, transport, false));
-    }
-
-    /**
-     * Open a GATT Server
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as the results of any other GATT server operations.
-     * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
-     * to conduct GATT server operations.
-     *
-     * @param context App context
-     * @param callback GATT server callback handler that will receive asynchronous callbacks.
-     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
-     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
-     * BluetoothDevice#TRANSPORT_LE}
-     * @param eatt_support idicates if server should use eatt channel for notifications.
-     * @return BluetoothGattServer instance
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothGattServer openGattServer(Context context,
-            BluetoothGattServerCallback callback, int transport, boolean eatt_support) {
-        if (context == null || callback == null) {
-            throw new IllegalArgumentException("null parameter: " + context + " " + callback);
-        }
-
-        // TODO(Bluetooth) check whether platform support BLE
-        //     Do the check here or in GattServer?
-
-        try {
-            IBluetoothManager managerService = mAdapter.getBluetoothManager();
-            IBluetoothGatt iGatt = managerService.getBluetoothGatt();
-            if (iGatt == null) {
-                Log.e(TAG, "Fail to get GATT Server connection");
-                return null;
-            }
-            BluetoothGattServer mGattServer =
-                    new BluetoothGattServer(iGatt, transport, mAdapter);
-            Boolean regStatus = mGattServer.registerCallback(callback, eatt_support);
-            return regStatus ? mGattServer : null;
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return null;
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
deleted file mode 100644
index 56e4972..0000000
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth MAP
- * Profile.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
-
-    private static final String TAG = "BluetoothMap";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    private CloseGuard mCloseGuard;
-
-    /** @hide */
-    @SuppressLint("ActionValue")
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * There was an error trying to obtain the state
-     *
-     * @hide
-     */
-    public static final int STATE_ERROR = -1;
-
-    /** @hide */
-    public static final int RESULT_FAILURE = 0;
-    /** @hide */
-    public static final int RESULT_SUCCESS = 1;
-    /**
-     * Connection canceled before completion.
-     *
-     * @hide
-     */
-    public static final int RESULT_CANCELED = 2;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.MAP,
-                    "BluetoothMap", IBluetoothMap.class.getName()) {
-                @Override
-                public IBluetoothMap getServiceInterface(IBinder service) {
-                    return IBluetoothMap.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothMap proxy object.
-     */
-    /* package */ BluetoothMap(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-        mCloseGuard = new CloseGuard();
-        mCloseGuard.open("close");
-    }
-
-    protected void finalize() {
-        if (mCloseGuard != null) {
-            mCloseGuard.warnIfOpen();
-        }
-        close();
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothMap will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     *
-     * @hide
-     */
-    @SystemApi
-    public void close() {
-        if (VDBG) log("close()");
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothMap getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Get the current state of the BluetoothMap service.
-     *
-     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not
-     * connected to the Map service.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getState() {
-        if (VDBG) log("getState()");
-        final IBluetoothMap service = getService();
-        final int defaultValue = BluetoothMap.STATE_ERROR;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getState(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the currently connected remote Bluetooth device (PCE).
-     *
-     * @return The remote Bluetooth device, or null if not in connected or connecting state, or if
-     * this proxy object is not connected to the Map service.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothDevice getClient() {
-        if (VDBG) log("getClient()");
-        final IBluetoothMap service = getService();
-        final BluetoothDevice defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<BluetoothDevice> recv =
-                        new SynchronousResultReceiver();
-                service.getClient(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns true if the specified Bluetooth device is connected.
-     * Returns false if not connected, or if this proxy object is not
-     * currently connected to the Map service.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isConnected(BluetoothDevice device) {
-        if (VDBG) log("isConnected(" + device + ")");
-        final IBluetoothMap service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isConnected(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate connection. Initiation of outgoing connections is not
-     * supported for MAP server.
-     *
-     * @hide
-     */
-    @RequiresNoPermission
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")" + "not supported for MAPS");
-        return false;
-    }
-
-    /**
-     * Initiate disconnect.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on error, true otherwise
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothMap service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Check class bits for possible Map support.
-     * This is a simple heuristic that tries to guess if a device with the
-     * given class bits might support Map. It is not accurate for all
-     * devices. It tries to err on the side of false positives.
-     *
-     * @return True if this device might support Map.
-     *
-     * @hide
-     */
-    public static boolean doesClassMatchSink(BluetoothClass btClass) {
-        // TODO optimize the rule
-        switch (btClass.getDeviceClass()) {
-            case BluetoothClass.Device.COMPUTER_DESKTOP:
-            case BluetoothClass.Device.COMPUTER_LAPTOP:
-            case BluetoothClass.Device.COMPUTER_SERVER:
-            case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Get the list of connected devices. Currently at most one.
-     *
-     * @return list of connected devices
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
-        final IBluetoothMap service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of devices matching specified states. Currently at most one.
-     *
-     * @return list of matching devices
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
-        final IBluetoothMap service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get connection state of device
-     *
-     * @return device connection state
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getConnectionState(" + device + ")");
-        final IBluetoothMap service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothMap service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                    && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                        || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothMap service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.isEnabled();
-    }
-
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
deleted file mode 100644
index 03536f9a..0000000
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-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.app.PendingIntent;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth MAP MCE Profile.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothMapClient implements BluetoothProfile {
-
-    private static final String TAG = "BluetoothMapClient";
-    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
-
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
-    /** @hide */
-    @RequiresPermission(android.Manifest.permission.RECEIVE_SMS)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_MESSAGE_RECEIVED =
-            "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED";
-    /* Actions to be used for pending intents */
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY =
-            "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY";
-    /** @hide */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
-            "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
-
-    /**
-     * Action to notify read status changed
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_MESSAGE_READ_STATUS_CHANGED =
-            "android.bluetooth.mapmce.profile.action.MESSAGE_READ_STATUS_CHANGED";
-
-    /**
-     * Action to notify deleted status changed
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_MESSAGE_DELETED_STATUS_CHANGED =
-            "android.bluetooth.mapmce.profile.action.MESSAGE_DELETED_STATUS_CHANGED";
-
-    /**
-     * Extras used in ACTION_MESSAGE_RECEIVED intent.
-     * NOTE: HANDLE is only valid for a single session with the device.
-     */
-    /** @hide */
-    public static final String EXTRA_MESSAGE_HANDLE =
-            "android.bluetooth.mapmce.profile.extra.MESSAGE_HANDLE";
-    /** @hide */
-    public static final String EXTRA_MESSAGE_TIMESTAMP =
-            "android.bluetooth.mapmce.profile.extra.MESSAGE_TIMESTAMP";
-    /** @hide */
-    public static final String EXTRA_MESSAGE_READ_STATUS =
-            "android.bluetooth.mapmce.profile.extra.MESSAGE_READ_STATUS";
-    /** @hide */
-    public static final String EXTRA_SENDER_CONTACT_URI =
-            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_URI";
-    /** @hide */
-    public static final String EXTRA_SENDER_CONTACT_NAME =
-            "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
-
-    /**
-     * Used as a boolean extra in ACTION_MESSAGE_DELETED_STATUS_CHANGED
-     * Contains the MAP message deleted status
-     * Possible values are:
-     * true: deleted
-     * false: undeleted
-     *
-     * @hide
-     */
-    public static final String EXTRA_MESSAGE_DELETED_STATUS =
-            "android.bluetooth.mapmce.profile.extra.MESSAGE_DELETED_STATUS";
-
-    /**
-     * Extra used in ACTION_MESSAGE_READ_STATUS_CHANGED or ACTION_MESSAGE_DELETED_STATUS_CHANGED
-     * Possible values are:
-     * 0: failure
-     * 1: success
-     *
-     * @hide
-     */
-    public static final String EXTRA_RESULT_CODE =
-            "android.bluetooth.device.extra.RESULT_CODE";
-
-    /**
-     * There was an error trying to obtain the state
-     * @hide
-     */
-    public static final int STATE_ERROR = -1;
-
-    /** @hide */
-    public static final int RESULT_FAILURE = 0;
-    /** @hide */
-    public static final int RESULT_SUCCESS = 1;
-    /**
-     * Connection canceled before completion.
-     * @hide
-     */
-    public static final int RESULT_CANCELED = 2;
-    /** @hide */
-    private static final int UPLOADING_FEATURE_BITMASK = 0x08;
-
-    /*
-     * UNREAD, READ, UNDELETED, DELETED are passed as parameters
-     * to setMessageStatus to indicate the messages new state.
-     */
-
-    /** @hide */
-    public static final int UNREAD = 0;
-    /** @hide */
-    public static final int READ = 1;
-    /** @hide */
-    public static final int UNDELETED = 2;
-    /** @hide */
-    public static final int DELETED = 3;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT,
-                    "BluetoothMapClient", IBluetoothMapClient.class.getName()) {
-                @Override
-                public IBluetoothMapClient getServiceInterface(IBinder service) {
-                    return IBluetoothMapClient.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothMapClient proxy object.
-     */
-    /* package */ BluetoothMapClient(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothMap will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     * @hide
-     */
-    public void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothMapClient getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Returns true if the specified Bluetooth device is connected.
-     * Returns false if not connected, or if this proxy object is not
-     * currently connected to the Map service.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isConnected(BluetoothDevice device) {
-        if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isConnected(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate connection. Initiation of outgoing connections is not
-     * supported for MAP server.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnect.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on error, true otherwise
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "disconnect(" + device + ")");
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of connected devices. Currently at most one.
-     *
-     * @return list of connected devices
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) Log.d(TAG, "getConnectedDevices()");
-        final IBluetoothMapClient service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of devices matching specified states. Currently at most one.
-     *
-     * @return list of matching devices
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
-        final IBluetoothMapClient service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get connection state of device
-     *
-     * @return device connection state
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
-        final IBluetoothMapClient service = getService();
-        final int defaultValue =  BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver<>();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) Log.d(TAG, "getConnectionPolicy(" + device + ")");
-        final IBluetoothMapClient service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Send a message.
-     *
-     * Send an SMS message to either the contacts primary number or the telephone number specified.
-     *
-     * @param device Bluetooth device
-     * @param contacts Uri Collection of the contacts
-     * @param message Message to be sent
-     * @param sentIntent intent issued when message is sent
-     * @param deliveredIntent intent issued when message is delivered
-     * @return true if the message is enqueued, false on error
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.SEND_SMS,
-    })
-    public boolean sendMessage(@NonNull BluetoothDevice device, @NonNull Collection<Uri> contacts,
-            @NonNull String message, @Nullable PendingIntent sentIntent,
-            @Nullable PendingIntent deliveredIntent) {
-        return sendMessage(device, contacts.toArray(new Uri[contacts.size()]), message, sentIntent,
-                deliveredIntent);
-    }
-
-     /**
-     * Send a message.
-     *
-     * Send an SMS message to either the contacts primary number or the telephone number specified.
-     *
-     * @param device Bluetooth device
-     * @param contacts Uri[] of the contacts
-     * @param message Message to be sent
-     * @param sentIntent intent issued when message is sent
-     * @param deliveredIntent intent issued when message is delivered
-     * @return true if the message is enqueued, false on error
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.SEND_SMS,
-    })
-    public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
-            PendingIntent sentIntent, PendingIntent deliveredIntent) {
-        if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.sendMessage(device, contacts, message, sentIntent, deliveredIntent,
-                        mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get unread messages.  Unread messages will be published via {@link #ACTION_MESSAGE_RECEIVED}.
-     *
-     * @param device Bluetooth device
-     * @return true if the message is enqueued, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.READ_SMS,
-    })
-    public boolean getUnreadMessages(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.getUnreadMessages(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns the "Uploading" feature bit value from the SDP record's
-     * MapSupportedFeatures field (see Bluetooth MAP 1.4 spec, page 114).
-     * @param device The Bluetooth device to get this value for.
-     * @return Returns true if the Uploading bit value in SDP record's
-     *         MapSupportedFeatures field is set. False is returned otherwise.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isUploadingSupported(BluetoothDevice device) {
-        if (DBG) Log.d(TAG, "isUploadingSupported(" + device + ")");
-        final IBluetoothMapClient service = getService();
-        final int defaultValue = 0;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getSupportedFeatures(device, mAttributionSource, recv);
-                return (recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue)
-                        & UPLOADING_FEATURE_BITMASK) > 0;
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Set message status of message on MSE
-     * <p>
-     * When read status changed, the result will be published via
-     * {@link #ACTION_MESSAGE_READ_STATUS_CHANGED}
-     * When deleted status changed, the result will be published via
-     * {@link #ACTION_MESSAGE_DELETED_STATUS_CHANGED}
-     *
-     * @param device Bluetooth device
-     * @param handle message handle
-     * @param status <code>UNREAD</code> for "unread", <code>READ</code> for
-     *            "read", <code>UNDELETED</code> for "undeleted", <code>DELETED</code> for
-     *            "deleted", otherwise return error
-     * @return <code>true</code> if request has been sent, <code>false</code> on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.READ_SMS,
-    })
-    public boolean setMessageStatus(BluetoothDevice device, String handle, int status) {
-        if (DBG) Log.d(TAG, "setMessageStatus(" + device + ", " + handle + ", " + status + ")");
-        final IBluetoothMapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device) && handle != null && (status == READ
-                    || status == UNREAD || status == UNDELETED  || status == DELETED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setMessageStatus(device, handle, status, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.isEnabled();
-    }
-
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothMasInstance.java b/core/java/android/bluetooth/BluetoothMasInstance.java
deleted file mode 100644
index eeaf085..0000000
--- a/core/java/android/bluetooth/BluetoothMasInstance.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public final class BluetoothMasInstance implements Parcelable {
-    private final int mId;
-    private final String mName;
-    private final int mChannel;
-    private final int mMsgTypes;
-
-    public BluetoothMasInstance(int id, String name, int channel, int msgTypes) {
-        mId = id;
-        mName = name;
-        mChannel = channel;
-        mMsgTypes = msgTypes;
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (o instanceof BluetoothMasInstance) {
-            return mId == ((BluetoothMasInstance) o).mId;
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return mId + (mChannel << 8) + (mMsgTypes << 16);
-    }
-
-    @Override
-    public String toString() {
-        return Integer.toString(mId) + ":" + mName + ":" + mChannel + ":"
-                + Integer.toHexString(mMsgTypes);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothMasInstance> CREATOR =
-            new Parcelable.Creator<BluetoothMasInstance>() {
-                public BluetoothMasInstance createFromParcel(Parcel in) {
-                    return new BluetoothMasInstance(in.readInt(), in.readString(),
-                            in.readInt(), in.readInt());
-                }
-
-                public BluetoothMasInstance[] newArray(int size) {
-                    return new BluetoothMasInstance[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mId);
-        out.writeString(mName);
-        out.writeInt(mChannel);
-        out.writeInt(mMsgTypes);
-    }
-
-    public static final class MessageType {
-        public static final int EMAIL = 0x01;
-        public static final int SMS_GSM = 0x02;
-        public static final int SMS_CDMA = 0x04;
-        public static final int MMS = 0x08;
-    }
-
-    public int getId() {
-        return mId;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    public int getChannel() {
-        return mChannel;
-    }
-
-    public int getMsgTypes() {
-        return mMsgTypes;
-    }
-
-    public boolean msgSupported(int msg) {
-        return (mMsgTypes & msg) != 0;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java
deleted file mode 100644
index ac2b3ed..0000000
--- a/core/java/android/bluetooth/BluetoothOutputStream.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.SuppressLint;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * BluetoothOutputStream.
- *
- * Used to read from a Bluetooth socket.
- *
- * @hide
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-/*package*/ final class BluetoothOutputStream extends OutputStream {
-    private BluetoothSocket mSocket;
-
-    /*package*/ BluetoothOutputStream(BluetoothSocket s) {
-        mSocket = s;
-    }
-
-    /**
-     * Close this output stream and the socket associated with it.
-     */
-    public void close() throws IOException {
-        mSocket.close();
-    }
-
-    /**
-     * Writes a single byte to this stream. Only the least significant byte of
-     * the integer {@code oneByte} is written to the stream.
-     *
-     * @param oneByte the byte to be written.
-     * @throws IOException if an error occurs while writing to this stream.
-     * @since Android 1.0
-     */
-    public void write(int oneByte) throws IOException {
-        byte[] b = new byte[1];
-        b[0] = (byte) oneByte;
-        mSocket.write(b, 0, 1);
-    }
-
-    /**
-     * Writes {@code count} bytes from the byte array {@code buffer} starting
-     * at position {@code offset} to this stream.
-     *
-     * @param b the buffer to be written.
-     * @param offset the start position in {@code buffer} from where to get bytes.
-     * @param count the number of bytes from {@code buffer} to write to this stream.
-     * @throws IOException if an error occurs while writing to this stream.
-     * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code count < 0}, or if {@code
-     * offset + count} is bigger than the length of {@code buffer}.
-     * @since Android 1.0
-     */
-    public void write(byte[] b, int offset, int count) throws IOException {
-        if (b == null) {
-            throw new NullPointerException("buffer is null");
-        }
-        if ((offset | count) < 0 || count > b.length - offset) {
-            throw new IndexOutOfBoundsException("invalid offset or length");
-        }
-        mSocket.write(b, offset, count);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
deleted file mode 100644
index d4ad4ef4..0000000
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth Pan
- * Profile.
- *
- * <p>BluetoothPan is a proxy object for controlling the Bluetooth
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothPan proxy object.
- *
- * <p>Each method is protected with its appropriate permission.
- *
- * @hide
- */
-@SystemApi
-public final class BluetoothPan implements BluetoothProfile {
-    private static final String TAG = "BluetoothPan";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the Pan
-     * profile.
-     *
-     * <p>This intent will have 4 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>
-     * <li> {@link #EXTRA_LOCAL_ROLE} - Which local role the remote device is
-     * bound to. </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}.
-     *
-     * <p> {@link #EXTRA_LOCAL_ROLE} can be one of {@link #LOCAL_NAP_ROLE} or
-     * {@link #LOCAL_PANU_ROLE}
-     */
-    @SuppressLint("ActionValue")
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * Extra for {@link #ACTION_CONNECTION_STATE_CHANGED} intent
-     * The local role of the PAN profile that the remote device is bound to.
-     * It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}.
-     */
-    @SuppressLint("ActionValue")
-    public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
-
-    /**
-     * Intent used to broadcast the change in tethering state of the Pan
-     * Profile
-     *
-     * <p>This intent will have 1 extra:
-     * <ul>
-     * <li> {@link #EXTRA_TETHERING_STATE} - The current state of Bluetooth
-     * tethering. </li>
-     * </ul>
-     *
-     * <p> {@link #EXTRA_TETHERING_STATE} can be any of {@link #TETHERING_STATE_OFF} or
-     * {@link #TETHERING_STATE_ON}
-     */
-    @RequiresLegacyBluetoothPermission
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_TETHERING_STATE_CHANGED =
-            "android.bluetooth.action.TETHERING_STATE_CHANGED";
-
-    /**
-     * Extra for {@link #ACTION_TETHERING_STATE_CHANGED} intent
-     * The tethering state of the PAN profile.
-     * It can be one of {@link #TETHERING_STATE_OFF} or {@link #TETHERING_STATE_ON}.
-     */
-    public static final String EXTRA_TETHERING_STATE =
-            "android.bluetooth.extra.TETHERING_STATE";
-
-    /** @hide */
-    @IntDef({PAN_ROLE_NONE, LOCAL_NAP_ROLE, LOCAL_PANU_ROLE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface LocalPanRole {}
-
-    public static final int PAN_ROLE_NONE = 0;
-    /**
-     * The local device is acting as a Network Access Point.
-     */
-    public static final int LOCAL_NAP_ROLE = 1;
-
-    /**
-     * The local device is acting as a PAN User.
-     */
-    public static final int LOCAL_PANU_ROLE = 2;
-
-    /** @hide */
-    @IntDef({PAN_ROLE_NONE, REMOTE_NAP_ROLE, REMOTE_PANU_ROLE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RemotePanRole {}
-
-    public static final int REMOTE_NAP_ROLE = 1;
-
-    public static final int REMOTE_PANU_ROLE = 2;
-
-    /** @hide **/
-    @IntDef({TETHERING_STATE_OFF, TETHERING_STATE_ON})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface TetheringState{}
-
-    public static final int TETHERING_STATE_OFF = 1;
-
-    public static final int TETHERING_STATE_ON = 2;
-    /**
-     * Return codes for the connect and disconnect Bluez / Dbus calls.
-     *
-     * @hide
-     */
-    public static final int PAN_DISCONNECT_FAILED_NOT_CONNECTED = 1000;
-
-    /**
-     * @hide
-     */
-    public static final int PAN_CONNECT_FAILED_ALREADY_CONNECTED = 1001;
-
-    /**
-     * @hide
-     */
-    public static final int PAN_CONNECT_FAILED_ATTEMPT_FAILED = 1002;
-
-    /**
-     * @hide
-     */
-    public static final int PAN_OPERATION_GENERIC_FAILURE = 1003;
-
-    /**
-     * @hide
-     */
-    public static final int PAN_OPERATION_SUCCESS = 1004;
-
-    private final Context mContext;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.PAN,
-                    "BluetoothPan", IBluetoothPan.class.getName()) {
-                @Override
-                public IBluetoothPan getServiceInterface(IBinder service) {
-                    return IBluetoothPan.Stub.asInterface(service);
-                }
-    };
-
-
-    /**
-     * Create a BluetoothPan proxy object for interacting with the local
-     * Bluetooth Service which handles the Pan profile
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    /* package */ BluetoothPan(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mContext = context;
-        mProfileConnector.connect(context, listener);
-    }
-
-    /**
-     * Closes the connection to the service and unregisters callbacks
-     */
-    @UnsupportedAppUsage
-    void close() {
-        if (VDBG) log("close()");
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothPan getService() {
-        return mProfileConnector.getService();
-    }
-
-    /** @hide */
-    protected void finalize() {
-        close();
-    }
-
-    /**
-     * Initiate connection to a profile of the remote bluetooth device.
-     *
-     * <p> This API returns false in scenarios like the profile on the
-     * device is already connected or Bluetooth is not turned on.
-     * When this API returns true, it is guaranteed that
-     * connection state intent for the profile will be broadcasted with
-     * the state. Users can get the connection state of the profile
-     * from this intent.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")");
-        final IBluetoothPan service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnection from a profile
-     *
-     * <p> This API will return false in scenarios like the profile on the
-     * Bluetooth device is not in connected state etc. When this API returns,
-     * true, it is guaranteed that the connection state change
-     * intent will be broadcasted with the state. Users can get the
-     * disconnection state of the profile from this intent.
-     *
-     * <p> If the disconnection is initiated by a remote device, the state
-     * will transition from {@link #STATE_CONNECTED} to
-     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
-     * host (local) device the state will transition from
-     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
-     * state {@link #STATE_DISCONNECTED}. The transition to
-     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
-     * two scenarios.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on immediate error, true otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothPan service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothPan service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @hide
-     */
-    @SystemApi
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (VDBG) log("getConnectedDevices()");
-        final IBluetoothPan service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @hide
-     */
-    @Override
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (VDBG) log("getDevicesMatchingStates()");
-        final IBluetoothPan service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @hide
-     */
-    @SystemApi
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getConnectionState(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getState(" + device + ")");
-        final IBluetoothPan service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Turns on/off bluetooth tethering
-     *
-     * @param value is whether to enable or disable bluetooth tethering
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-            android.Manifest.permission.TETHER_PRIVILEGED,
-    })
-    public void setBluetoothTethering(boolean value) {
-        String pkgName = mContext.getOpPackageName();
-        if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName);
-        final IBluetoothPan service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setBluetoothTethering(value, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * Determines whether tethering is enabled
-     *
-     * @return true if tethering is on, false if not or some error occurred
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isTetheringOn() {
-        if (VDBG) log("isTetheringOn()");
-        final IBluetoothPan service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isTetheringOn(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    @UnsupportedAppUsage
-    private boolean isEnabled() {
-        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    @UnsupportedAppUsage
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-
-    @UnsupportedAppUsage
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
deleted file mode 100644
index de2db9c..0000000
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Public API for controlling the Bluetooth Pbap Service. This includes
- * Bluetooth Phone book Access profile.
- * BluetoothPbap is a proxy object for controlling the Bluetooth Pbap
- * Service via IPC.
- *
- * Creating a BluetoothPbap object will create a binding with the
- * BluetoothPbap service. Users of this object should call close() when they
- * are finished with the BluetoothPbap, so that this proxy object can unbind
- * from the service.
- *
- * This BluetoothPbap object is not immediately bound to the
- * BluetoothPbap service. Use the ServiceListener interface to obtain a
- * notification when it is bound, this is especially important if you wish to
- * immediately call methods on BluetoothPbap after construction.
- *
- * To get an instance of the BluetoothPbap class, you can call
- * {@link BluetoothAdapter#getProfileProxy(Context, ServiceListener, int)} with the final param
- * being {@link BluetoothProfile#PBAP}. The ServiceListener should be able to get the instance of
- * BluetoothPbap in {@link android.bluetooth.BluetoothProfile.ServiceListener#onServiceConnected}.
- *
- * Android only supports one connected Bluetooth Pce at a time.
- *
- * @hide
- */
-@SystemApi
-public class BluetoothPbap implements BluetoothProfile {
-
-    private static final String TAG = "BluetoothPbap";
-    private static final boolean DBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the PBAP
-     * profile.
-     *
-     * <p>This intent will have 3 extras:
-     * <ul>
-     * <li> {@link BluetoothProfile#EXTRA_STATE} - The current state of the profile. </li>
-     * <li> {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
-     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
-     * </ul>
-     * <p>{@link BluetoothProfile#EXTRA_STATE} or {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}
-     *  can be any of {@link BluetoothProfile#STATE_DISCONNECTED},
-     *  {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_CONNECTED},
-     *  {@link BluetoothProfile#STATE_DISCONNECTING}.
-     *
-     * @hide
-     */
-    @SuppressLint("ActionValue")
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
-
-    private final AttributionSource mAttributionSource;
-
-    /** @hide */
-    public static final int RESULT_FAILURE = 0;
-    /** @hide */
-    public static final int RESULT_SUCCESS = 1;
-    /**
-     * Connection canceled before completion.
-     *
-     * @hide
-     */
-    public static final int RESULT_CANCELED = 2;
-
-    private BluetoothAdapter mAdapter;
-    private final BluetoothProfileConnector<IBluetoothPbap> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.PBAP, "BluetoothPbap",
-                    IBluetoothPbap.class.getName()) {
-                @Override
-                public IBluetoothPbap getServiceInterface(IBinder service) {
-                    return IBluetoothPbap.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothPbap proxy object.
-     *
-     * @hide
-     */
-    public BluetoothPbap(Context context, ServiceListener listener, BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    /** @hide */
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothPbap will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     *
-     * @hide
-     */
-    public synchronized void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothPbap getService() {
-        return (IBluetoothPbap) mProfileConnector.getService();
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        log("getConnectedDevices()");
-        final IBluetoothPbap service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            return new ArrayList<BluetoothDevice>();
-        }
-        try {
-            return Attributable.setAttributionSource(
-                    service.getConnectedDevices(mAttributionSource), mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
-        return new ArrayList<BluetoothDevice>();
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @SystemApi
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
-        log("getConnectionState: device=" + device);
-        try {
-            final IBluetoothPbap service = getService();
-            if (service != null && isEnabled() && isValidDevice(device)) {
-                return service.getConnectionState(device, mAttributionSource);
-            }
-            if (service == null) {
-                Log.w(TAG, "Proxy not attached to service");
-            }
-            return BluetoothProfile.STATE_DISCONNECTED;
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
-        return BluetoothProfile.STATE_DISCONNECTED;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @hide
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states));
-        final IBluetoothPbap service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            return new ArrayList<BluetoothDevice>();
-        }
-        try {
-            return Attributable.setAttributionSource(
-                    service.getDevicesMatchingConnectionStates(states, mAttributionSource),
-                    mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
-        return new ArrayList<BluetoothDevice>();
-    }
-
-    /**
-     * Set connection policy of the profile and tries to disconnect it if connectionPolicy is
-     * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN}
-     *
-     * <p> The device should already be paired.
-     * Connection policy can be one of:
-     * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED},
-     * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN},
-     * {@link BluetoothProfile#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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        try {
-            final IBluetoothPbap service = getService();
-            if (service != null && isEnabled()
-                    && isValidDevice(device)) {
-                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                        && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
-                    return false;
-                }
-                return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource);
-            }
-            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;
-        }
-    }
-
-    /**
-     * Disconnects the current Pbap client (PCE). Currently this call blocks,
-     * it may soon be made asynchronous. Returns false if this proxy object is
-     * not currently connected to the Pbap service.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        log("disconnect()");
-        final IBluetoothPbap service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            return false;
-        }
-        try {
-            service.disconnect(device, mAttributionSource);
-            return true;
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
-        return false;
-    }
-
-    private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
-    }
-
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
-    }
-
-    private static void log(String msg) {
-        if (DBG) {
-            Log.d(TAG, msg);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
deleted file mode 100644
index e096de8..0000000
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth PBAP Client Profile.
- *
- * @hide
- */
-public final class BluetoothPbapClient implements BluetoothProfile {
-
-    private static final String TAG = "BluetoothPbapClient";
-    private static final boolean DBG = false;
-    private static final boolean VDBG = false;
-
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
-
-    /** There was an error trying to obtain the state */
-    public static final int STATE_ERROR = -1;
-
-    public static final int RESULT_FAILURE = 0;
-    public static final int RESULT_SUCCESS = 1;
-    /** Connection canceled before completion. */
-    public static final int RESULT_CANCELED = 2;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
-                    "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
-                @Override
-                public IBluetoothPbapClient getServiceInterface(IBinder service) {
-                    return IBluetoothPbapClient.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothPbapClient proxy object.
-     */
-    BluetoothPbapClient(Context context, ServiceListener listener, BluetoothAdapter adapter) {
-        if (DBG) {
-            Log.d(TAG, "Create BluetoothPbapClient proxy object");
-        }
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothPbapClient will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     */
-    public synchronized void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothPbapClient getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Initiate connection.
-     * Upon successful connection to remote PBAP server the Client will
-     * attempt to automatically download the users phonebook and call log.
-     *
-     * @param device a remote device we want connect to
-     * @return <code>true</code> if command has been issued successfully; <code>false</code>
-     * otherwise;
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) {
-            log("connect(" + device + ") for PBAP Client.");
-        }
-        final IBluetoothPbapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.connect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate disconnect.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on error, true otherwise
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) {
-            log("disconnect(" + device + ")" + new Exception());
-        }
-        final IBluetoothPbapClient service = getService();
-        final boolean defaultValue = true;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-                return true;
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of connected devices.
-     * Currently at most one.
-     *
-     * @return list of connected devices
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) {
-            log("getConnectedDevices()");
-        }
-        final IBluetoothPbapClient service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of devices matching specified states. Currently at most one.
-     *
-     * @return list of matching devices
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) {
-            log("getDevicesMatchingStates()");
-        }
-        final IBluetoothPbapClient service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get connection state of device
-     *
-     * @return device connection state
-     */
-    @Override
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (DBG) {
-            log("getConnectionState(" + device + ")");
-        }
-        final IBluetoothPbapClient service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.isEnabled();
-    }
-
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) {
-            log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        }
-        final IBluetoothPbapClient service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) {
-            log("getConnectionPolicy(" + device + ")");
-        }
-        final IBluetoothPbapClient service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
deleted file mode 100644
index d0f74e9..0000000
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2010-2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.IntDef;
-import android.annotation.RequiresNoPermission;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * Public APIs for the Bluetooth Profiles.
- *
- * <p> Clients should call {@link BluetoothAdapter#getProfileProxy},
- * to get the Profile Proxy. Each public profile implements this
- * interface.
- */
-public interface BluetoothProfile {
-
-    /**
-     * Extra for the connection state intents of the individual profiles.
-     *
-     * This extra represents the current connection state of the profile of the
-     * Bluetooth device.
-     */
-    @SuppressLint("ActionValue")
-    String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
-
-    /**
-     * Extra for the connection state intents of the individual profiles.
-     *
-     * This extra represents the previous connection state of the profile of the
-     * Bluetooth device.
-     */
-    @SuppressLint("ActionValue")
-    String EXTRA_PREVIOUS_STATE =
-            "android.bluetooth.profile.extra.PREVIOUS_STATE";
-
-    /** The profile is in disconnected state */
-    int STATE_DISCONNECTED = 0;
-    /** The profile is in connecting state */
-    int STATE_CONNECTING = 1;
-    /** The profile is in connected state */
-    int STATE_CONNECTED = 2;
-    /** The profile is in disconnecting state */
-    int STATE_DISCONNECTING = 3;
-
-    /** @hide */
-    @IntDef({
-            STATE_DISCONNECTED,
-            STATE_CONNECTING,
-            STATE_CONNECTED,
-            STATE_DISCONNECTING,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface BtProfileState {}
-
-    /**
-     * Headset and Handsfree profile
-     */
-    int HEADSET = 1;
-
-    /**
-     * A2DP profile.
-     */
-    int A2DP = 2;
-
-    /**
-     * Health Profile
-     *
-     * @deprecated Health Device Profile (HDP) and MCAP protocol are no longer used. New
-     * apps should use Bluetooth Low Energy based solutions such as {@link BluetoothGatt},
-     * {@link BluetoothAdapter#listenUsingL2capChannel()}, or
-     * {@link BluetoothDevice#createL2capChannel(int)}
-     */
-    @Deprecated
-    int HEALTH = 3;
-
-    /**
-     * HID Host
-     *
-     * @hide
-     */
-    int HID_HOST = 4;
-
-    /**
-     * PAN Profile
-     *
-     * @hide
-     */
-    @SystemApi
-    int PAN = 5;
-
-    /**
-     * PBAP
-     *
-     * @hide
-     */
-    int PBAP = 6;
-
-    /**
-     * GATT
-     */
-    int GATT = 7;
-
-    /**
-     * GATT_SERVER
-     */
-    int GATT_SERVER = 8;
-
-    /**
-     * MAP Profile
-     *
-     * @hide
-     */
-    int MAP = 9;
-
-    /*
-     * SAP Profile
-     * @hide
-     */
-    int SAP = 10;
-
-    /**
-     * A2DP Sink Profile
-     *
-     * @hide
-     */
-    @SystemApi
-    int A2DP_SINK = 11;
-
-    /**
-     * AVRCP Controller Profile
-     *
-     * @hide
-     */
-    @SystemApi
-    int AVRCP_CONTROLLER = 12;
-
-    /**
-     * AVRCP Target Profile
-     *
-     * @hide
-     */
-    int AVRCP = 13;
-
-    /**
-     * Headset Client - HFP HF Role
-     *
-     * @hide
-     */
-    @SystemApi
-    int HEADSET_CLIENT = 16;
-
-    /**
-     * PBAP Client
-     *
-     * @hide
-     */
-    @SystemApi
-    int PBAP_CLIENT = 17;
-
-    /**
-     * MAP Messaging Client Equipment (MCE)
-     *
-     * @hide
-     */
-    @SystemApi
-    int MAP_CLIENT = 18;
-
-    /**
-     * HID Device
-     */
-    int HID_DEVICE = 19;
-
-    /**
-     * Object Push Profile (OPP)
-     *
-     * @hide
-     */
-    int OPP = 20;
-
-    /**
-     * Hearing Aid Device
-     *
-     */
-    int HEARING_AID = 21;
-
-    /**
-     * LE Audio Device
-     *
-     */
-    int LE_AUDIO = 22;
-
-    /**
-     * Volume Control profile
-     *
-     * @hide
-     */
-    @SystemApi
-    int VOLUME_CONTROL = 23;
-
-    /**
-     * @hide
-     * Media Control Profile server
-     *
-     */
-    int MCP_SERVER = 24;
-
-    /**
-     * Coordinated Set Identification Profile set coordinator
-     *
-     */
-    int CSIP_SET_COORDINATOR = 25;
-
-    /**
-     * LE Audio Broadcast Source
-     *
-     * @hide
-     */
-    int LE_AUDIO_BROADCAST = 26;
-
-    /**
-     * @hide
-     * Telephone Bearer Service from Call Control Profile
-     *
-     */
-    int LE_CALL_CONTROL = 27;
-
-    /**
-     * 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 = 27;
-
-    /**
-     * Default priority for devices that we try to auto-connect to and
-     * and allow incoming connections for the profile
-     *
-     * @hide
-     **/
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    int PRIORITY_AUTO_CONNECT = 1000;
-
-    /**
-     * Default priority for devices that allow incoming
-     * and outgoing connections for the profile
-     *
-     * @hide
-     * @deprecated Replaced with {@link #CONNECTION_POLICY_ALLOWED}
-     **/
-    @Deprecated
-    @SystemApi
-    int PRIORITY_ON = 100;
-
-    /**
-     * Default priority for devices that does not allow incoming
-     * connections and outgoing connections for the profile.
-     *
-     * @hide
-     * @deprecated Replaced with {@link #CONNECTION_POLICY_FORBIDDEN}
-     **/
-    @Deprecated
-    @SystemApi
-    int PRIORITY_OFF = 0;
-
-    /**
-     * Default priority when not set or when the device is unpaired
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    int PRIORITY_UNDEFINED = -1;
-
-    /** @hide */
-    @IntDef(prefix = "CONNECTION_POLICY_", value = {CONNECTION_POLICY_ALLOWED,
-            CONNECTION_POLICY_FORBIDDEN, CONNECTION_POLICY_UNKNOWN})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ConnectionPolicy{}
-
-    /**
-     * Default connection policy for devices that allow incoming and outgoing connections
-     * for the profile
-     *
-     * @hide
-     **/
-    @SystemApi
-    int CONNECTION_POLICY_ALLOWED = 100;
-
-    /**
-     * Default connection policy for devices that do not allow incoming or outgoing connections
-     * for the profile.
-     *
-     * @hide
-     **/
-    @SystemApi
-    int CONNECTION_POLICY_FORBIDDEN = 0;
-
-    /**
-     * Default connection policy when not set or when the device is unpaired
-     *
-     * @hide
-     */
-    @SystemApi
-    int CONNECTION_POLICY_UNKNOWN = -1;
-
-    /**
-     * Get connected devices for this specific profile.
-     *
-     * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
-     *
-     * @return List of devices. The list will be empty on error.
-     */
-    public List<BluetoothDevice> getConnectedDevices();
-
-    /**
-     * Get a list of devices that match any of the given connection
-     * states.
-     *
-     * <p> If none of the devices match any of the given states,
-     * an empty list will be returned.
-     *
-     * @param states Array of states. States can be one of {@link #STATE_CONNECTED}, {@link
-     * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
-     * @return List of devices. The list will be empty on error.
-     */
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states);
-
-    /**
-     * Get the current connection state of the profile
-     *
-     * @param device Remote bluetooth device.
-     * @return State of the profile connection. One of {@link #STATE_CONNECTED}, {@link
-     * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
-     */
-    @BtProfileState int getConnectionState(BluetoothDevice device);
-
-    /**
-     * An interface for notifying BluetoothProfile IPC clients when they have
-     * been connected or disconnected to the service.
-     */
-    public interface ServiceListener {
-        /**
-         * Called to notify the client when the proxy object has been
-         * connected to the service.
-         *
-         * @param profile - One of {@link #HEADSET} or {@link #A2DP}
-         * @param proxy - One of {@link BluetoothHeadset} or {@link BluetoothA2dp}
-         */
-        @RequiresNoPermission
-        public void onServiceConnected(int profile, BluetoothProfile proxy);
-
-        /**
-         * Called to notify the client that this proxy object has been
-         * disconnected from the service.
-         *
-         * @param profile - One of {@link #HEADSET} or {@link #A2DP}
-         */
-        @RequiresNoPermission
-        public void onServiceDisconnected(int profile);
-    }
-
-    /**
-     * Convert an integer value of connection state into human readable string
-     *
-     * @param connectionState - One of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
-     * {@link #STATE_CONNECTED}, or {@link #STATE_DISCONNECTED}
-     * @return a string representation of the connection state, STATE_UNKNOWN if the state
-     * is not defined
-     * @hide
-     */
-    static String getConnectionStateName(int connectionState) {
-        switch (connectionState) {
-            case STATE_DISCONNECTED:
-                return "STATE_DISCONNECTED";
-            case STATE_CONNECTING:
-                return "STATE_CONNECTING";
-            case STATE_CONNECTED:
-                return "STATE_CONNECTED";
-            case STATE_DISCONNECTING:
-                return "STATE_DISCONNECTING";
-            default:
-                return "STATE_UNKNOWN";
-        }
-    }
-
-    /**
-     * Convert an integer value of profile ID into human readable string
-     *
-     * @param profile profile ID
-     * @return profile name as String, UNKOWN_PROFILE if the profile ID is not defined.
-     * @hide
-     */
-    static String getProfileName(int profile) {
-        switch(profile) {
-            case HEADSET:
-                return "HEADSET";
-            case A2DP:
-                return "A2DP";
-            case HID_HOST:
-                return "HID_HOST";
-            case PAN:
-                return "PAN";
-            case PBAP:
-                return "PBAP";
-            case GATT:
-                return "GATT";
-            case GATT_SERVER:
-                return "GATT_SERVER";
-            case MAP:
-                return "MAP";
-            case SAP:
-                return "SAP";
-            case A2DP_SINK:
-                return "A2DP_SINK";
-            case AVRCP_CONTROLLER:
-                return "AVRCP_CONTROLLER";
-            case AVRCP:
-                return "AVRCP";
-            case HEADSET_CLIENT:
-                return "HEADSET_CLIENT";
-            case PBAP_CLIENT:
-                return "PBAP_CLIENT";
-            case MAP_CLIENT:
-                return "MAP_CLIENT";
-            case HID_DEVICE:
-                return "HID_DEVICE";
-            case OPP:
-                return "OPP";
-            case HEARING_AID:
-                return "HEARING_AID";
-            case LE_AUDIO:
-                return "LE_AUDIO";
-            default:
-                return "UNKNOWN_PROFILE";
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
deleted file mode 100644
index 79373f1a..0000000
--- a/core/java/android/bluetooth/BluetoothProfileConnector.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import java.util.List;
-/**
- * Connector for Bluetooth profile proxies to bind manager service and
- * profile services
- * @param <T> The Bluetooth profile interface for this connection.
- * @hide
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public abstract class BluetoothProfileConnector<T> {
-    private final CloseGuard mCloseGuard = new CloseGuard();
-    private final int mProfileId;
-    private BluetoothProfile.ServiceListener mServiceListener;
-    private final BluetoothProfile mProfileProxy;
-    private Context mContext;
-    private final String mProfileName;
-    private final String mServiceName;
-    private volatile T mService;
-
-    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
-            new IBluetoothStateChangeCallback.Stub() {
-        public void onBluetoothStateChange(boolean up) {
-            if (up) {
-                doBind();
-            } else {
-                doUnbind();
-            }
-        }
-    };
-
-    private @Nullable ComponentName resolveSystemService(@NonNull Intent intent,
-            @NonNull PackageManager pm, @PackageManager.ComponentInfoFlags int flags) {
-        List<ResolveInfo> results = pm.queryIntentServices(intent, flags);
-        if (results == null) {
-            return null;
-        }
-        ComponentName comp = null;
-        for (int i = 0; i < results.size(); i++) {
-            ResolveInfo ri = results.get(i);
-            if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-                continue;
-            }
-            ComponentName foundComp = new ComponentName(ri.serviceInfo.applicationInfo.packageName,
-                    ri.serviceInfo.name);
-            if (comp != null) {
-                throw new IllegalStateException("Multiple system services handle " + intent
-                        + ": " + comp + ", " + foundComp);
-            }
-            comp = foundComp;
-        }
-        return comp;
-    }
-
-    private final ServiceConnection mConnection = new ServiceConnection() {
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            logDebug("Proxy object connected");
-            mService = getServiceInterface(service);
-
-            if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(mProfileId, mProfileProxy);
-            }
-        }
-
-        public void onServiceDisconnected(ComponentName className) {
-            logDebug("Proxy object disconnected");
-            doUnbind();
-            if (mServiceListener != null) {
-                mServiceListener.onServiceDisconnected(mProfileId);
-            }
-        }
-    };
-
-    BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName,
-            String serviceName) {
-        mProfileId = profileId;
-        mProfileProxy = profile;
-        mProfileName = profileName;
-        mServiceName = serviceName;
-    }
-
-    /** {@hide} */
-    @Override
-    public void finalize() {
-        mCloseGuard.warnIfOpen();
-        doUnbind();
-    }
-
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    private boolean doBind() {
-        synchronized (mConnection) {
-            if (mService == null) {
-                logDebug("Binding service...");
-                mCloseGuard.open("doUnbind");
-                try {
-                    Intent intent = new Intent(mServiceName);
-                    ComponentName comp = resolveSystemService(intent, mContext.getPackageManager(),
-                            0);
-                    intent.setComponent(comp);
-                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
-                            UserHandle.CURRENT)) {
-                        logError("Could not bind to Bluetooth Service with " + intent);
-                        return false;
-                    }
-                } catch (SecurityException se) {
-                    logError("Failed to bind service. " + se);
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private void doUnbind() {
-        synchronized (mConnection) {
-            if (mService != null) {
-                logDebug("Unbinding service...");
-                mCloseGuard.close();
-                try {
-                    mContext.unbindService(mConnection);
-                } catch (IllegalArgumentException ie) {
-                    logError("Unable to unbind service: " + ie);
-                } finally {
-                    mService = null;
-                }
-            }
-        }
-    }
-
-    void connect(Context context, BluetoothProfile.ServiceListener listener) {
-        mContext = context;
-        mServiceListener = listener;
-        IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
-
-        // Preserve legacy compatibility where apps were depending on
-        // registerStateChangeCallback() performing a permissions check which
-        // has been relaxed in modern platform versions
-        if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
-                && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
-                        != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Need BLUETOOTH permission");
-        }
-
-        if (mgr != null) {
-            try {
-                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
-            } catch (RemoteException re) {
-                logError("Failed to register state change callback. " + re);
-            }
-        }
-        doBind();
-    }
-
-    void disconnect() {
-        mServiceListener = null;
-        IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
-        if (mgr != null) {
-            try {
-                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
-            } catch (RemoteException re) {
-                logError("Failed to unregister state change callback" + re);
-            }
-        }
-        doUnbind();
-    }
-
-    T getService() {
-        return mService;
-    }
-
-    /**
-     * This abstract function is used to implement method to get the
-     * connected Bluetooth service interface.
-     * @param service the connected binder service.
-     * @return T the binder interface of {@code service}.
-     * @hide
-     */
-    public abstract T getServiceInterface(IBinder service);
-
-    private void logDebug(String log) {
-        Log.d(mProfileName, log);
-    }
-
-    private void logError(String log) {
-        Log.e(mProfileName, log);
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
deleted file mode 100644
index 808fa39..0000000
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the APIs to control the Bluetooth SIM
- * Access Profile (SAP).
- *
- * <p>BluetoothSap is a proxy object for controlling the Bluetooth
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothSap proxy object.
- *
- * <p>Each method is protected with its appropriate permission.
- *
- * @hide
- */
-public final class BluetoothSap implements BluetoothProfile {
-
-    private static final String TAG = "BluetoothSap";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Intent used to broadcast the change in connection state of the profile.
-     *
-     * <p>This intent will have 4 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}.
-     *
-     * @hide
-     */
-    @RequiresLegacyBluetoothPermission
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
-
-    /**
-     * There was an error trying to obtain the state.
-     *
-     * @hide
-     */
-    public static final int STATE_ERROR = -1;
-
-    /**
-     * Connection state change succceeded.
-     *
-     * @hide
-     */
-    public static final int RESULT_SUCCESS = 1;
-
-    /**
-     * Connection canceled before completion.
-     *
-     * @hide
-     */
-    public static final int RESULT_CANCELED = 2;
-
-    private final BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.SAP,
-                    "BluetoothSap", IBluetoothSap.class.getName()) {
-                @Override
-                public IBluetoothSap getServiceInterface(IBinder service) {
-                    return IBluetoothSap.Stub.asInterface(service);
-                }
-    };
-
-    /**
-     * Create a BluetoothSap proxy object.
-     */
-    /* package */ BluetoothSap(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        if (DBG) Log.d(TAG, "Create BluetoothSap proxy object");
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /**
-     * Close the connection to the backing service.
-     * Other public functions of BluetoothSap will return default error
-     * results once close() has been called. Multiple invocations of close()
-     * are ok.
-     *
-     * @hide
-     */
-    public synchronized void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothSap getService() {
-        return mProfileConnector.getService();
-    }
-
-    /**
-     * Get the current state of the BluetoothSap service.
-     *
-     * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not
-     * connected to the Sap service.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public int getState() {
-        if (VDBG) log("getState()");
-        final IBluetoothSap service = getService();
-        final int defaultValue = BluetoothSap.STATE_ERROR;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getState(mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the currently connected remote Bluetooth device (PCE).
-     *
-     * @return The remote Bluetooth device, or null if not in connected or connecting state, or if
-     * this proxy object is not connected to the Sap service.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public BluetoothDevice getClient() {
-        if (VDBG) log("getClient()");
-        final IBluetoothSap service = getService();
-        final BluetoothDevice defaultValue = null;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<BluetoothDevice> recv =
-                        new SynchronousResultReceiver();
-                service.getClient(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Returns true if the specified Bluetooth device is connected.
-     * Returns false if not connected, or if this proxy object is not
-     * currently connected to the Sap service.
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean isConnected(BluetoothDevice device) {
-        if (VDBG) log("isConnected(" + device + ")");
-        final IBluetoothSap service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.isConnected(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Initiate connection. Initiation of outgoing connections is not
-     * supported for SAP server.
-     *
-     * @hide
-     */
-    @RequiresNoPermission
-    public boolean connect(BluetoothDevice device) {
-        if (DBG) log("connect(" + device + ")" + "not supported for SAPS");
-        return false;
-    }
-
-    /**
-     * Initiate disconnect.
-     *
-     * @param device Remote Bluetooth Device
-     * @return false on error, true otherwise
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public boolean disconnect(BluetoothDevice device) {
-        if (DBG) log("disconnect(" + device + ")");
-        final IBluetoothSap service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.disconnect(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of connected devices. Currently at most one.
-     *
-     * @return list of connected devices
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
-        final IBluetoothSap service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of devices matching specified states. Currently at most one.
-     *
-     * @return list of matching devices
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
-        final IBluetoothSap service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get connection state of device
-     *
-     * @return device connection state
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getConnectionState(" + device + ")");
-        final IBluetoothSap service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Set priority of the profile
-     *
-     * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
-     *
-     * @param device Paired bluetooth device
-     * @param priority
-     * @return true if priority is set, false on error
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setPriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothSap service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the priority of the profile.
-     *
-     * <p> The priority can be any of:
-     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * @param device Bluetooth device
-     * @return priority of the device
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public int getPriority(BluetoothDevice device) {
-        if (VDBG) log("getPriority(" + device + ")");
-        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
-    }
-
-    /**
-     * 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
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothSap service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    private static void log(String msg) {
-        Log.d(TAG, msg);
-    }
-
-    private boolean isEnabled() {
-        return mAdapter.isEnabled();
-    }
-
-    private static boolean isValidDevice(BluetoothDevice device) {
-        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
deleted file mode 100644
index bb4e354..0000000
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.SuppressLint;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * A listening Bluetooth socket.
- *
- * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
- * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
- * side, use a {@link BluetoothServerSocket} to create a listening server
- * socket. When a connection is accepted by the {@link BluetoothServerSocket},
- * it will return a new {@link BluetoothSocket} to manage the connection.
- * On the client side, use a single {@link BluetoothSocket} to both initiate
- * an outgoing connection and to manage the connection.
- *
- * <p>For Bluetooth BR/EDR, the most common type of socket is RFCOMM, which is the type supported by
- * the Android APIs. RFCOMM is a connection-oriented, streaming transport over Bluetooth BR/EDR. It
- * is also known as the Serial Port Profile (SPP). To create a listening
- * {@link BluetoothServerSocket} that's ready for incoming Bluetooth BR/EDR connections, use {@link
- * BluetoothAdapter#listenUsingRfcommWithServiceRecord
- * BluetoothAdapter.listenUsingRfcommWithServiceRecord()}.
- *
- * <p>For Bluetooth LE, the socket uses LE Connection-oriented Channel (CoC). LE CoC is a
- * connection-oriented, streaming transport over Bluetooth LE and has a credit-based flow control.
- * Correspondingly, use {@link BluetoothAdapter#listenUsingL2capChannel
- * BluetoothAdapter.listenUsingL2capChannel()} to create a listening {@link BluetoothServerSocket}
- * that's ready for incoming Bluetooth LE CoC connections. For LE CoC, you can use {@link #getPsm()}
- * to get the protocol/service multiplexer (PSM) value that the peer needs to use to connect to your
- * socket.
- *
- * <p> After the listening {@link BluetoothServerSocket} is created, call {@link #accept()} to
- * listen for incoming connection requests. This call will block until a connection is established,
- * at which point, it will return a {@link BluetoothSocket} to manage the connection. Once the
- * {@link BluetoothSocket} is acquired, it's a good idea to call {@link #close()} on the {@link
- * BluetoothServerSocket} when it's no longer needed for accepting
- * connections. Closing the {@link BluetoothServerSocket} will <em>not</em> close the returned
- * {@link BluetoothSocket}.
- *
- * <p>{@link BluetoothServerSocket} is thread
- * safe. In particular, {@link #close} will always immediately abort ongoing
- * operations and close the server socket.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using Bluetooth, read the
- * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
- * </div>
- *
- * {@see BluetoothSocket}
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class BluetoothServerSocket implements Closeable {
-
-    private static final String TAG = "BluetoothServerSocket";
-    private static final boolean DBG = false;
-    @UnsupportedAppUsage(publicAlternatives = "Use public {@link BluetoothServerSocket} API "
-            + "instead.")
-    /*package*/ final BluetoothSocket mSocket;
-    private Handler mHandler;
-    private int mMessage;
-    private int mChannel;
-
-    /**
-     * Construct a socket for incoming connections.
-     *
-     * @param type type of socket
-     * @param auth require the remote device to be authenticated
-     * @param encrypt require the connection to be encrypted
-     * @param port remote port
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * privileges
-     */
-    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
-            throws IOException {
-        mChannel = port;
-        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
-        if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            mSocket.setExcludeSdp(true);
-        }
-    }
-
-    /**
-     * Construct a socket for incoming connections.
-     *
-     * @param type type of socket
-     * @param auth require the remote device to be authenticated
-     * @param encrypt require the connection to be encrypted
-     * @param port remote port
-     * @param mitm enforce person-in-the-middle protection for authentication.
-     * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * privileges
-     */
-    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port,
-            boolean mitm, boolean min16DigitPin)
-            throws IOException {
-        mChannel = port;
-        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null, mitm,
-                min16DigitPin);
-        if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            mSocket.setExcludeSdp(true);
-        }
-    }
-
-    /**
-     * Construct a socket for incoming connections.
-     *
-     * @param type type of socket
-     * @param auth require the remote device to be authenticated
-     * @param encrypt require the connection to be encrypted
-     * @param uuid uuid
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * privileges
-     */
-    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
-            throws IOException {
-        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
-        // TODO: This is the same as mChannel = -1 - is this intentional?
-        mChannel = mSocket.getPort();
-    }
-
-
-    /**
-     * Block until a connection is established.
-     * <p>Returns a connected {@link BluetoothSocket} on successful connection.
-     * <p>Once this call returns, it can be called again to accept subsequent
-     * incoming connections.
-     * <p>{@link #close} can be used to abort this call from another thread.
-     *
-     * @return a connected {@link BluetoothSocket}
-     * @throws IOException on error, for example this call was aborted, or timeout
-     */
-    public BluetoothSocket accept() throws IOException {
-        return accept(-1);
-    }
-
-    /**
-     * Block until a connection is established, with timeout.
-     * <p>Returns a connected {@link BluetoothSocket} on successful connection.
-     * <p>Once this call returns, it can be called again to accept subsequent
-     * incoming connections.
-     * <p>{@link #close} can be used to abort this call from another thread.
-     *
-     * @return a connected {@link BluetoothSocket}
-     * @throws IOException on error, for example this call was aborted, or timeout
-     */
-    public BluetoothSocket accept(int timeout) throws IOException {
-        return mSocket.accept(timeout);
-    }
-
-    /**
-     * Immediately close this socket, and release all associated resources.
-     * <p>Causes blocked calls on this socket in other threads to immediately
-     * throw an IOException.
-     * <p>Closing the {@link BluetoothServerSocket} will <em>not</em>
-     * close any {@link BluetoothSocket} received from {@link #accept()}.
-     */
-    public void close() throws IOException {
-        if (DBG) Log.d(TAG, "BluetoothServerSocket:close() called. mChannel=" + mChannel);
-        synchronized (this) {
-            if (mHandler != null) {
-                mHandler.obtainMessage(mMessage).sendToTarget();
-            }
-        }
-        mSocket.close();
-    }
-
-    /*package*/
-    synchronized void setCloseHandler(Handler handler, int message) {
-        mHandler = handler;
-        mMessage = message;
-    }
-
-    /*package*/ void setServiceName(String serviceName) {
-        mSocket.setServiceName(serviceName);
-    }
-
-    /**
-     * Returns the channel on which this socket is bound.
-     *
-     * @hide
-     */
-    public int getChannel() {
-        return mChannel;
-    }
-
-    /**
-     * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
-     * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
-     * {@link BluetoothAdapter#listenUsingL2capChannel()} or {@link
-     * BluetoothAdapter#listenUsingInsecureL2capChannel()}. The returned value is undefined if this
-     * method is called on non-L2CAP server sockets.
-     *
-     * @return the assigned PSM or LE_PSM value depending on transport
-     */
-    public int getPsm() {
-        return mChannel;
-    }
-
-    /**
-     * Sets the channel on which future sockets are bound.
-     * Currently used only when a channel is auto generated.
-     */
-    /*package*/ void setChannel(int newChannel) {
-        /* TODO: From a design/architecture perspective this is wrong.
-         *       The bind operation should be conducted through this class
-         *       and the resulting port should be kept in mChannel, and
-         *       not set from BluetoothAdapter. */
-        if (mSocket != null) {
-            if (mSocket.getPort() != newChannel) {
-                Log.w(TAG, "The port set is different that the underlying port. mSocket.getPort(): "
-                        + mSocket.getPort() + " requested newChannel: " + newChannel);
-            }
-        }
-        mChannel = newChannel;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("ServerSocket: Type: ");
-        switch (mSocket.getConnectionType()) {
-            case BluetoothSocket.TYPE_RFCOMM: {
-                sb.append("TYPE_RFCOMM");
-                break;
-            }
-            case BluetoothSocket.TYPE_L2CAP: {
-                sb.append("TYPE_L2CAP");
-                break;
-            }
-            case BluetoothSocket.TYPE_L2CAP_LE: {
-                sb.append("TYPE_L2CAP_LE");
-                break;
-            }
-            case BluetoothSocket.TYPE_SCO: {
-                sb.append("TYPE_SCO");
-                break;
-            }
-        }
-        sb.append(" Channel: ").append(mChannel);
-        return sb.toString();
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
deleted file mode 100644
index db5b751..0000000
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.net.LocalSocket;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.Closeable;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.UUID;
-
-/**
- * A connected or connecting Bluetooth socket.
- *
- * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
- * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
- * side, use a {@link BluetoothServerSocket} to create a listening server
- * socket. When a connection is accepted by the {@link BluetoothServerSocket},
- * it will return a new {@link BluetoothSocket} to manage the connection.
- * On the client side, use a single {@link BluetoothSocket} to both initiate
- * an outgoing connection and to manage the connection.
- *
- * <p>The most common type of Bluetooth socket is RFCOMM, which is the type
- * supported by the Android APIs. RFCOMM is a connection-oriented, streaming
- * transport over Bluetooth. It is also known as the Serial Port Profile (SPP).
- *
- * <p>To create a {@link BluetoothSocket} for connecting to a known device, use
- * {@link BluetoothDevice#createRfcommSocketToServiceRecord
- * BluetoothDevice.createRfcommSocketToServiceRecord()}.
- * Then call {@link #connect()} to attempt a connection to the remote device.
- * This call will block until a connection is established or the connection
- * fails.
- *
- * <p>To create a {@link BluetoothSocket} as a server (or "host"), see the
- * {@link BluetoothServerSocket} documentation.
- *
- * <p>Once the socket is connected, whether initiated as a client or accepted
- * as a server, open the IO streams by calling {@link #getInputStream} and
- * {@link #getOutputStream} in order to retrieve {@link java.io.InputStream}
- * and {@link java.io.OutputStream} objects, respectively, which are
- * automatically connected to the socket.
- *
- * <p>{@link BluetoothSocket} is thread
- * safe. In particular, {@link #close} will always immediately abort ongoing
- * operations and close the socket.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using Bluetooth, read the
- * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
- * </div>
- *
- * {@see BluetoothServerSocket}
- * {@see java.io.InputStream}
- * {@see java.io.OutputStream}
- */
-public final class BluetoothSocket implements Closeable {
-    private static final String TAG = "BluetoothSocket";
-    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
-
-    /** @hide */
-    public static final int MAX_RFCOMM_CHANNEL = 30;
-    /*package*/ static final int MAX_L2CAP_PACKAGE_SIZE = 0xFFFF;
-
-    /** RFCOMM socket */
-    public static final int TYPE_RFCOMM = 1;
-
-    /** SCO socket */
-    public static final int TYPE_SCO = 2;
-
-    /** L2CAP socket */
-    public static final int TYPE_L2CAP = 3;
-
-    /** L2CAP socket on BR/EDR transport
-     * @hide
-     */
-    public static final int TYPE_L2CAP_BREDR = TYPE_L2CAP;
-
-    /** L2CAP socket on LE transport
-     * @hide
-     */
-    public static final int TYPE_L2CAP_LE = 4;
-
-    /*package*/ static final int EBADFD = 77;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    /*package*/ static final int EADDRINUSE = 98;
-
-    /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
-    /*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
-    /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2;
-    /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3;
-    /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4;
-
-    private final int mType;  /* one of TYPE_RFCOMM etc */
-    private BluetoothDevice mDevice;    /* remote device */
-    private String mAddress;    /* remote address */
-    private final boolean mAuth;
-    private final boolean mEncrypt;
-    private final BluetoothInputStream mInputStream;
-    private final BluetoothOutputStream mOutputStream;
-    private final ParcelUuid mUuid;
-    /** when true no SPP SDP record will be created */
-    private boolean mExcludeSdp = false;
-    /** when true Person-in-the-middle protection will be enabled */
-    private boolean mAuthMitm = false;
-    /** Minimum 16 digit pin for sec mode 2 connections */
-    private boolean mMin16DigitPin = false;
-    @UnsupportedAppUsage(publicAlternatives = "Use {@link BluetoothSocket} public API instead.")
-    private ParcelFileDescriptor mPfd;
-    @UnsupportedAppUsage
-    private LocalSocket mSocket;
-    private InputStream mSocketIS;
-    private OutputStream mSocketOS;
-    @UnsupportedAppUsage
-    private int mPort;  /* RFCOMM channel or L2CAP psm */
-    private int mFd;
-    private String mServiceName;
-    private static final int PROXY_CONNECTION_TIMEOUT = 5000;
-
-    private static final int SOCK_SIGNAL_SIZE = 20;
-
-    private ByteBuffer mL2capBuffer = null;
-    private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer.
-    private int mMaxRxPacketSize = 0; // The l2cap maximum packet size that can be received.
-
-    private enum SocketState {
-        INIT,
-        CONNECTED,
-        LISTENING,
-        CLOSED,
-    }
-
-    /** prevents all native calls after destroyNative() */
-    private volatile SocketState mSocketState;
-
-    /** protects mSocketState */
-    //private final ReentrantReadWriteLock mLock;
-
-    /**
-     * Construct a BluetoothSocket.
-     *
-     * @param type type of socket
-     * @param fd fd to use for connected socket, or -1 for a new socket
-     * @param auth require the remote device to be authenticated
-     * @param encrypt require the connection to be encrypted
-     * @param device remote device that this socket can connect to
-     * @param port remote port
-     * @param uuid SDP uuid
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * privileges
-     */
-    /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
-            BluetoothDevice device, int port, ParcelUuid uuid) throws IOException {
-        this(type, fd, auth, encrypt, device, port, uuid, false, false);
-    }
-
-    /**
-     * Construct a BluetoothSocket.
-     *
-     * @param type type of socket
-     * @param fd fd to use for connected socket, or -1 for a new socket
-     * @param auth require the remote device to be authenticated
-     * @param encrypt require the connection to be encrypted
-     * @param device remote device that this socket can connect to
-     * @param port remote port
-     * @param uuid SDP uuid
-     * @param mitm enforce person-in-the-middle protection.
-     * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * privileges
-     */
-    /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
-            BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin)
-            throws IOException {
-        if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type);
-        if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1
-                && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            if (port < 1 || port > MAX_RFCOMM_CHANNEL) {
-                throw new IOException("Invalid RFCOMM channel: " + port);
-            }
-        }
-        if (uuid != null) {
-            mUuid = uuid;
-        } else {
-            mUuid = new ParcelUuid(new UUID(0, 0));
-        }
-        mType = type;
-        mAuth = auth;
-        mAuthMitm = mitm;
-        mMin16DigitPin = min16DigitPin;
-        mEncrypt = encrypt;
-        mDevice = device;
-        mPort = port;
-        mFd = fd;
-
-        mSocketState = SocketState.INIT;
-
-        if (device == null) {
-            // Server socket
-            mAddress = BluetoothAdapter.getDefaultAdapter().getAddress();
-        } else {
-            // Remote socket
-            mAddress = device.getAddress();
-        }
-        mInputStream = new BluetoothInputStream(this);
-        mOutputStream = new BluetoothOutputStream(this);
-    }
-
-    private BluetoothSocket(BluetoothSocket s) {
-        if (VDBG) Log.d(TAG, "Creating new Private BluetoothSocket of type: " + s.mType);
-        mUuid = s.mUuid;
-        mType = s.mType;
-        mAuth = s.mAuth;
-        mEncrypt = s.mEncrypt;
-        mPort = s.mPort;
-        mInputStream = new BluetoothInputStream(this);
-        mOutputStream = new BluetoothOutputStream(this);
-        mMaxRxPacketSize = s.mMaxRxPacketSize;
-        mMaxTxPacketSize = s.mMaxTxPacketSize;
-
-        mServiceName = s.mServiceName;
-        mExcludeSdp = s.mExcludeSdp;
-        mAuthMitm = s.mAuthMitm;
-        mMin16DigitPin = s.mMin16DigitPin;
-    }
-
-    private BluetoothSocket acceptSocket(String remoteAddr) throws IOException {
-        BluetoothSocket as = new BluetoothSocket(this);
-        as.mSocketState = SocketState.CONNECTED;
-        FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
-        if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds));
-        if (fds == null || fds.length != 1) {
-            Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds));
-            as.close();
-            throw new IOException("bt socket acept failed");
-        }
-
-        as.mPfd = ParcelFileDescriptor.dup(fds[0]);
-        as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
-        as.mSocketIS = as.mSocket.getInputStream();
-        as.mSocketOS = as.mSocket.getOutputStream();
-        as.mAddress = remoteAddr;
-        as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr);
-        return as;
-    }
-
-    /**
-     * Construct a BluetoothSocket from address. Used by native code.
-     *
-     * @param type type of socket
-     * @param fd fd to use for connected socket, or -1 for a new socket
-     * @param auth require the remote device to be authenticated
-     * @param encrypt require the connection to be encrypted
-     * @param address remote device that this socket can connect to
-     * @param port remote port
-     * @throws IOException On error, for example Bluetooth not available, or insufficient
-     * privileges
-     */
-    private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
-            int port) throws IOException {
-        this(type, fd, auth, encrypt, new BluetoothDevice(address), port, null, false, false);
-    }
-
-    /** @hide */
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private int getSecurityFlags() {
-        int flags = 0;
-        if (mAuth) {
-            flags |= SEC_FLAG_AUTH;
-        }
-        if (mEncrypt) {
-            flags |= SEC_FLAG_ENCRYPT;
-        }
-        if (mExcludeSdp) {
-            flags |= BTSOCK_FLAG_NO_SDP;
-        }
-        if (mAuthMitm) {
-            flags |= SEC_FLAG_AUTH_MITM;
-        }
-        if (mMin16DigitPin) {
-            flags |= SEC_FLAG_AUTH_16_DIGIT;
-        }
-        return flags;
-    }
-
-    /**
-     * Get the remote device this socket is connecting, or connected, to.
-     *
-     * @return remote device
-     */
-    @RequiresNoPermission
-    public BluetoothDevice getRemoteDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Get the input stream associated with this socket.
-     * <p>The input stream will be returned even if the socket is not yet
-     * connected, but operations on that stream will throw IOException until
-     * the associated socket is connected.
-     *
-     * @return InputStream
-     */
-    @RequiresNoPermission
-    public InputStream getInputStream() throws IOException {
-        return mInputStream;
-    }
-
-    /**
-     * Get the output stream associated with this socket.
-     * <p>The output stream will be returned even if the socket is not yet
-     * connected, but operations on that stream will throw IOException until
-     * the associated socket is connected.
-     *
-     * @return OutputStream
-     */
-    @RequiresNoPermission
-    public OutputStream getOutputStream() throws IOException {
-        return mOutputStream;
-    }
-
-    /**
-     * Get the connection status of this socket, ie, whether there is an active connection with
-     * remote device.
-     *
-     * @return true if connected false if not connected
-     */
-    @RequiresNoPermission
-    public boolean isConnected() {
-        return mSocketState == SocketState.CONNECTED;
-    }
-
-    /*package*/ void setServiceName(String name) {
-        mServiceName = name;
-    }
-
-    /**
-     * Attempt to connect to a remote device.
-     * <p>This method will block until a connection is made or the connection
-     * fails. If this method returns without an exception then this socket
-     * is now connected.
-     * <p>Creating new connections to
-     * remote Bluetooth devices should not be attempted while device discovery
-     * is in progress. Device discovery is a heavyweight procedure on the
-     * Bluetooth adapter and will significantly slow a device connection.
-     * Use {@link BluetoothAdapter#cancelDiscovery()} to cancel an ongoing
-     * discovery. Discovery is not managed by the Activity,
-     * but is run as a system service, so an application should always call
-     * {@link BluetoothAdapter#cancelDiscovery()} even if it
-     * did not directly request a discovery, just to be sure.
-     * <p>{@link #close} can be used to abort this call from another thread.
-     *
-     * @throws IOException on error, for example connection failure
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void connect() throws IOException {
-        if (mDevice == null) throw new IOException("Connect is called on null device");
-
-        try {
-            if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-            IBluetooth bluetoothProxy =
-                    BluetoothAdapter.getDefaultAdapter().getBluetoothService();
-            if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
-            mPfd = bluetoothProxy.getSocketManager().connectSocket(mDevice, mType,
-                    mUuid, mPort, getSecurityFlags());
-            synchronized (this) {
-                if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
-                if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
-                if (mPfd == null) throw new IOException("bt socket connect failed");
-                FileDescriptor fd = mPfd.getFileDescriptor();
-                mSocket = LocalSocket.createConnectedLocalSocket(fd);
-                mSocketIS = mSocket.getInputStream();
-                mSocketOS = mSocket.getOutputStream();
-            }
-            int channel = readInt(mSocketIS);
-            if (channel <= 0) {
-                throw new IOException("bt socket connect failed");
-            }
-            mPort = channel;
-            waitSocketSignal(mSocketIS);
-            synchronized (this) {
-                if (mSocketState == SocketState.CLOSED) {
-                    throw new IOException("bt socket closed");
-                }
-                mSocketState = SocketState.CONNECTED;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, Log.getStackTraceString(new Throwable()));
-            throw new IOException("unable to send RPC: " + e.getMessage());
-        }
-    }
-
-    /**
-     * Currently returns unix errno instead of throwing IOException,
-     * so that BluetoothAdapter can check the error code for EADDRINUSE
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    /*package*/ int bindListen() {
-        int ret;
-        if (mSocketState == SocketState.CLOSED) return EBADFD;
-        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
-        if (bluetoothProxy == null) {
-            Log.e(TAG, "bindListen fail, reason: bluetooth is off");
-            return -1;
-        }
-        try {
-            if (DBG) Log.d(TAG, "bindListen(): mPort=" + mPort + ", mType=" + mType);
-            mPfd = bluetoothProxy.getSocketManager().createSocketChannel(mType, mServiceName,
-                    mUuid, mPort, getSecurityFlags());
-        } catch (RemoteException e) {
-            Log.e(TAG, Log.getStackTraceString(new Throwable()));
-            return -1;
-        }
-
-        // read out port number
-        try {
-            synchronized (this) {
-                if (DBG) {
-                    Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
-                }
-                if (mSocketState != SocketState.INIT) return EBADFD;
-                if (mPfd == null) return -1;
-                FileDescriptor fd = mPfd.getFileDescriptor();
-                if (fd == null) {
-                    Log.e(TAG, "bindListen(), null file descriptor");
-                    return -1;
-                }
-
-                if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
-                mSocket = LocalSocket.createConnectedLocalSocket(fd);
-                if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
-                mSocketIS = mSocket.getInputStream();
-                mSocketOS = mSocket.getOutputStream();
-            }
-            if (DBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS);
-            int channel = readInt(mSocketIS);
-            synchronized (this) {
-                if (mSocketState == SocketState.INIT) {
-                    mSocketState = SocketState.LISTENING;
-                }
-            }
-            if (DBG) Log.d(TAG, "bindListen(): channel=" + channel + ", mPort=" + mPort);
-            if (mPort <= -1) {
-                mPort = channel;
-            } // else ASSERT(mPort == channel)
-            ret = 0;
-        } catch (IOException e) {
-            if (mPfd != null) {
-                try {
-                    mPfd.close();
-                } catch (IOException e1) {
-                    Log.e(TAG, "bindListen, close mPfd: " + e1);
-                }
-                mPfd = null;
-            }
-            Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
-            return -1;
-        }
-        return ret;
-    }
-
-    /*package*/ BluetoothSocket accept(int timeout) throws IOException {
-        BluetoothSocket acceptedSocket;
-        if (mSocketState != SocketState.LISTENING) {
-            throw new IOException("bt socket is not in listen state");
-        }
-        if (timeout > 0) {
-            Log.d(TAG, "accept() set timeout (ms):" + timeout);
-            mSocket.setSoTimeout(timeout);
-        }
-        String RemoteAddr = waitSocketSignal(mSocketIS);
-        if (timeout > 0) {
-            mSocket.setSoTimeout(0);
-        }
-        synchronized (this) {
-            if (mSocketState != SocketState.LISTENING) {
-                throw new IOException("bt socket is not in listen state");
-            }
-            acceptedSocket = acceptSocket(RemoteAddr);
-            //quick drop the reference of the file handle
-        }
-        return acceptedSocket;
-    }
-
-    /*package*/ int available() throws IOException {
-        if (VDBG) Log.d(TAG, "available: " + mSocketIS);
-        return mSocketIS.available();
-    }
-
-    /*package*/ int read(byte[] b, int offset, int length) throws IOException {
-        int ret = 0;
-        if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
-        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
-            int bytesToRead = length;
-            if (VDBG) {
-                Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length
-                        + "mL2capBuffer= " + mL2capBuffer);
-            }
-            if (mL2capBuffer == null) {
-                createL2capRxBuffer();
-            }
-            if (mL2capBuffer.remaining() == 0) {
-                if (VDBG) Log.v(TAG, "l2cap buffer empty, refilling...");
-                if (fillL2capRxBuffer() == -1) {
-                    return -1;
-                }
-            }
-            if (bytesToRead > mL2capBuffer.remaining()) {
-                bytesToRead = mL2capBuffer.remaining();
-            }
-            if (VDBG) {
-                Log.v(TAG, "get(): offset: " + offset
-                        + " bytesToRead: " + bytesToRead);
-            }
-            mL2capBuffer.get(b, offset, bytesToRead);
-            ret = bytesToRead;
-        } else {
-            if (VDBG) Log.v(TAG, "default: read(): offset: " + offset + " length:" + length);
-            ret = mSocketIS.read(b, offset, length);
-        }
-        if (ret < 0) {
-            throw new IOException("bt socket closed, read return: " + ret);
-        }
-        if (VDBG) Log.d(TAG, "read out:  " + mSocketIS + " ret: " + ret);
-        return ret;
-    }
-
-    /*package*/ int write(byte[] b, int offset, int length) throws IOException {
-
-        //TODO: Since bindings can exist between the SDU size and the
-        //      protocol, we might need to throw an exception instead of just
-        //      splitting the write into multiple smaller writes.
-        //      Rfcomm uses dynamic allocation, and should not have any bindings
-        //      to the actual message length.
-        if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
-        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
-            if (length <= mMaxTxPacketSize) {
-                mSocketOS.write(b, offset, length);
-            } else {
-                if (DBG) {
-                    Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n"
-                            + "Packet will be divided into SDU packets of size "
-                            + mMaxTxPacketSize);
-                }
-                int tmpOffset = offset;
-                int bytesToWrite = length;
-                while (bytesToWrite > 0) {
-                    int tmpLength = (bytesToWrite > mMaxTxPacketSize)
-                            ? mMaxTxPacketSize
-                            : bytesToWrite;
-                    mSocketOS.write(b, tmpOffset, tmpLength);
-                    tmpOffset += tmpLength;
-                    bytesToWrite -= tmpLength;
-                }
-            }
-        } else {
-            mSocketOS.write(b, offset, length);
-        }
-        // There is no good way to confirm since the entire process is asynchronous anyway
-        if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
-        return length;
-    }
-
-    @Override
-    public void close() throws IOException {
-        Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS
-                + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket + ", mSocketState: "
-                + mSocketState);
-        if (mSocketState == SocketState.CLOSED) {
-            return;
-        } else {
-            synchronized (this) {
-                if (mSocketState == SocketState.CLOSED) {
-                    return;
-                }
-                mSocketState = SocketState.CLOSED;
-                if (mSocket != null) {
-                    if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket);
-                    mSocket.shutdownInput();
-                    mSocket.shutdownOutput();
-                    mSocket.close();
-                    mSocket = null;
-                }
-                if (mPfd != null) {
-                    mPfd.close();
-                    mPfd = null;
-                }
-            }
-        }
-    }
-
-    /*package */ void removeChannel() {
-    }
-
-    /*package */ int getPort() {
-        return mPort;
-    }
-
-    /**
-     * Get the maximum supported Transmit packet size for the underlying transport.
-     * Use this to optimize the writes done to the output socket, to avoid sending
-     * half full packets.
-     *
-     * @return the maximum supported Transmit packet size for the underlying transport.
-     */
-    @RequiresNoPermission
-    public int getMaxTransmitPacketSize() {
-        return mMaxTxPacketSize;
-    }
-
-    /**
-     * Get the maximum supported Receive packet size for the underlying transport.
-     * Use this to optimize the reads done on the input stream, as any call to read
-     * will return a maximum of this amount of bytes - or for some transports a
-     * multiple of this value.
-     *
-     * @return the maximum supported Receive packet size for the underlying transport.
-     */
-    @RequiresNoPermission
-    public int getMaxReceivePacketSize() {
-        return mMaxRxPacketSize;
-    }
-
-    /**
-     * Get the type of the underlying connection.
-     *
-     * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
-     */
-    @RequiresNoPermission
-    public int getConnectionType() {
-        if (mType == TYPE_L2CAP_LE) {
-            // Treat the LE CoC to be the same type as L2CAP.
-            return TYPE_L2CAP;
-        }
-        return mType;
-    }
-
-    /**
-     * Change if a SDP entry should be automatically created.
-     * Must be called before calling .bind, for the call to have any effect.
-     *
-     * @param excludeSdp <li>TRUE - do not auto generate SDP record. <li>FALSE - default - auto
-     * generate SPP SDP record.
-     * @hide
-     */
-    @RequiresNoPermission
-    public void setExcludeSdp(boolean excludeSdp) {
-        mExcludeSdp = excludeSdp;
-    }
-
-    /**
-     * Set the LE Transmit Data Length to be the maximum that the BT Controller is capable of. This
-     * parameter is used by the BT Controller to set the maximum transmission packet size on this
-     * connection. This function is currently used for testing only.
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public void requestMaximumTxDataLength() throws IOException {
-        if (mDevice == null) {
-            throw new IOException("requestMaximumTxDataLength is called on null device");
-        }
-
-        try {
-            if (mSocketState == SocketState.CLOSED) {
-                throw new IOException("socket closed");
-            }
-            IBluetooth bluetoothProxy =
-                    BluetoothAdapter.getDefaultAdapter().getBluetoothService();
-            if (bluetoothProxy == null) {
-                throw new IOException("Bluetooth is off");
-            }
-
-            if (DBG) Log.d(TAG, "requestMaximumTxDataLength");
-            bluetoothProxy.getSocketManager().requestMaximumTxDataLength(mDevice);
-        } catch (RemoteException e) {
-            Log.e(TAG, Log.getStackTraceString(new Throwable()));
-            throw new IOException("unable to send RPC: " + e.getMessage());
-        }
-    }
-
-    private String convertAddr(final byte[] addr) {
-        return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
-                addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-    }
-
-    private String waitSocketSignal(InputStream is) throws IOException {
-        byte[] sig = new byte[SOCK_SIGNAL_SIZE];
-        int ret = readAll(is, sig);
-        if (VDBG) {
-            Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + " bytes signal ret: " + ret);
-        }
-        ByteBuffer bb = ByteBuffer.wrap(sig);
-        /* the struct in native is decorated with __attribute__((packed)), hence this is possible */
-        bb.order(ByteOrder.nativeOrder());
-        int size = bb.getShort();
-        if (size != SOCK_SIGNAL_SIZE) {
-            throw new IOException("Connection failure, wrong signal size: " + size);
-        }
-        byte[] addr = new byte[6];
-        bb.get(addr);
-        int channel = bb.getInt();
-        int status = bb.getInt();
-        mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
-        mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
-        String RemoteAddr = convertAddr(addr);
-        if (VDBG) {
-            Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: "
-                    + RemoteAddr + ", channel: " + channel + ", status: " + status
-                    + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize);
-        }
-        if (status != 0) {
-            throw new IOException("Connection failure, status: " + status);
-        }
-        return RemoteAddr;
-    }
-
-    private void createL2capRxBuffer() {
-        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
-            // Allocate the buffer to use for reads.
-            if (VDBG) Log.v(TAG, "  Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize);
-            mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]);
-            if (VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining());
-            mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request
-            if (VDBG) {
-                Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + mL2capBuffer.remaining());
-            }
-        }
-    }
-
-    private int readAll(InputStream is, byte[] b) throws IOException {
-        int left = b.length;
-        while (left > 0) {
-            int ret = is.read(b, b.length - left, left);
-            if (ret <= 0) {
-                throw new IOException("read failed, socket might closed or timeout, read ret: "
-                        + ret);
-            }
-            left -= ret;
-            if (left != 0) {
-                Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left)
-                        + ", expect size: " + b.length);
-            }
-        }
-        return b.length;
-    }
-
-    private int readInt(InputStream is) throws IOException {
-        byte[] ibytes = new byte[4];
-        int ret = readAll(is, ibytes);
-        if (VDBG) Log.d(TAG, "inputStream.read ret: " + ret);
-        ByteBuffer bb = ByteBuffer.wrap(ibytes);
-        bb.order(ByteOrder.nativeOrder());
-        return bb.getInt();
-    }
-
-    private int fillL2capRxBuffer() throws IOException {
-        mL2capBuffer.rewind();
-        int ret = mSocketIS.read(mL2capBuffer.array());
-        if (ret == -1) {
-            // reached end of stream - return -1
-            mL2capBuffer.limit(0);
-            return -1;
-        }
-        mL2capBuffer.limit(ret);
-        return ret;
-    }
-
-
-}
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
deleted file mode 100644
index 9dafa07..0000000
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.annotation.SystemApi;
-
-/**
- * A class with constants representing possible return values for Bluetooth APIs. General return
- * values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999.
- * API-specific return values start at 1000. The exception to this is the "UNKNOWN" error code which
- * occupies the max integer value.
- */
-public final class BluetoothStatusCodes {
-
-    private BluetoothStatusCodes() {}
-
-    /**
-     * Indicates that the API call was successful
-     */
-    public static final int SUCCESS = 0;
-
-    /**
-     * Error code indicating that Bluetooth is not enabled
-     */
-    public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1;
-
-    /**
-     * Error code indicating that the API call was initiated by neither the system nor the active
-     * Zuser
-     */
-    public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2;
-
-    /**
-     * Error code indicating that the Bluetooth Device specified is not bonded
-     */
-    public static final int ERROR_DEVICE_NOT_BONDED = 3;
-
-    /**
-     * Error code indicating that the Bluetooth Device specified is not connected, but is bonded
-     *
-     * @hide
-     */
-    public static final int ERROR_DEVICE_NOT_CONNECTED = 4;
-
-    /**
-     * Error code indicating that the caller does not have the
-     * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission
-     *
-     * @hide
-     */
-    public static final int ERROR_MISSING_BLUETOOTH_ADVERTISE_PERMISSION = 5;
-
-    /**
-     * Error code indicating that the caller does not have the
-     * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission
-     */
-    public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6;
-
-    /**
-     * Error code indicating that the caller does not have the
-     * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission
-     *
-     * @hide
-     */
-    public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
-
-    /**
-     * Error code indicating that the caller does not have the
-     * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission
-     */
-    public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8;
-
-    /**
-     * Error code indicating that the profile service is not bound. You can bind a profile service
-     * by calling {@link BluetoothAdapter#getProfileProxy}
-     */
-    public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9;
-
-    /**
-     * Error code indicating that the feature is not supported.
-     */
-    public static final int ERROR_FEATURE_NOT_SUPPORTED = 10;
-
-    /**
-     * A GATT writeCharacteristic request is not permitted on the remote device.
-     */
-    public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101;
-
-    /**
-     * A GATT writeCharacteristic request is issued to a busy remote device.
-     */
-    public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102;
-
-    /**
-     * If another application has already requested {@link OobData} then another fetch will be
-     * disallowed until the callback is removed.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000;
-
-    /**
-     * Indicates that the ACL disconnected due to an explicit request from the local device.
-     * <p>
-     * Example cause: This is a normal disconnect reason, e.g., user/app initiates
-     * disconnection.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_LOCAL_REQUEST = 1100;
-
-    /**
-     * Indicates that the ACL disconnected due to an explicit request from the remote device.
-     * <p>
-     * Example cause: This is a normal disconnect reason, e.g., user/app initiates
-     * disconnection.
-     * <p>
-     * Example solution: The app can also prompt the user to check their remote device.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_REMOTE_REQUEST = 1101;
-
-    /**
-     * Generic disconnect reason indicating the ACL disconnected due to an error on the local
-     * device.
-     * <p>
-     * Example solution: Prompt the user to check their local device (e.g., phone, car
-     * headunit).
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_LOCAL = 1102;
-
-    /**
-     * Generic disconnect reason indicating the ACL disconnected due to an error on the remote
-     * device.
-     * <p>
-     * Example solution: Prompt the user to check their remote device (e.g., headset, car
-     * headunit, watch).
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_REMOTE = 1103;
-
-    /**
-     * Indicates that the ACL disconnected due to a timeout.
-     * <p>
-     * Example cause: remote device might be out of range.
-     * <p>
-     * Example solution: Prompt user to verify their remote device is on or in
-     * connection/pairing mode.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_TIMEOUT = 1104;
-
-    /**
-     * Indicates that the ACL disconnected due to link key issues.
-     * <p>
-     * Example cause: Devices are either unpaired or remote device is refusing our pairing
-     * request.
-     * <p>
-     * Example solution: Prompt user to unpair and pair again.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_SECURITY = 1105;
-
-    /**
-     * Indicates that the ACL disconnected due to the local device's system policy.
-     * <p>
-     * Example cause: privacy policy, power management policy, permissions, etc.
-     * <p>
-     * Example solution: Prompt the user to check settings, or check with their system
-     * administrator (e.g. some corp-managed devices do not allow OPP connection).
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_SYSTEM_POLICY = 1106;
-
-    /**
-     * Indicates that the ACL disconnected due to resource constraints, either on the local
-     * device or the remote device.
-     * <p>
-     * Example cause: controller is busy, memory limit reached, maximum number of connections
-     * reached.
-     * <p>
-     * Example solution: The app should wait and try again. If still failing, prompt the user
-     * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED = 1107;
-
-    /**
-     * Indicates that the ACL disconnected because another ACL connection already exists.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS = 1108;
-
-    /**
-     * Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_DISCONNECT_REASON_BAD_PARAMETERS = 1109;
-
-    /**
-     * Indicates that setting the LE Audio Broadcast mode failed.
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED = 1110;
-
-    /**
-     * Indicates that setting a new encryption key for Bluetooth LE Audio Broadcast Source failed.
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED = 1111;
-
-    /**
-     * Indicates that connecting to a remote Broadcast Audio Scan Service failed.
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_CONNECT_FAILED = 1112;
-
-    /**
-     * Indicates that disconnecting from a remote Broadcast Audio Scan Service failed.
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_DISCONNECT_FAILED = 1113;
-
-    /**
-     * Indicates that enabling LE Audio Broadcast encryption failed
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED = 1114;
-
-    /**
-     * Indicates that disabling LE Audio Broadcast encryption failed
-     * <p>
-     * Example solution: Change parameters and try again. If error persists, the app can report
-     * telemetry and/or log the error in a bugreport.
-     *
-     * @hide
-     */
-    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115;
-
-    /**
-     * Indicates that an unknown error has occurred has occurred.
-     */
-    public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;
-}
diff --git a/core/java/android/bluetooth/BluetoothUtils.java b/core/java/android/bluetooth/BluetoothUtils.java
deleted file mode 100644
index 8674692..0000000
--- a/core/java/android/bluetooth/BluetoothUtils.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.bluetooth;
-
-import java.time.Duration;
-
-/**
- * {@hide}
- */
-public final class BluetoothUtils {
-    /**
-     * This utility class cannot be instantiated
-     */
-    private BluetoothUtils() {}
-
-    /**
-     * Timeout value for synchronous binder call
-     */
-    private static final Duration SYNC_CALLS_TIMEOUT = Duration.ofSeconds(5);
-
-    /**
-     * @return timeout value for synchronous binder call
-     */
-    static Duration getSyncTimeout() {
-        return SYNC_CALLS_TIMEOUT;
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
deleted file mode 100644
index 2a8ff51..0000000
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR 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.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.ParcelUuid;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.UUID;
-
-/**
- * Static helper methods and constants to decode the ParcelUuid of remote devices.
- *
- * @hide
- */
-@SystemApi
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class BluetoothUuid {
-
-    /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs
-     * for the various services.
-     *
-     * The following 128 bit values are calculated as:
-     *  uuid * 2^96 + BASE_UUID
-     */
-
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid A2DP_SINK =
-            ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid A2DP_SOURCE =
-            ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid ADV_AUDIO_DIST =
-            ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HSP =
-            ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HSP_AG =
-            ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HFP =
-            ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HFP_AG =
-            ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid AVRCP_CONTROLLER =
-            ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid AVRCP_TARGET =
-            ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid OBEX_OBJECT_PUSH =
-            ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HID =
-            ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HOGP =
-            ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid PANU =
-            ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid NAP =
-            ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid BNEP =
-            ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid PBAP_PCE =
-            ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid PBAP_PSE =
-            ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid MAP =
-            ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid MNS =
-            ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid MAS =
-            ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid SAP =
-            ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid HEARING_AID =
-            ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid LE_AUDIO =
-            ParcelUuid.fromString("0000184E-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid DIP =
-            ParcelUuid.fromString("00001200-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid VOLUME_CONTROL =
-            ParcelUuid.fromString("00001844-0000-1000-8000-00805F9B34FB");
-    /** @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 CAP =
-            ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB");
-    /** @hide */
-    @NonNull
-    @SystemApi
-    public static final ParcelUuid BASE_UUID =
-            ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
-
-    /**
-     * Length of bytes for 16 bit UUID
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int UUID_BYTES_16_BIT = 2;
-    /**
-     * Length of bytes for 32 bit UUID
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int UUID_BYTES_32_BIT = 4;
-    /**
-     * Length of bytes for 128 bit UUID
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int UUID_BYTES_128_BIT = 16;
-
-    /**
-     * Returns true if there any common ParcelUuids in uuidA and uuidB.
-     *
-     * @param uuidA - List of ParcelUuids
-     * @param uuidB - List of ParcelUuids
-     *
-     * @hide
-     */
-    @SystemApi
-    public static boolean containsAnyUuid(@Nullable ParcelUuid[] uuidA,
-            @Nullable ParcelUuid[] uuidB) {
-        if (uuidA == null && uuidB == null) return true;
-
-        if (uuidA == null) {
-            return uuidB.length == 0;
-        }
-
-        if (uuidB == null) {
-            return uuidA.length == 0;
-        }
-
-        HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid>(Arrays.asList(uuidA));
-        for (ParcelUuid uuid : uuidB) {
-            if (uuidSet.contains(uuid)) return true;
-        }
-        return false;
-    }
-
-    /**
-     * Extract the Service Identifier or the actual uuid from the Parcel Uuid.
-     * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid,
-     * this function will return 110B
-     *
-     * @param parcelUuid
-     * @return the service identifier.
-     */
-    private static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) {
-        UUID uuid = parcelUuid.getUuid();
-        long value = (uuid.getMostSignificantBits() & 0xFFFFFFFF00000000L) >>> 32;
-        return (int) value;
-    }
-
-    /**
-     * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID,
-     * but the returned UUID is always in 128-bit format.
-     * Note UUID is little endian in Bluetooth.
-     *
-     * @param uuidBytes Byte representation of uuid.
-     * @return {@link ParcelUuid} parsed from bytes.
-     * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed.
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    public static ParcelUuid parseUuidFrom(@Nullable byte[] uuidBytes) {
-        if (uuidBytes == null) {
-            throw new IllegalArgumentException("uuidBytes cannot be null");
-        }
-        int length = uuidBytes.length;
-        if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT
-                && length != UUID_BYTES_128_BIT) {
-            throw new IllegalArgumentException("uuidBytes length invalid - " + length);
-        }
-
-        // Construct a 128 bit UUID.
-        if (length == UUID_BYTES_128_BIT) {
-            ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
-            long msb = buf.getLong(8);
-            long lsb = buf.getLong(0);
-            return new ParcelUuid(new UUID(msb, lsb));
-        }
-
-        // For 16 bit and 32 bit UUID we need to convert them to 128 bit value.
-        // 128_bit_value = uuid * 2^96 + BASE_UUID
-        long shortUuid;
-        if (length == UUID_BYTES_16_BIT) {
-            shortUuid = uuidBytes[0] & 0xFF;
-            shortUuid += (uuidBytes[1] & 0xFF) << 8;
-        } else {
-            shortUuid = uuidBytes[0] & 0xFF;
-            shortUuid += (uuidBytes[1] & 0xFF) << 8;
-            shortUuid += (uuidBytes[2] & 0xFF) << 16;
-            shortUuid += (uuidBytes[3] & 0xFF) << 24;
-        }
-        long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32);
-        long lsb = BASE_UUID.getUuid().getLeastSignificantBits();
-        return new ParcelUuid(new UUID(msb, lsb));
-    }
-
-    /**
-     * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or
-     * 128-bit UUID, Note returned value is little endian (Bluetooth).
-     *
-     * @param uuid uuid to parse.
-     * @return shortest representation of {@code uuid} as bytes.
-     * @throws IllegalArgumentException If the {@code uuid} is null.
-     *
-     * @hide
-     */
-    public static byte[] uuidToBytes(ParcelUuid uuid) {
-        if (uuid == null) {
-            throw new IllegalArgumentException("uuid cannot be null");
-        }
-
-        if (is16BitUuid(uuid)) {
-            byte[] uuidBytes = new byte[UUID_BYTES_16_BIT];
-            int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
-            uuidBytes[0] = (byte) (uuidVal & 0xFF);
-            uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8);
-            return uuidBytes;
-        }
-
-        if (is32BitUuid(uuid)) {
-            byte[] uuidBytes = new byte[UUID_BYTES_32_BIT];
-            int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
-            uuidBytes[0] = (byte) (uuidVal & 0xFF);
-            uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8);
-            uuidBytes[2] = (byte) ((uuidVal & 0xFF0000) >> 16);
-            uuidBytes[3] = (byte) ((uuidVal & 0xFF000000) >> 24);
-            return uuidBytes;
-        }
-
-        // Construct a 128 bit UUID.
-        long msb = uuid.getUuid().getMostSignificantBits();
-        long lsb = uuid.getUuid().getLeastSignificantBits();
-
-        byte[] uuidBytes = new byte[UUID_BYTES_128_BIT];
-        ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
-        buf.putLong(8, msb);
-        buf.putLong(0, lsb);
-        return uuidBytes;
-    }
-
-    /**
-     * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
-     *
-     * @param parcelUuid
-     * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static boolean is16BitUuid(ParcelUuid parcelUuid) {
-        UUID uuid = parcelUuid.getUuid();
-        if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
-            return false;
-        }
-        return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
-    }
-
-
-    /**
-     * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid.
-     *
-     * @param parcelUuid
-     * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static boolean is32BitUuid(ParcelUuid parcelUuid) {
-        UUID uuid = parcelUuid.getUuid();
-        if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
-            return false;
-        }
-        if (is16BitUuid(parcelUuid)) {
-            return false;
-        }
-        return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L);
-    }
-
-    private BluetoothUuid() {}
-}
diff --git a/core/java/android/bluetooth/BluetoothVolumeControl.java b/core/java/android/bluetooth/BluetoothVolumeControl.java
deleted file mode 100644
index 27532aa..0000000
--- a/core/java/android/bluetooth/BluetoothVolumeControl.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * 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 static android.bluetooth.BluetoothUtils.getSyncTimeout;
-
-import android.Manifest;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.CloseGuard;
-import android.util.Log;
-
-import com.android.modules.utils.SynchronousResultReceiver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeoutException;
-
-/**
- * This class provides the public APIs to control the Bluetooth Volume Control service.
- *
- * <p>BluetoothVolumeControl is a proxy object for controlling the Bluetooth VC
- * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
- * the BluetoothVolumeControl proxy object.
- * @hide
- */
-@SystemApi
-public final class BluetoothVolumeControl implements BluetoothProfile, AutoCloseable {
-    private static final String TAG = "BluetoothVolumeControl";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    private CloseGuard mCloseGuard;
-
-    /**
-     * Intent used to broadcast the change in connection state of the Volume Control
-     * profile.
-     *
-     * <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}.
-     *
-     * @hide
-     */
-    @SystemApi
-    @SuppressLint("ActionValue")
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_CONNECTION_STATE_CHANGED =
-            "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED";
-
-    private BluetoothAdapter mAdapter;
-    private final AttributionSource mAttributionSource;
-    private final BluetoothProfileConnector<IBluetoothVolumeControl> mProfileConnector =
-            new BluetoothProfileConnector(this, BluetoothProfile.VOLUME_CONTROL, TAG,
-                    IBluetoothVolumeControl.class.getName()) {
-                @Override
-                public IBluetoothVolumeControl getServiceInterface(IBinder service) {
-                    return IBluetoothVolumeControl.Stub.asInterface(service);
-                }
-            };
-
-    /**
-     * Create a BluetoothVolumeControl proxy object for interacting with the local
-     * Bluetooth Volume Control service.
-     */
-    /*package*/ BluetoothVolumeControl(Context context, ServiceListener listener,
-            BluetoothAdapter adapter) {
-        mAdapter = adapter;
-        mAttributionSource = adapter.getAttributionSource();
-        mProfileConnector.connect(context, listener);
-        mCloseGuard = new CloseGuard();
-        mCloseGuard.open("close");
-    }
-
-    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
-    protected void finalize() {
-        if (mCloseGuard != null) {
-            mCloseGuard.warnIfOpen();
-        }
-        close();
-    }
-
-    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void close() {
-        mProfileConnector.disconnect();
-    }
-
-    private IBluetoothVolumeControl getService() { return mProfileConnector.getService(); }
-
-    /**
-     * Get the list of connected devices. Currently at most one.
-     *
-     * @return list of connected devices
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @NonNull List<BluetoothDevice> getConnectedDevices() {
-        if (DBG) log("getConnectedDevices()");
-        final IBluetoothVolumeControl service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getConnectedDevices(mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get the list of devices matching specified states. Currently at most one.
-     *
-     * @return list of matching devices
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (DBG) log("getDevicesMatchingStates()");
-        final IBluetoothVolumeControl service = getService();
-        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver<List<BluetoothDevice>> recv =
-                        new SynchronousResultReceiver();
-                service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv);
-                return Attributable.setAttributionSource(
-                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
-                        mAttributionSource);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Get connection state of device
-     *
-     * @return device connection state
-     *
-     * @hide
-     */
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
-    public int getConnectionState(BluetoothDevice device) {
-        if (DBG) log("getConnectionState(" + device + ")");
-        final IBluetoothVolumeControl service = getService();
-        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionState(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Tells remote device to set an absolute volume.
-     *
-     * @param volume Absolute volume to be set on remote device.
-     *               Minimum value is 0 and maximum value is 255
-     * @hide
-     */
-    @SystemApi
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public void setVolume(@Nullable BluetoothDevice device,
-            @IntRange(from = 0, to = 255) int volume) {
-        if (DBG) log("setVolume(" + volume + ")");
-        final IBluetoothVolumeControl service = getService();
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled()) {
-            try {
-                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
-                service.setVolume(device, volume, mAttributionSource, recv);
-                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
-            @ConnectionPolicy int connectionPolicy) {
-        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
-        final IBluetoothVolumeControl service = getService();
-        final boolean defaultValue = false;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)
-                && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
-                    || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
-            try {
-                final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
-                service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * 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
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
-        if (VDBG) log("getConnectionPolicy(" + device + ")");
-        final IBluetoothVolumeControl service = getService();
-        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            if (DBG) log(Log.getStackTraceString(new Throwable()));
-        } else if (isEnabled() && isValidDevice(device)) {
-            try {
-                final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
-                service.getConnectionPolicy(device, mAttributionSource, recv);
-                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
-            } catch (RemoteException | TimeoutException e) {
-                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
-            }
-        }
-        return defaultValue;
-    }
-
-    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/BufferConstraint.java b/core/java/android/bluetooth/BufferConstraint.java
deleted file mode 100644
index cbffc78..0000000
--- a/core/java/android/bluetooth/BufferConstraint.java
+++ /dev/null
@@ -1,105 +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.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Stores a codec's constraints on buffering length in milliseconds.
- *
- * {@hide}
- */
-@SystemApi
-public final class BufferConstraint implements Parcelable {
-
-    private static final String TAG = "BufferConstraint";
-    private int mDefaultMillis;
-    private int mMaxMillis;
-    private int mMinMillis;
-
-    public BufferConstraint(int defaultMillis, int maxMillis,
-            int minMillis) {
-        mDefaultMillis = defaultMillis;
-        mMaxMillis = maxMillis;
-        mMinMillis = minMillis;
-    }
-
-    BufferConstraint(Parcel in) {
-        mDefaultMillis = in.readInt();
-        mMaxMillis = in.readInt();
-        mMinMillis = in.readInt();
-    }
-
-    public static final @NonNull Parcelable.Creator<BufferConstraint> CREATOR =
-            new Parcelable.Creator<BufferConstraint>() {
-                public BufferConstraint createFromParcel(Parcel in) {
-                    return new BufferConstraint(in);
-                }
-
-                public BufferConstraint[] newArray(int size) {
-                    return new BufferConstraint[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeInt(mDefaultMillis);
-        out.writeInt(mMaxMillis);
-        out.writeInt(mMinMillis);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Get the default buffer millis
-     *
-     * @return default buffer millis
-     * @hide
-     */
-    @SystemApi
-    public int getDefaultMillis() {
-        return mDefaultMillis;
-    }
-
-    /**
-     * Get the maximum buffer millis
-     *
-     * @return maximum buffer millis
-     * @hide
-     */
-    @SystemApi
-    public int getMaxMillis() {
-        return mMaxMillis;
-    }
-
-    /**
-     * Get the minimum buffer millis
-     *
-     * @return minimum buffer millis
-     * @hide
-     */
-    @SystemApi
-    public int getMinMillis() {
-        return mMinMillis;
-    }
-}
diff --git a/core/java/android/bluetooth/BufferConstraints.java b/core/java/android/bluetooth/BufferConstraints.java
deleted file mode 100644
index 97d9723..0000000
--- a/core/java/android/bluetooth/BufferConstraints.java
+++ /dev/null
@@ -1,96 +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.bluetooth;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-
-/**
- * A parcelable collection of buffer constraints by codec type.
- *
- * {@hide}
- */
-@SystemApi
-public final class BufferConstraints implements Parcelable {
-    public static final int BUFFER_CODEC_MAX_NUM = 32;
-
-    private static final String TAG = "BufferConstraints";
-
-    private Map<Integer, BufferConstraint> mBufferConstraints;
-    private List<BufferConstraint> mBufferConstraintList;
-
-    public BufferConstraints(@NonNull List<BufferConstraint>
-            bufferConstraintList) {
-
-        mBufferConstraintList = new ArrayList<BufferConstraint>(bufferConstraintList);
-        mBufferConstraints = new HashMap<Integer, BufferConstraint>();
-        for (int i = 0; i < BUFFER_CODEC_MAX_NUM; i++) {
-            mBufferConstraints.put(i, bufferConstraintList.get(i));
-        }
-    }
-
-    BufferConstraints(Parcel in) {
-        mBufferConstraintList = new ArrayList<BufferConstraint>();
-        mBufferConstraints = new HashMap<Integer, BufferConstraint>();
-        in.readList(mBufferConstraintList, BufferConstraint.class.getClassLoader());
-        for (int i = 0; i < mBufferConstraintList.size(); i++) {
-            mBufferConstraints.put(i, mBufferConstraintList.get(i));
-        }
-    }
-
-    public static final @NonNull Parcelable.Creator<BufferConstraints> CREATOR =
-            new Parcelable.Creator<BufferConstraints>() {
-                public BufferConstraints createFromParcel(Parcel in) {
-                    return new BufferConstraints(in);
-                }
-
-                public BufferConstraints[] newArray(int size) {
-                    return new BufferConstraints[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeList(mBufferConstraintList);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Get the buffer constraints by codec type.
-     *
-     * @param codec Audio codec
-     * @return buffer constraints by codec type.
-     * @hide
-     */
-    @SystemApi
-    public @Nullable BufferConstraint forCodec(@BluetoothCodecConfig.SourceCodecType int codec) {
-        return mBufferConstraints.get(codec);
-    }
-}
diff --git a/core/java/android/bluetooth/OWNERS b/core/java/android/bluetooth/OWNERS
deleted file mode 100644
index fbee577..0000000
--- a/core/java/android/bluetooth/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 27441
-
-rahulsabnis@google.com
-sattiraju@google.com
-siyuanh@google.com
-zachoverflow@google.com
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
deleted file mode 100644
index bb0b956..0000000
--- a/core/java/android/bluetooth/OobData.java
+++ /dev/null
@@ -1,958 +0,0 @@
-/**
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Out Of Band Data for Bluetooth device pairing.
- *
- * <p>This object represents optional data obtained from a remote device through
- * an out-of-band channel (eg. NFC, QR).
- *
- * <p>References:
- * NFC AD Forum SSP 1.1 (AD)
- * {@link https://members.nfc-forum.org//apps/group_public/download.php/24620/NFCForum-AD-BTSSP_1_1.pdf}
- * Core Specification Supplement (CSS) V9
- *
- * <p>There are several BR/EDR Examples
- *
- * <p>Negotiated Handover:
- *   Bluetooth Carrier Configuration Record:
- *    - OOB Data Length
- *    - Device Address
- *    - Class of Device
- *    - Simple Pairing Hash C
- *    - Simple Pairing Randomizer R
- *    - Service Class UUID
- *    - Bluetooth Local Name
- *
- * <p>Static Handover:
- *   Bluetooth Carrier Configuration Record:
- *    - OOB Data Length
- *    - Device Address
- *    - Class of Device
- *    - Service Class UUID
- *    - Bluetooth Local Name
- *
- * <p>Simplified Tag Format for Single BT Carrier:
- *   Bluetooth OOB Data Record:
- *    - OOB Data Length
- *    - Device Address
- *    - Class of Device
- *    - Service Class UUID
- *    - Bluetooth Local Name
- *
- * @hide
- */
-@SystemApi
-public final class OobData implements Parcelable {
-
-    private static final String TAG = "OobData";
-    /** The {@link OobData#mClassicLength} may be. (AD 3.1.1) (CSS 1.6.2) @hide */
-    @SystemApi
-    public static final int OOB_LENGTH_OCTETS = 2;
-    /**
-     * The length for the {@link OobData#mDeviceAddressWithType}(6) and Address Type(1).
-     * (AD 3.1.2) (CSS 1.6.2)
-     * @hide
-     */
-    @SystemApi
-    public static final int DEVICE_ADDRESS_OCTETS = 7;
-    /** The Class of Device is 3 octets. (AD 3.1.3) (CSS 1.6.2) @hide */
-    @SystemApi
-    public static final int CLASS_OF_DEVICE_OCTETS = 3;
-    /** The Confirmation data must be 16 octets. (AD 3.2.2) (CSS 1.6.2) @hide */
-    @SystemApi
-    public static final int CONFIRMATION_OCTETS = 16;
-    /** The Randomizer data must be 16 octets. (AD 3.2.3) (CSS 1.6.2) @hide */
-    @SystemApi
-    public static final int RANDOMIZER_OCTETS = 16;
-    /** The LE Device Role length is 1 octet. (AD 3.3.2) (CSS 1.17) @hide */
-    @SystemApi
-    public static final int LE_DEVICE_ROLE_OCTETS = 1;
-    /** The {@link OobData#mLeTemporaryKey} length. (3.4.1) @hide */
-    @SystemApi
-    public static final int LE_TK_OCTETS = 16;
-    /** The {@link OobData#mLeAppearance} length. (3.4.1) @hide */
-    @SystemApi
-    public static final int LE_APPEARANCE_OCTETS = 2;
-    /** The {@link OobData#mLeFlags} length. (3.4.1) @hide */
-    @SystemApi
-    public static final int LE_DEVICE_FLAG_OCTETS = 1; // 1 octet to hold the 0-4 value.
-
-    // Le Roles
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-        prefix = { "LE_DEVICE_ROLE_" },
-        value = {
-            LE_DEVICE_ROLE_PERIPHERAL_ONLY,
-            LE_DEVICE_ROLE_CENTRAL_ONLY,
-            LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL,
-            LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL
-        }
-    )
-    public @interface LeRole {}
-
-    /** @hide */
-    @SystemApi
-    public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0x00;
-    /** @hide */
-    @SystemApi
-    public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 0x01;
-    /** @hide */
-    @SystemApi
-    public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 0x02;
-    /** @hide */
-    @SystemApi
-    public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 0x03;
-
-    // Le Flags
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-        prefix = { "LE_FLAG_" },
-        value = {
-            LE_FLAG_LIMITED_DISCOVERY_MODE,
-            LE_FLAG_GENERAL_DISCOVERY_MODE,
-            LE_FLAG_BREDR_NOT_SUPPORTED,
-            LE_FLAG_SIMULTANEOUS_CONTROLLER,
-            LE_FLAG_SIMULTANEOUS_HOST
-        }
-    )
-    public @interface LeFlag {}
-
-    /** @hide */
-    @SystemApi
-    public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0x00;
-    /** @hide */
-    @SystemApi
-    public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 0x01;
-    /** @hide */
-    @SystemApi
-    public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 0x02;
-    /** @hide */
-    @SystemApi
-    public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 0x03;
-    /** @hide */
-    @SystemApi
-    public static final int LE_FLAG_SIMULTANEOUS_HOST = 0x04;
-
-    /**
-     * Builds an {@link OobData} object and validates that the required combination
-     * of values are present to create the LE specific OobData type.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final class LeBuilder {
-
-        /**
-         * It is recommended that this Hash C is generated anew for each
-         * pairing.
-         *
-         * <p>It should be noted that on passive NFC this isn't possible as the data is static
-         * and immutable.
-         */
-        private byte[] mConfirmationHash = null;
-
-        /**
-         * Optional, but adds more validity to the pairing.
-         *
-         * <p>If not present a value of 0 is assumed.
-         */
-        private byte[] mRandomizerHash = new byte[] {
-            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-        };
-
-        /**
-         * The Bluetooth Device user-friendly name presented over Bluetooth Technology.
-         *
-         * <p>This is the name that may be displayed to the device user as part of the UI.
-         */
-        private byte[] mDeviceName = null;
-
-        /**
-         * Sets the Bluetooth Device name to be used for UI purposes.
-         *
-         * <p>Optional attribute.
-         *
-         * @param deviceName byte array representing the name, may be 0 in length, not null.
-         *
-         * @return {@link OobData#ClassicBuilder}
-         *
-         * @throws NullPointerException if deviceName is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public LeBuilder setDeviceName(@NonNull byte[] deviceName) {
-            requireNonNull(deviceName);
-            this.mDeviceName = deviceName;
-            return this;
-        }
-
-        /**
-         * The Bluetooth Device Address is the address to which the OOB data belongs.
-         *
-         * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
-         *
-         * <p> Address is encoded in Little Endian order.
-         *
-         * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
-         */
-        private final byte[] mDeviceAddressWithType;
-
-        /**
-         * During an LE connection establishment, one must be in the Peripheral mode and the other
-         * in the Central role.
-         *
-         * <p>Possible Values:
-         * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
-         * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
-         * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
-         * Peripheral Preferred
-         * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
-         * 0x04 - 0xFF Reserved
-         */
-        private final @LeRole int mLeDeviceRole;
-
-        /**
-         * Temporary key value from the Security Manager.
-         *
-         * <p> Must be {@link LE_TK_OCTETS} in size
-         */
-        private byte[] mLeTemporaryKey = null;
-
-        /**
-         * Defines the representation of the external appearance of the device.
-         *
-         * <p>For example, a mouse, remote control, or keyboard.
-         *
-         * <p>Used for visual on discovering device to represent icon/string/etc...
-         */
-        private byte[] mLeAppearance = null;
-
-        /**
-         * Contains which discoverable mode to use, BR/EDR support and capability.
-         *
-         * <p>Possible LE Flags:
-         * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
-         * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
-         * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
-         * LMP Feature Mask Definitions.
-         * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
-         * Same Device Capable (Controller).
-         * Bit 49 of LMP Feature Mask Definitions.
-         * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
-         * Same Device Capable (Host).
-         * Bit 55 of LMP Feature Mask Definitions.
-         * <b>0x05- 0x07 Reserved</b>
-         */
-        private @LeFlag int mLeFlags = LE_FLAG_GENERAL_DISCOVERY_MODE; // Invalid default
-
-        /**
-         * Main creation method for creating a LE version of {@link OobData}.
-         *
-         * <p>This object will allow the caller to call {@link LeBuilder#build()}
-         * to build the data object or add any option information to the builder.
-         *
-         * @param deviceAddressWithType the LE device address plus the address type (7 octets);
-         * not null.
-         * @param leDeviceRole whether the device supports Peripheral, Central,
-         * Both including preference; not null. (1 octet)
-         * @param confirmationHash Array consisting of {@link OobData#CONFIRMATION_OCTETS} octets
-         * of data. Data is derived from controller/host stack and is
-         * required for pairing OOB.
-         *
-         * <p>Possible Values:
-         * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
-         * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
-         * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
-         * Peripheral Preferred
-         * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
-         * 0x04 - 0xFF Reserved
-         *
-         * @throws IllegalArgumentException if any of the values fail to be set.
-         * @throws NullPointerException if any argument is null.
-         *
-         * @hide
-         */
-        @SystemApi
-        public LeBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] deviceAddressWithType,
-                @LeRole int leDeviceRole) {
-            requireNonNull(confirmationHash);
-            requireNonNull(deviceAddressWithType);
-            if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
-                throw new IllegalArgumentException("confirmationHash must be "
-                    + OobData.CONFIRMATION_OCTETS + " octets in length.");
-            }
-            this.mConfirmationHash = confirmationHash;
-            if (deviceAddressWithType.length != OobData.DEVICE_ADDRESS_OCTETS) {
-                throw new IllegalArgumentException("confirmationHash must be "
-                    + OobData.DEVICE_ADDRESS_OCTETS+ " octets in length.");
-            }
-            this.mDeviceAddressWithType = deviceAddressWithType;
-            if (leDeviceRole < LE_DEVICE_ROLE_PERIPHERAL_ONLY
-                    || leDeviceRole > LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL) {
-                throw new IllegalArgumentException("leDeviceRole must be a valid value.");
-            }
-            this.mLeDeviceRole = leDeviceRole;
-        }
-
-        /**
-         * Sets the Temporary Key value to be used by the LE Security Manager during
-         * LE pairing.
-         *
-         * @param leTemporaryKey byte array that shall be 16 bytes. Please see Bluetooth CSSv6,
-         * Part A 1.8 for a detailed description.
-         *
-         * @return {@link OobData#Builder}
-         *
-         * @throws IllegalArgumentException if the leTemporaryKey is an invalid format.
-         * @throws NullinterException if leTemporaryKey is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public LeBuilder setLeTemporaryKey(@NonNull byte[] leTemporaryKey) {
-            requireNonNull(leTemporaryKey);
-            if (leTemporaryKey.length != LE_TK_OCTETS) {
-                throw new IllegalArgumentException("leTemporaryKey must be "
-                        + LE_TK_OCTETS + " octets in length.");
-            }
-            this.mLeTemporaryKey = leTemporaryKey;
-            return this;
-        }
-
-        /**
-         * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
-         * of data. Data is derived from controller/host stack and is required for pairing OOB.
-         * Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
-         *
-         * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
-         * @throws NullPointerException if randomizerHash is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public LeBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
-            requireNonNull(randomizerHash);
-            if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
-                throw new IllegalArgumentException("randomizerHash must be "
-                    + OobData.RANDOMIZER_OCTETS + " octets in length.");
-            }
-            this.mRandomizerHash = randomizerHash;
-            return this;
-        }
-
-        /**
-         * Sets the LE Flags necessary for the pairing scenario or discovery mode.
-         *
-         * @param leFlags enum value representing the 1 octet of data about discovery modes.
-         *
-         * <p>Possible LE Flags:
-         * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
-         * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
-         * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
-         * LMP Feature Mask Definitions.
-         * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
-         * Same Device Capable (Controller) Bit 49 of LMP Feature Mask Definitions.
-         * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
-         * Same Device Capable (Host).
-         * Bit 55 of LMP Feature Mask Definitions.
-         * 0x05- 0x07 Reserved
-         *
-         * @throws IllegalArgumentException for invalid flag
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public LeBuilder setLeFlags(@LeFlag int leFlags) {
-            if (leFlags < LE_FLAG_LIMITED_DISCOVERY_MODE || leFlags > LE_FLAG_SIMULTANEOUS_HOST) {
-                throw new IllegalArgumentException("leFlags must be a valid value.");
-            }
-            this.mLeFlags = leFlags;
-            return this;
-        }
-
-        /**
-         * Validates and builds the {@link OobData} object for LE Security.
-         *
-         * @return {@link OobData} with given builder values
-         *
-         * @throws IllegalStateException if either of the 2 required fields were not set.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public OobData build() {
-            final OobData oob =
-                    new OobData(this.mDeviceAddressWithType, this.mLeDeviceRole,
-                            this.mConfirmationHash);
-
-            // If we have values, set them, otherwise use default
-            oob.mLeTemporaryKey =
-                    (this.mLeTemporaryKey != null) ? this.mLeTemporaryKey : oob.mLeTemporaryKey;
-            oob.mLeAppearance = (this.mLeAppearance != null)
-                    ? this.mLeAppearance : oob.mLeAppearance;
-            oob.mLeFlags = (this.mLeFlags != 0xF) ? this.mLeFlags : oob.mLeFlags;
-            oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
-            oob.mRandomizerHash = this.mRandomizerHash;
-            return oob;
-        }
-    }
-
-    /**
-     * Builds an {@link OobData} object and validates that the required combination
-     * of values are present to create the Classic specific OobData type.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final class ClassicBuilder {
-        // Used by both Classic and LE
-        /**
-         * It is recommended that this Hash C is generated anew for each
-         * pairing.
-         *
-         * <p>It should be noted that on passive NFC this isn't possible as the data is static
-         * and immutable.
-         *
-         * @hide
-         */
-        private byte[] mConfirmationHash = null;
-
-        /**
-         * Optional, but adds more validity to the pairing.
-         *
-         * <p>If not present a value of 0 is assumed.
-         *
-         * @hide
-         */
-        private byte[] mRandomizerHash = new byte[] {
-            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-        };
-
-        /**
-         * The Bluetooth Device user-friendly name presented over Bluetooth Technology.
-         *
-         * <p>This is the name that may be displayed to the device user as part of the UI.
-         *
-         * @hide
-         */
-        private byte[] mDeviceName = null;
-
-        /**
-         * This length value provides the absolute length of total OOB data block used for
-         * Bluetooth BR/EDR
-         *
-         * <p>OOB communication, which includes the length field itself and the Bluetooth
-         * Device Address.
-         *
-         * <p>The minimum length that may be represented in this field is 8.
-         *
-         * @hide
-         */
-        private final byte[] mClassicLength;
-
-        /**
-         * The Bluetooth Device Address is the address to which the OOB data belongs.
-         *
-         * <p>The length MUST be {@link OobData#DEVICE_ADDRESS_OCTETS} octets.
-         *
-         * <p> Address is encoded in Little Endian order.
-         *
-         * <p>e.g. 00:01:02:03:04:05 would be x05x04x03x02x01x00
-         *
-         * @hide
-         */
-        private final byte[] mDeviceAddressWithType;
-
-        /**
-         * Class of Device information is to be used to provide a graphical representation
-         * to the user as part of UI involving operations.
-         *
-         * <p>This is not to be used to determine a particular service can be used.
-         *
-         * <p>The length MUST be {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
-         *
-         * @hide
-         */
-        private byte[] mClassOfDevice = null;
-
-        /**
-         * Main creation method for creating a Classic version of {@link OobData}.
-         *
-         * <p>This object will allow the caller to call {@link ClassicBuilder#build()}
-         * to build the data object or add any option information to the builder.
-         *
-         * @param confirmationHash byte array consisting of {@link OobData#CONFIRMATION_OCTETS}
-         * octets of data. Data is derived from controller/host stack and is required for pairing
-         * OOB.
-         * @param classicLength byte array representing the length of data from 8-65535 across 2
-         * octets (0xXXXX).
-         * @param deviceAddressWithType byte array representing the Bluetooth Address of the device
-         * that owns the OOB data. (i.e. the originator) [6 octets]
-         *
-         * @throws IllegalArgumentException if any of the values fail to be set.
-         * @throws NullPointerException if any argument is null.
-         *
-         * @hide
-         */
-        @SystemApi
-        public ClassicBuilder(@NonNull byte[] confirmationHash, @NonNull byte[] classicLength,
-                @NonNull byte[] deviceAddressWithType) {
-            requireNonNull(confirmationHash);
-            requireNonNull(classicLength);
-            requireNonNull(deviceAddressWithType);
-            if (confirmationHash.length != OobData.CONFIRMATION_OCTETS) {
-                throw new IllegalArgumentException("confirmationHash must be "
-                    + OobData.CONFIRMATION_OCTETS + " octets in length.");
-            }
-            this.mConfirmationHash = confirmationHash;
-            if (classicLength.length != OOB_LENGTH_OCTETS) {
-                throw new IllegalArgumentException("classicLength must be "
-                        + OOB_LENGTH_OCTETS + " octets in length.");
-            }
-            this.mClassicLength = classicLength;
-            if (deviceAddressWithType.length != DEVICE_ADDRESS_OCTETS) {
-                throw new IllegalArgumentException("deviceAddressWithType must be "
-                        + DEVICE_ADDRESS_OCTETS + " octets in length.");
-            }
-            this.mDeviceAddressWithType = deviceAddressWithType;
-        }
-
-        /**
-         * @param randomizerHash byte array consisting of {@link OobData#RANDOMIZER_OCTETS} octets
-         * of data. Data is derived from controller/host stack and is required for pairing OOB.
-         * Also, randomizerHash may be all 0s or null in which case it becomes all 0s.
-         *
-         * @throws IllegalArgumentException if null or incorrect length randomizerHash was passed.
-         * @throws NullPointerException if randomizerHash is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public ClassicBuilder setRandomizerHash(@NonNull byte[] randomizerHash) {
-            requireNonNull(randomizerHash);
-            if (randomizerHash.length != OobData.RANDOMIZER_OCTETS) {
-                throw new IllegalArgumentException("randomizerHash must be "
-                    + OobData.RANDOMIZER_OCTETS + " octets in length.");
-            }
-            this.mRandomizerHash = randomizerHash;
-            return this;
-        }
-
-        /**
-         * Sets the Bluetooth Device name to be used for UI purposes.
-         *
-         * <p>Optional attribute.
-         *
-         * @param deviceName byte array representing the name, may be 0 in length, not null.
-         *
-         * @return {@link OobData#ClassicBuilder}
-         *
-         * @throws NullPointerException if deviceName is null
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public ClassicBuilder setDeviceName(@NonNull byte[] deviceName) {
-            requireNonNull(deviceName);
-            this.mDeviceName = deviceName;
-            return this;
-        }
-
-        /**
-         * Sets the Bluetooth Class of Device; used for UI purposes only.
-         *
-         * <p>Not an indicator of available services!
-         *
-         * <p>Optional attribute.
-         *
-         * @param classOfDevice byte array of {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
-         *
-         * @return {@link OobData#ClassicBuilder}
-         *
-         * @throws IllegalArgumentException if length is not equal to
-         * {@link OobData#CLASS_OF_DEVICE_OCTETS} octets.
-         * @throws NullPointerException if classOfDevice is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public ClassicBuilder setClassOfDevice(@NonNull byte[] classOfDevice) {
-            requireNonNull(classOfDevice);
-            if (classOfDevice.length != OobData.CLASS_OF_DEVICE_OCTETS) {
-                throw new IllegalArgumentException("classOfDevice must be "
-                        + OobData.CLASS_OF_DEVICE_OCTETS + " octets in length.");
-            }
-            this.mClassOfDevice = classOfDevice;
-            return this;
-        }
-
-        /**
-         * Validates and builds the {@link OobDat object for Classic Security.
-         *
-         * @return {@link OobData} with previously given builder values.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public OobData build() {
-            final OobData oob =
-                    new OobData(this.mClassicLength, this.mDeviceAddressWithType,
-                            this.mConfirmationHash);
-            // If we have values, set them, otherwise use default
-            oob.mDeviceName = (this.mDeviceName != null) ? this.mDeviceName : oob.mDeviceName;
-            oob.mClassOfDevice = (this.mClassOfDevice != null)
-                    ? this.mClassOfDevice : oob.mClassOfDevice;
-            oob.mRandomizerHash = this.mRandomizerHash;
-            return oob;
-        }
-    }
-
-    // Members (Defaults for Optionals must be set or Parceling fails on NPE)
-    // Both
-    private final byte[] mDeviceAddressWithType;
-    private final byte[] mConfirmationHash;
-    private byte[] mRandomizerHash = new byte[] {
-        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-    };
-    // Default the name to "Bluetooth Device"
-    private byte[] mDeviceName = new byte[] {
-        // Bluetooth
-        0x42, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68,
-        // <space>Device
-        0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65
-    };
-
-    // Classic
-    private final byte[] mClassicLength;
-    private byte[] mClassOfDevice = new byte[CLASS_OF_DEVICE_OCTETS];
-
-    // LE
-    private final @LeRole int mLeDeviceRole;
-    private byte[] mLeTemporaryKey = new byte[LE_TK_OCTETS];
-    private byte[] mLeAppearance = new byte[LE_APPEARANCE_OCTETS];
-    private @LeFlag int mLeFlags = LE_FLAG_LIMITED_DISCOVERY_MODE;
-
-    /**
-     * @return byte array representing the MAC address of a bluetooth device.
-     * The Address is 6 octets long with a 1 octet address type associated with the address.
-     *
-     * <p>For classic this will be 6 byte address plus the default of PUBLIC_ADDRESS Address Type.
-     * For LE there are more choices for Address Type.
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    public byte[] getDeviceAddressWithType() {
-        return mDeviceAddressWithType;
-    }
-
-    /**
-     * @return byte array representing the confirmationHash value
-     * which is used to confirm the identity to the controller.
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    public byte[] getConfirmationHash() {
-        return mConfirmationHash;
-    }
-
-    /**
-     * @return byte array representing the randomizerHash value
-     * which is used to verify the identity of the controller.
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    public byte[] getRandomizerHash() {
-        return mRandomizerHash;
-    }
-
-    /**
-     * @return Device Name used for displaying name in UI.
-     *
-     * <p>Also, this will be populated with the LE Local Name if the data is for LE.
-     *
-     * @hide
-     */
-    @Nullable
-    @SystemApi
-    public byte[] getDeviceName() {
-        return mDeviceName;
-    }
-
-    /**
-     * @return byte array representing the oob data length which is the length
-     * of all of the data including these octets.
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    public byte[] getClassicLength() {
-        return mClassicLength;
-    }
-
-    /**
-     * @return byte array representing the class of device for UI display.
-     *
-     * <p>Does not indicate services available; for display only.
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    public byte[] getClassOfDevice() {
-        return mClassOfDevice;
-    }
-
-    /**
-     * @return Temporary Key used for LE pairing.
-     *
-     * @hide
-     */
-    @Nullable
-    @SystemApi
-    public byte[] getLeTemporaryKey() {
-        return mLeTemporaryKey;
-    }
-
-    /**
-     * @return Appearance used for LE pairing. For use in UI situations
-     * when determining what sort of icons or text to display regarding
-     * the device.
-     *
-     * @hide
-     */
-    @Nullable
-    @SystemApi
-    public byte[] getLeAppearance() {
-        return mLeAppearance;
-    }
-
-    /**
-     * @return Flags used to determing discoverable mode to use, BR/EDR Support, and Capability.
-     *
-     * <p>Possible LE Flags:
-     * {@link LE_FLAG_LIMITED_DISCOVERY_MODE} LE Limited Discoverable Mode.
-     * {@link LE_FLAG_GENERAL_DISCOVERY_MODE} LE General Discoverable Mode.
-     * {@link LE_FLAG_BREDR_NOT_SUPPORTED} BR/EDR Not Supported. Bit 37 of
-     * LMP Feature Mask Definitions.
-     * {@link LE_FLAG_SIMULTANEOUS_CONTROLLER} Simultaneous LE and BR/EDR to
-     * Same Device Capable (Controller).
-     * Bit 49 of LMP Feature Mask Definitions.
-     * {@link LE_FLAG_SIMULTANEOUS_HOST} Simultaneous LE and BR/EDR to
-     * Same Device Capable (Host).
-     * Bit 55 of LMP Feature Mask Definitions.
-     * <b>0x05- 0x07 Reserved</b>
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    @LeFlag
-    public int getLeFlags() {
-        return mLeFlags;
-    }
-
-    /**
-     * @return the supported and preferred roles of the LE device.
-     *
-     * <p>Possible Values:
-     * {@link LE_DEVICE_ROLE_PERIPHERAL_ONLY} Only Peripheral supported
-     * {@link LE_DEVICE_ROLE_CENTRAL_ONLY} Only Central supported
-     * {@link LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL} Central & Peripheral supported;
-     * Peripheral Preferred
-     * {@link LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL} Only peripheral supported; Central Preferred
-     * 0x04 - 0xFF Reserved
-     *
-     * @hide
-     */
-    @NonNull
-    @SystemApi
-    @LeRole
-    public int getLeDeviceRole() {
-        return mLeDeviceRole;
-    }
-
-    /**
-     * Classic Security Constructor
-     */
-    private OobData(@NonNull byte[] classicLength, @NonNull byte[] deviceAddressWithType,
-            @NonNull byte[] confirmationHash) {
-        mClassicLength = classicLength;
-        mDeviceAddressWithType = deviceAddressWithType;
-        mConfirmationHash = confirmationHash;
-        mLeDeviceRole = -1; // Satisfy final
-    }
-
-    /**
-     * LE Security Constructor
-     */
-    private OobData(@NonNull byte[] deviceAddressWithType, @LeRole int leDeviceRole,
-            @NonNull byte[] confirmationHash) {
-        mDeviceAddressWithType = deviceAddressWithType;
-        mLeDeviceRole = leDeviceRole;
-        mConfirmationHash = confirmationHash;
-        mClassicLength = new byte[OOB_LENGTH_OCTETS]; // Satisfy final
-    }
-
-    private OobData(Parcel in) {
-        // Both
-        mDeviceAddressWithType = in.createByteArray();
-        mConfirmationHash = in.createByteArray();
-        mRandomizerHash = in.createByteArray();
-        mDeviceName = in.createByteArray();
-
-        // Classic
-        mClassicLength = in.createByteArray();
-        mClassOfDevice = in.createByteArray();
-
-        // LE
-        mLeDeviceRole = in.readInt();
-        mLeTemporaryKey = in.createByteArray();
-        mLeAppearance = in.createByteArray();
-        mLeFlags = in.readInt();
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        // Both
-        // Required
-        out.writeByteArray(mDeviceAddressWithType);
-        // Required
-        out.writeByteArray(mConfirmationHash);
-        // Optional
-        out.writeByteArray(mRandomizerHash);
-        // Optional
-        out.writeByteArray(mDeviceName);
-
-        // Classic
-        // Required
-        out.writeByteArray(mClassicLength);
-        // Optional
-        out.writeByteArray(mClassOfDevice);
-
-        // LE
-        // Required
-        out.writeInt(mLeDeviceRole);
-        // Required
-        out.writeByteArray(mLeTemporaryKey);
-        // Optional
-        out.writeByteArray(mLeAppearance);
-        // Optional
-        out.writeInt(mLeFlags);
-    }
-
-    // For Parcelable
-    public static final @android.annotation.NonNull Parcelable.Creator<OobData> CREATOR =
-            new Parcelable.Creator<OobData>() {
-        public OobData createFromParcel(Parcel in) {
-            return new OobData(in);
-        }
-
-        public OobData[] newArray(int size) {
-            return new OobData[size];
-        }
-    };
-
-    /**
-     * @return a {@link String} representation of the OobData object.
-     *
-     * @hide
-     */
-    @Override
-    @NonNull
-    public String toString() {
-        return "OobData: \n\t"
-            // Both
-            + "Device Address With Type: " +  toHexString(mDeviceAddressWithType) + "\n\t"
-            + "Confirmation: " + toHexString(mConfirmationHash) + "\n\t"
-            + "Randomizer: " + toHexString(mRandomizerHash) + "\n\t"
-            + "Device Name: " + toHexString(mDeviceName) + "\n\t"
-            // Classic
-            + "OobData Length: " +  toHexString(mClassicLength) + "\n\t"
-            + "Class of Device: " +  toHexString(mClassOfDevice) + "\n\t"
-            // LE
-            + "LE Device Role: " + toHexString(mLeDeviceRole) + "\n\t"
-            + "LE Temporary Key: " + toHexString(mLeTemporaryKey) + "\n\t"
-            + "LE Appearance: " + toHexString(mLeAppearance) + "\n\t"
-            + "LE Flags: " + toHexString(mLeFlags) + "\n\t";
-    }
-
-    @NonNull
-    private String toHexString(int b) {
-        return toHexString(new byte[] {(byte) b});
-    }
-
-    @NonNull
-    private String toHexString(byte b) {
-        return toHexString(new byte[] {b});
-    }
-
-    @NonNull
-    private String toHexString(byte[] array) {
-        if (array == null) return "null";
-        StringBuilder builder = new StringBuilder(array.length * 2);
-        for (byte b: array) {
-            builder.append(String.format("%02x", b));
-        }
-        return builder.toString();
-    }
-}
diff --git a/core/java/android/bluetooth/SdpDipRecord.java b/core/java/android/bluetooth/SdpDipRecord.java
deleted file mode 100644
index 84b0eef..0000000
--- a/core/java/android/bluetooth/SdpDipRecord.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR 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 java.util.Arrays;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Data representation of a Object Push Profile Server side SDP record.
- */
-/** @hide */
-public class SdpDipRecord implements Parcelable {
-    private final int mSpecificationId;
-    private final int mVendorId;
-    private final int mVendorIdSource;
-    private final int mProductId;
-    private final int mVersion;
-    private final boolean mPrimaryRecord;
-
-    public SdpDipRecord(int specificationId,
-            int vendorId, int vendorIdSource,
-            int productId, int version,
-            boolean primaryRecord) {
-        super();
-        this.mSpecificationId = specificationId;
-        this.mVendorId = vendorId;
-        this.mVendorIdSource = vendorIdSource;
-        this.mProductId = productId;
-        this.mVersion = version;
-        this.mPrimaryRecord = primaryRecord;
-    }
-
-    public SdpDipRecord(Parcel in) {
-        this.mSpecificationId = in.readInt();
-        this.mVendorId = in.readInt();
-        this.mVendorIdSource = in.readInt();
-        this.mProductId = in.readInt();
-        this.mVersion = in.readInt();
-        this.mPrimaryRecord = in.readBoolean();
-    }
-
-    public int getSpecificationId() {
-        return mSpecificationId;
-    }
-
-    public int getVendorId() {
-        return mVendorId;
-    }
-
-    public int getVendorIdSource() {
-        return mVendorIdSource;
-    }
-
-    public int getProductId() {
-        return mProductId;
-    }
-
-    public int getVersion() {
-        return mVersion;
-    }
-
-    public boolean getPrimaryRecord() {
-        return mPrimaryRecord;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mSpecificationId);
-        dest.writeInt(mVendorId);
-        dest.writeInt(mVendorIdSource);
-        dest.writeInt(mProductId);
-        dest.writeInt(mVersion);
-        dest.writeBoolean(mPrimaryRecord);
-    }
-
-    @Override
-    public int describeContents() {
-        /* No special objects */
-        return 0;
-    }
-
-    public static  final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpDipRecord createFromParcel(Parcel in) {
-            return new SdpDipRecord(in);
-        }
-        public SdpDipRecord[] newArray(int size) {
-            return new SdpDipRecord[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/SdpMasRecord.java b/core/java/android/bluetooth/SdpMasRecord.java
deleted file mode 100644
index 72d4938..0000000
--- a/core/java/android/bluetooth/SdpMasRecord.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR 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.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpMasRecord implements Parcelable {
-    private final int mMasInstanceId;
-    private final int mL2capPsm;
-    private final int mRfcommChannelNumber;
-    private final int mProfileVersion;
-    private final int mSupportedFeatures;
-    private final int mSupportedMessageTypes;
-    private final String mServiceName;
-
-    /** Message type */
-    public static final class MessageType {
-        public static final int EMAIL = 0x01;
-        public static final int SMS_GSM = 0x02;
-        public static final int SMS_CDMA = 0x04;
-        public static final int MMS = 0x08;
-    }
-
-    public SdpMasRecord(int masInstanceId,
-            int l2capPsm,
-            int rfcommChannelNumber,
-            int profileVersion,
-            int supportedFeatures,
-            int supportedMessageTypes,
-            String serviceName) {
-        mMasInstanceId = masInstanceId;
-        mL2capPsm = l2capPsm;
-        mRfcommChannelNumber = rfcommChannelNumber;
-        mProfileVersion = profileVersion;
-        mSupportedFeatures = supportedFeatures;
-        mSupportedMessageTypes = supportedMessageTypes;
-        mServiceName = serviceName;
-    }
-
-    public SdpMasRecord(Parcel in) {
-        mMasInstanceId = in.readInt();
-        mL2capPsm = in.readInt();
-        mRfcommChannelNumber = in.readInt();
-        mProfileVersion = in.readInt();
-        mSupportedFeatures = in.readInt();
-        mSupportedMessageTypes = in.readInt();
-        mServiceName = in.readString();
-    }
-
-    @Override
-    public int describeContents() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    public int getMasInstanceId() {
-        return mMasInstanceId;
-    }
-
-    public int getL2capPsm() {
-        return mL2capPsm;
-    }
-
-    public int getRfcommCannelNumber() {
-        return mRfcommChannelNumber;
-    }
-
-    public int getProfileVersion() {
-        return mProfileVersion;
-    }
-
-    public int getSupportedFeatures() {
-        return mSupportedFeatures;
-    }
-
-    public int getSupportedMessageTypes() {
-        return mSupportedMessageTypes;
-    }
-
-    public boolean msgSupported(int msg) {
-        return (mSupportedMessageTypes & msg) != 0;
-    }
-
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mMasInstanceId);
-        dest.writeInt(mL2capPsm);
-        dest.writeInt(mRfcommChannelNumber);
-        dest.writeInt(mProfileVersion);
-        dest.writeInt(mSupportedFeatures);
-        dest.writeInt(mSupportedMessageTypes);
-        dest.writeString(mServiceName);
-    }
-
-    @Override
-    public String toString() {
-        String ret = "Bluetooth MAS SDP Record:\n";
-
-        if (mMasInstanceId != -1) {
-            ret += "Mas Instance Id: " + mMasInstanceId + "\n";
-        }
-        if (mRfcommChannelNumber != -1) {
-            ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
-        }
-        if (mL2capPsm != -1) {
-            ret += "L2CAP PSM: " + mL2capPsm + "\n";
-        }
-        if (mServiceName != null) {
-            ret += "Service Name: " + mServiceName + "\n";
-        }
-        if (mProfileVersion != -1) {
-            ret += "Profile version: " + mProfileVersion + "\n";
-        }
-        if (mSupportedMessageTypes != -1) {
-            ret += "Supported msg types: " + mSupportedMessageTypes + "\n";
-        }
-        if (mSupportedFeatures != -1) {
-            ret += "Supported features: " + mSupportedFeatures + "\n";
-        }
-        return ret;
-    }
-
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpMasRecord createFromParcel(Parcel in) {
-            return new SdpMasRecord(in);
-        }
-
-        public SdpRecord[] newArray(int size) {
-            return new SdpRecord[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/SdpMnsRecord.java b/core/java/android/bluetooth/SdpMnsRecord.java
deleted file mode 100644
index a781d5d..0000000
--- a/core/java/android/bluetooth/SdpMnsRecord.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR 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.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpMnsRecord implements Parcelable {
-    private final int mL2capPsm;
-    private final int mRfcommChannelNumber;
-    private final int mSupportedFeatures;
-    private final int mProfileVersion;
-    private final String mServiceName;
-
-    public SdpMnsRecord(int l2capPsm,
-            int rfcommChannelNumber,
-            int profileVersion,
-            int supportedFeatures,
-            String serviceName) {
-        mL2capPsm = l2capPsm;
-        mRfcommChannelNumber = rfcommChannelNumber;
-        mSupportedFeatures = supportedFeatures;
-        mServiceName = serviceName;
-        mProfileVersion = profileVersion;
-    }
-
-    public SdpMnsRecord(Parcel in) {
-        mRfcommChannelNumber = in.readInt();
-        mL2capPsm = in.readInt();
-        mServiceName = in.readString();
-        mSupportedFeatures = in.readInt();
-        mProfileVersion = in.readInt();
-    }
-
-    @Override
-    public int describeContents() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-
-    public int getL2capPsm() {
-        return mL2capPsm;
-    }
-
-    public int getRfcommChannelNumber() {
-        return mRfcommChannelNumber;
-    }
-
-    public int getSupportedFeatures() {
-        return mSupportedFeatures;
-    }
-
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    public int getProfileVersion() {
-        return mProfileVersion;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRfcommChannelNumber);
-        dest.writeInt(mL2capPsm);
-        dest.writeString(mServiceName);
-        dest.writeInt(mSupportedFeatures);
-        dest.writeInt(mProfileVersion);
-    }
-
-    public String toString() {
-        String ret = "Bluetooth MNS SDP Record:\n";
-
-        if (mRfcommChannelNumber != -1) {
-            ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
-        }
-        if (mL2capPsm != -1) {
-            ret += "L2CAP PSM: " + mL2capPsm + "\n";
-        }
-        if (mServiceName != null) {
-            ret += "Service Name: " + mServiceName + "\n";
-        }
-        if (mSupportedFeatures != -1) {
-            ret += "Supported features: " + mSupportedFeatures + "\n";
-        }
-        if (mProfileVersion != -1) {
-            ret += "Profile_version: " + mProfileVersion + "\n";
-        }
-        return ret;
-    }
-
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpMnsRecord createFromParcel(Parcel in) {
-            return new SdpMnsRecord(in);
-        }
-
-        public SdpMnsRecord[] newArray(int size) {
-            return new SdpMnsRecord[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/SdpOppOpsRecord.java b/core/java/android/bluetooth/SdpOppOpsRecord.java
deleted file mode 100644
index e30745b8..0000000
--- a/core/java/android/bluetooth/SdpOppOpsRecord.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR 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.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * Data representation of a Object Push Profile Server side SDP record.
- */
-
-/** @hide */
-public class SdpOppOpsRecord implements Parcelable {
-
-    private final String mServiceName;
-    private final int mRfcommChannel;
-    private final int mL2capPsm;
-    private final int mProfileVersion;
-    private final byte[] mFormatsList;
-
-    public SdpOppOpsRecord(String serviceName, int rfcommChannel,
-            int l2capPsm, int version, byte[] formatsList) {
-        super();
-        mServiceName = serviceName;
-        mRfcommChannel = rfcommChannel;
-        mL2capPsm = l2capPsm;
-        mProfileVersion = version;
-        mFormatsList = formatsList;
-    }
-
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    public int getRfcommChannel() {
-        return mRfcommChannel;
-    }
-
-    public int getL2capPsm() {
-        return mL2capPsm;
-    }
-
-    public int getProfileVersion() {
-        return mProfileVersion;
-    }
-
-    public byte[] getFormatsList() {
-        return mFormatsList;
-    }
-
-    @Override
-    public int describeContents() {
-        /* No special objects */
-        return 0;
-    }
-
-    public SdpOppOpsRecord(Parcel in) {
-        mRfcommChannel = in.readInt();
-        mL2capPsm = in.readInt();
-        mProfileVersion = in.readInt();
-        mServiceName = in.readString();
-        int arrayLength = in.readInt();
-        if (arrayLength > 0) {
-            byte[] bytes = new byte[arrayLength];
-            in.readByteArray(bytes);
-            mFormatsList = bytes;
-        } else {
-            mFormatsList = null;
-        }
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRfcommChannel);
-        dest.writeInt(mL2capPsm);
-        dest.writeInt(mProfileVersion);
-        dest.writeString(mServiceName);
-        if (mFormatsList != null && mFormatsList.length > 0) {
-            dest.writeInt(mFormatsList.length);
-            dest.writeByteArray(mFormatsList);
-        } else {
-            dest.writeInt(0);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("Bluetooth OPP Server SDP Record:\n");
-        sb.append("  RFCOMM Chan Number: ").append(mRfcommChannel);
-        sb.append("\n  L2CAP PSM: ").append(mL2capPsm);
-        sb.append("\n  Profile version: ").append(mProfileVersion);
-        sb.append("\n  Service Name: ").append(mServiceName);
-        sb.append("\n  Formats List: ").append(Arrays.toString(mFormatsList));
-        return sb.toString();
-    }
-
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpOppOpsRecord createFromParcel(Parcel in) {
-            return new SdpOppOpsRecord(in);
-        }
-
-        public SdpOppOpsRecord[] newArray(int size) {
-            return new SdpOppOpsRecord[size];
-        }
-    };
-
-}
diff --git a/core/java/android/bluetooth/SdpPseRecord.java b/core/java/android/bluetooth/SdpPseRecord.java
deleted file mode 100644
index 72249d0..0000000
--- a/core/java/android/bluetooth/SdpPseRecord.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR 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.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpPseRecord implements Parcelable {
-    private final int mL2capPsm;
-    private final int mRfcommChannelNumber;
-    private final int mProfileVersion;
-    private final int mSupportedFeatures;
-    private final int mSupportedRepositories;
-    private final String mServiceName;
-
-    public SdpPseRecord(int l2capPsm,
-            int rfcommChannelNumber,
-            int profileVersion,
-            int supportedFeatures,
-            int supportedRepositories,
-            String serviceName) {
-        mL2capPsm = l2capPsm;
-        mRfcommChannelNumber = rfcommChannelNumber;
-        mProfileVersion = profileVersion;
-        mSupportedFeatures = supportedFeatures;
-        mSupportedRepositories = supportedRepositories;
-        mServiceName = serviceName;
-    }
-
-    public SdpPseRecord(Parcel in) {
-        mRfcommChannelNumber = in.readInt();
-        mL2capPsm = in.readInt();
-        mProfileVersion = in.readInt();
-        mSupportedFeatures = in.readInt();
-        mSupportedRepositories = in.readInt();
-        mServiceName = in.readString();
-    }
-
-    @Override
-    public int describeContents() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    public int getL2capPsm() {
-        return mL2capPsm;
-    }
-
-    public int getRfcommChannelNumber() {
-        return mRfcommChannelNumber;
-    }
-
-    public int getSupportedFeatures() {
-        return mSupportedFeatures;
-    }
-
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    public int getProfileVersion() {
-        return mProfileVersion;
-    }
-
-    public int getSupportedRepositories() {
-        return mSupportedRepositories;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRfcommChannelNumber);
-        dest.writeInt(mL2capPsm);
-        dest.writeInt(mProfileVersion);
-        dest.writeInt(mSupportedFeatures);
-        dest.writeInt(mSupportedRepositories);
-        dest.writeString(mServiceName);
-
-    }
-
-    @Override
-    public String toString() {
-        String ret = "Bluetooth MNS SDP Record:\n";
-
-        if (mRfcommChannelNumber != -1) {
-            ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
-        }
-        if (mL2capPsm != -1) {
-            ret += "L2CAP PSM: " + mL2capPsm + "\n";
-        }
-        if (mProfileVersion != -1) {
-            ret += "profile version: " + mProfileVersion + "\n";
-        }
-        if (mServiceName != null) {
-            ret += "Service Name: " + mServiceName + "\n";
-        }
-        if (mSupportedFeatures != -1) {
-            ret += "Supported features: " + mSupportedFeatures + "\n";
-        }
-        if (mSupportedRepositories != -1) {
-            ret += "Supported repositories: " + mSupportedRepositories + "\n";
-        }
-
-        return ret;
-    }
-
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpPseRecord createFromParcel(Parcel in) {
-            return new SdpPseRecord(in);
-        }
-
-        public SdpPseRecord[] newArray(int size) {
-            return new SdpPseRecord[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/SdpRecord.java b/core/java/android/bluetooth/SdpRecord.java
deleted file mode 100644
index 730862e..0000000
--- a/core/java/android/bluetooth/SdpRecord.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-* Copyright (C) 2015 Samsung System LSI
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR 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.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/** @hide */
-public class SdpRecord implements Parcelable {
-
-    private final byte[] mRawData;
-    private final int mRawSize;
-
-    @Override
-    public String toString() {
-        return "BluetoothSdpRecord [rawData=" + Arrays.toString(mRawData)
-                + ", rawSize=" + mRawSize + "]";
-    }
-
-    public SdpRecord(int sizeRecord, byte[] record) {
-        mRawData = record;
-        mRawSize = sizeRecord;
-    }
-
-    public SdpRecord(Parcel in) {
-        mRawSize = in.readInt();
-        mRawData = new byte[mRawSize];
-        in.readByteArray(mRawData);
-
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRawSize);
-        dest.writeByteArray(mRawData);
-
-
-    }
-
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpRecord createFromParcel(Parcel in) {
-            return new SdpRecord(in);
-        }
-
-        public SdpRecord[] newArray(int size) {
-            return new SdpRecord[size];
-        }
-    };
-
-    public byte[] getRawData() {
-        return mRawData;
-    }
-
-    public int getRawSize() {
-        return mRawSize;
-    }
-}
diff --git a/core/java/android/bluetooth/SdpSapsRecord.java b/core/java/android/bluetooth/SdpSapsRecord.java
deleted file mode 100644
index a1e2f7b..0000000
--- a/core/java/android/bluetooth/SdpSapsRecord.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class SdpSapsRecord implements Parcelable {
-    private final int mRfcommChannelNumber;
-    private final int mProfileVersion;
-    private final String mServiceName;
-
-    public SdpSapsRecord(int rfcommChannelNumber, int profileVersion, String serviceName) {
-        mRfcommChannelNumber = rfcommChannelNumber;
-        mProfileVersion = profileVersion;
-        mServiceName = serviceName;
-    }
-
-    public SdpSapsRecord(Parcel in) {
-        mRfcommChannelNumber = in.readInt();
-        mProfileVersion = in.readInt();
-        mServiceName = in.readString();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public int getRfcommCannelNumber() {
-        return mRfcommChannelNumber;
-    }
-
-    public int getProfileVersion() {
-        return mProfileVersion;
-    }
-
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRfcommChannelNumber);
-        dest.writeInt(mProfileVersion);
-        dest.writeString(mServiceName);
-
-    }
-
-    @Override
-    public String toString() {
-        String ret = "Bluetooth MAS SDP Record:\n";
-
-        if (mRfcommChannelNumber != -1) {
-            ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n";
-        }
-        if (mServiceName != null) {
-            ret += "Service Name: " + mServiceName + "\n";
-        }
-        if (mProfileVersion != -1) {
-            ret += "Profile version: " + mProfileVersion + "\n";
-        }
-        return ret;
-    }
-
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
-        public SdpSapsRecord createFromParcel(Parcel in) {
-            return new SdpSapsRecord(in);
-        }
-
-        public SdpRecord[] newArray(int size) {
-            return new SdpRecord[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/UidTraffic.java b/core/java/android/bluetooth/UidTraffic.java
deleted file mode 100644
index 9982fa6..0000000
--- a/core/java/android/bluetooth/UidTraffic.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.bluetooth;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Record of data traffic (in bytes) by an application identified by its UID.
- *
- * @hide
- */
-@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
-public final class UidTraffic implements Cloneable, Parcelable {
-    private final int mAppUid;
-    private long mRxBytes;
-    private long mTxBytes;
-
-    /** @hide */
-    public UidTraffic(int appUid, long rx, long tx) {
-        mAppUid = appUid;
-        mRxBytes = rx;
-        mTxBytes = tx;
-    }
-
-    /** @hide */
-    private UidTraffic(Parcel in) {
-        mAppUid = in.readInt();
-        mRxBytes = in.readLong();
-        mTxBytes = in.readLong();
-    }
-
-    /** @hide */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mAppUid);
-        dest.writeLong(mRxBytes);
-        dest.writeLong(mTxBytes);
-    }
-
-    /** @hide */
-    public void setRxBytes(long bytes) {
-        mRxBytes = bytes;
-    }
-
-    /** @hide */
-    public void setTxBytes(long bytes) {
-        mTxBytes = bytes;
-    }
-
-    /** @hide */
-    public void addRxBytes(long bytes) {
-        mRxBytes += bytes;
-    }
-
-    /** @hide */
-    public void addTxBytes(long bytes) {
-        mTxBytes += bytes;
-    }
-
-    /**
-     * @return corresponding app Uid
-     */
-    public int getUid() {
-        return mAppUid;
-    }
-
-    /**
-     * @return rx bytes count
-     */
-    public long getRxBytes() {
-        return mRxBytes;
-    }
-
-    /**
-     * @return tx bytes count
-     */
-    public long getTxBytes() {
-        return mTxBytes;
-    }
-
-    /** @hide */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** @hide */
-    @Override
-    public UidTraffic clone() {
-        return new UidTraffic(mAppUid, mRxBytes, mTxBytes);
-    }
-
-    /** @hide */
-    @Override
-    public String toString() {
-        return "UidTraffic{mAppUid=" + mAppUid + ", mRxBytes=" + mRxBytes + ", mTxBytes="
-                + mTxBytes + '}';
-    }
-
-    public static final @android.annotation.NonNull Creator<UidTraffic> CREATOR = new Creator<UidTraffic>() {
-        @Override
-        public UidTraffic createFromParcel(Parcel source) {
-            return new UidTraffic(source);
-        }
-
-        @Override
-        public UidTraffic[] newArray(int size) {
-            return new UidTraffic[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothAdvertisePermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothAdvertisePermission.java
deleted file mode 100644
index c508c2c..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothAdvertisePermission.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#S} or or higher,
- *            this requires the {@link Manifest.permission#BLUETOOTH_ADVERTISE}
- *            permission which can be gained with
- *            {@link android.app.Activity#requestPermissions(String[], int)}.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothAdvertisePermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothConnectPermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothConnectPermission.java
deleted file mode 100644
index e159eaa..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothConnectPermission.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#S} or or higher,
- *            this requires the {@link Manifest.permission#BLUETOOTH_CONNECT}
- *            permission which can be gained with
- *            {@link android.app.Activity#requestPermissions(String[], int)}.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothConnectPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothLocationPermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothLocationPermission.java
deleted file mode 100644
index 2bb3204..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothLocationPermission.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc In addition, this requires either the
- *            {@link Manifest.permission#ACCESS_FINE_LOCATION}
- *            permission or a strong assertion that you will never derive the
- *            physical location of the device. You can make this assertion by
- *            declaring {@code usesPermissionFlags="neverForLocation"} on the
- *            relevant {@code <uses-permission>} manifest tag, but it may
- *            restrict the types of Bluetooth devices you can interact with.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothLocationPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresBluetoothScanPermission.java b/core/java/android/bluetooth/annotations/RequiresBluetoothScanPermission.java
deleted file mode 100644
index 800ff39..0000000
--- a/core/java/android/bluetooth/annotations/RequiresBluetoothScanPermission.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#S} or or higher,
- *            this requires the {@link Manifest.permission#BLUETOOTH_SCAN}
- *            permission which can be gained with
- *            {@link android.app.Activity#requestPermissions(String[], int)}.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresBluetoothScanPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothAdminPermission.java b/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothAdminPermission.java
deleted file mode 100644
index 9adf695..0000000
--- a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothAdminPermission.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#R} or lower, this
- *            requires the {@link Manifest.permission#BLUETOOTH_ADMIN}
- *            permission which can be gained with a simple
- *            {@code <uses-permission>} manifest tag.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresLegacyBluetoothAdminPermission {
-}
diff --git a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothPermission.java b/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothPermission.java
deleted file mode 100644
index 79621c3..0000000
--- a/core/java/android/bluetooth/annotations/RequiresLegacyBluetoothPermission.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.bluetooth.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.Manifest;
-import android.os.Build;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * @memberDoc For apps targeting {@link Build.VERSION_CODES#R} or lower, this
- *            requires the {@link Manifest.permission#BLUETOOTH} permission
- *            which can be gained with a simple {@code <uses-permission>}
- *            manifest tag.
- * @hide
- */
-@Retention(SOURCE)
-@Target({METHOD, FIELD})
-public @interface RequiresLegacyBluetoothPermission {
-}
diff --git a/core/java/android/bluetooth/le/AdvertiseCallback.java b/core/java/android/bluetooth/le/AdvertiseCallback.java
deleted file mode 100644
index 4fa8c4f..0000000
--- a/core/java/android/bluetooth/le/AdvertiseCallback.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-/**
- * Bluetooth LE advertising callbacks, used to deliver advertising operation status.
- */
-public abstract class AdvertiseCallback {
-
-    /**
-     * The requested operation was successful.
-     *
-     * @hide
-     */
-    public static final int ADVERTISE_SUCCESS = 0;
-
-    /**
-     * Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.
-     */
-    public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;
-
-    /**
-     * Failed to start advertising because no advertising instance is available.
-     */
-    public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2;
-
-    /**
-     * Failed to start advertising as the advertising is already started.
-     */
-    public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3;
-
-    /**
-     * Operation failed due to an internal error.
-     */
-    public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4;
-
-    /**
-     * This feature is not supported on this platform.
-     */
-    public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5;
-
-    /**
-     * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertising} indicating
-     * that the advertising has been started successfully.
-     *
-     * @param settingsInEffect The actual settings used for advertising, which may be different from
-     * what has been requested.
-     */
-    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
-    }
-
-    /**
-     * Callback when advertising could not be started.
-     *
-     * @param errorCode Error code (see ADVERTISE_FAILED_* constants) for advertising start
-     * failures.
-     */
-    public void onStartFailure(int errorCode) {
-    }
-}
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
deleted file mode 100644
index fdf62ec..0000000
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-import android.util.ArrayMap;
-import android.util.SparseArray;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Advertise data packet container for Bluetooth LE advertising. This represents the data to be
- * advertised as well as the scan response data for active scans.
- * <p>
- * Use {@link AdvertiseData.Builder} to create an instance of {@link AdvertiseData} to be
- * advertised.
- *
- * @see BluetoothLeAdvertiser
- * @see ScanRecord
- */
-public final class AdvertiseData implements Parcelable {
-
-    @Nullable
-    private final List<ParcelUuid> mServiceUuids;
-
-    @NonNull
-    private final List<ParcelUuid> mServiceSolicitationUuids;
-
-    @Nullable
-    private final List<TransportDiscoveryData> mTransportDiscoveryData;
-
-    private final SparseArray<byte[]> mManufacturerSpecificData;
-    private final Map<ParcelUuid, byte[]> mServiceData;
-    private final boolean mIncludeTxPowerLevel;
-    private final boolean mIncludeDeviceName;
-
-    private AdvertiseData(List<ParcelUuid> serviceUuids,
-            List<ParcelUuid> serviceSolicitationUuids,
-            List<TransportDiscoveryData> transportDiscoveryData,
-            SparseArray<byte[]> manufacturerData,
-            Map<ParcelUuid, byte[]> serviceData,
-            boolean includeTxPowerLevel,
-            boolean includeDeviceName) {
-        mServiceUuids = serviceUuids;
-        mServiceSolicitationUuids = serviceSolicitationUuids;
-        mTransportDiscoveryData = transportDiscoveryData;
-        mManufacturerSpecificData = manufacturerData;
-        mServiceData = serviceData;
-        mIncludeTxPowerLevel = includeTxPowerLevel;
-        mIncludeDeviceName = includeDeviceName;
-    }
-
-    /**
-     * Returns a list of service UUIDs within the advertisement that are used to identify the
-     * Bluetooth GATT services.
-     */
-    public List<ParcelUuid> getServiceUuids() {
-        return mServiceUuids;
-    }
-
-    /**
-     * Returns a list of service solicitation UUIDs within the advertisement that we invite to connect.
-     */
-    @NonNull
-    public List<ParcelUuid> getServiceSolicitationUuids() {
-        return mServiceSolicitationUuids;
-    }
-
-    /**
-     * Returns a list of {@link TransportDiscoveryData} within the advertisement.
-     */
-    @NonNull
-    public List<TransportDiscoveryData> getTransportDiscoveryData() {
-        if (mTransportDiscoveryData == null) {
-            return Collections.emptyList();
-        }
-        return mTransportDiscoveryData;
-    }
-
-    /**
-     * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The
-     * manufacturer id is a non-negative number assigned by Bluetooth SIG.
-     */
-    public SparseArray<byte[]> getManufacturerSpecificData() {
-        return mManufacturerSpecificData;
-    }
-
-    /**
-     * Returns a map of 16-bit UUID and its corresponding service data.
-     */
-    public Map<ParcelUuid, byte[]> getServiceData() {
-        return mServiceData;
-    }
-
-    /**
-     * Whether the transmission power level will be included in the advertisement packet.
-     */
-    public boolean getIncludeTxPowerLevel() {
-        return mIncludeTxPowerLevel;
-    }
-
-    /**
-     * Whether the device name will be included in the advertisement packet.
-     */
-    public boolean getIncludeDeviceName() {
-        return mIncludeDeviceName;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public int hashCode() {
-        return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mTransportDiscoveryData,
-                mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        AdvertiseData other = (AdvertiseData) obj;
-        return Objects.equals(mServiceUuids, other.mServiceUuids)
-                && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids)
-                && Objects.equals(mTransportDiscoveryData, other.mTransportDiscoveryData)
-                && BluetoothLeUtils.equals(mManufacturerSpecificData,
-                    other.mManufacturerSpecificData)
-                && BluetoothLeUtils.equals(mServiceData, other.mServiceData)
-                && mIncludeDeviceName == other.mIncludeDeviceName
-                && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel;
-    }
-
-    @Override
-    public String toString() {
-        return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids="
-                + mServiceSolicitationUuids + ", mTransportDiscoveryData="
-                + mTransportDiscoveryData + ", mManufacturerSpecificData="
-                + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData="
-                + BluetoothLeUtils.toString(mServiceData)
-                + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
-                + mIncludeDeviceName + "]";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeTypedArray(mServiceUuids.toArray(new ParcelUuid[mServiceUuids.size()]), flags);
-        dest.writeTypedArray(mServiceSolicitationUuids.toArray(
-                new ParcelUuid[mServiceSolicitationUuids.size()]), flags);
-
-        dest.writeTypedList(mTransportDiscoveryData);
-
-        // mManufacturerSpecificData could not be null.
-        dest.writeInt(mManufacturerSpecificData.size());
-        for (int i = 0; i < mManufacturerSpecificData.size(); ++i) {
-            dest.writeInt(mManufacturerSpecificData.keyAt(i));
-            dest.writeByteArray(mManufacturerSpecificData.valueAt(i));
-        }
-        dest.writeInt(mServiceData.size());
-        for (ParcelUuid uuid : mServiceData.keySet()) {
-            dest.writeTypedObject(uuid, flags);
-            dest.writeByteArray(mServiceData.get(uuid));
-        }
-        dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0));
-        dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0));
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseData> CREATOR =
-            new Creator<AdvertiseData>() {
-                @Override
-                public AdvertiseData[] newArray(int size) {
-                    return new AdvertiseData[size];
-                }
-
-                @Override
-                public AdvertiseData createFromParcel(Parcel in) {
-                    Builder builder = new Builder();
-                    ArrayList<ParcelUuid> uuids = in.createTypedArrayList(ParcelUuid.CREATOR);
-                    for (ParcelUuid uuid : uuids) {
-                        builder.addServiceUuid(uuid);
-                    }
-
-                    ArrayList<ParcelUuid> solicitationUuids = in.createTypedArrayList(ParcelUuid.CREATOR);
-                    for (ParcelUuid uuid : solicitationUuids) {
-                        builder.addServiceSolicitationUuid(uuid);
-                    }
-
-                    List<TransportDiscoveryData> transportDiscoveryData =
-                            in.createTypedArrayList(TransportDiscoveryData.CREATOR);
-                    for (TransportDiscoveryData tdd : transportDiscoveryData) {
-                        builder.addTransportDiscoveryData(tdd);
-                    }
-
-                    int manufacturerSize = in.readInt();
-                    for (int i = 0; i < manufacturerSize; ++i) {
-                        int manufacturerId = in.readInt();
-                        byte[] manufacturerData = in.createByteArray();
-                        builder.addManufacturerData(manufacturerId, manufacturerData);
-                    }
-                    int serviceDataSize = in.readInt();
-                    for (int i = 0; i < serviceDataSize; ++i) {
-                        ParcelUuid serviceDataUuid = in.readTypedObject(ParcelUuid.CREATOR);
-                        byte[] serviceData = in.createByteArray();
-                        builder.addServiceData(serviceDataUuid, serviceData);
-                    }
-                    builder.setIncludeTxPowerLevel(in.readByte() == 1);
-                    builder.setIncludeDeviceName(in.readByte() == 1);
-                    return builder.build();
-                }
-            };
-
-    /**
-     * Builder for {@link AdvertiseData}.
-     */
-    public static final class Builder {
-        @Nullable
-        private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
-        @NonNull
-        private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>();
-        @Nullable
-        private List<TransportDiscoveryData> mTransportDiscoveryData =
-                new ArrayList<TransportDiscoveryData>();
-        private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>();
-        private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>();
-        private boolean mIncludeTxPowerLevel;
-        private boolean mIncludeDeviceName;
-
-        /**
-         * Add a service UUID to advertise data.
-         *
-         * @param serviceUuid A service UUID to be advertised.
-         * @throws IllegalArgumentException If the {@code serviceUuid} is null.
-         */
-        public Builder addServiceUuid(ParcelUuid serviceUuid) {
-            if (serviceUuid == null) {
-                throw new IllegalArgumentException("serviceUuid is null");
-            }
-            mServiceUuids.add(serviceUuid);
-            return this;
-        }
-
-        /**
-         * Add a service solicitation UUID to advertise data.
-         *
-         * @param serviceSolicitationUuid A service solicitation UUID to be advertised.
-         * @throws IllegalArgumentException If the {@code serviceSolicitationUuid} is null.
-         */
-        @NonNull
-        public Builder addServiceSolicitationUuid(@NonNull ParcelUuid serviceSolicitationUuid) {
-            if (serviceSolicitationUuid == null) {
-                throw new IllegalArgumentException("serviceSolicitationUuid is null");
-            }
-            mServiceSolicitationUuids.add(serviceSolicitationUuid);
-            return this;
-        }
-
-        /**
-         * Add service data to advertise data.
-         *
-         * @param serviceDataUuid 16-bit UUID of the service the data is associated with
-         * @param serviceData Service data
-         * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is
-         * empty.
-         */
-        public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
-            if (serviceDataUuid == null || serviceData == null) {
-                throw new IllegalArgumentException(
-                        "serviceDataUuid or serviceDataUuid is null");
-            }
-            mServiceData.put(serviceDataUuid, serviceData);
-            return this;
-        }
-
-        /**
-         * Add Transport Discovery Data to advertise data.
-         *
-         * @param transportDiscoveryData Transport Discovery Data, consisting of one or more
-         * Transport Blocks. Transport Discovery Data AD Type Code is already included.
-         * @throws IllegalArgumentException If the {@code transportDiscoveryData} is empty
-         */
-        @NonNull
-        public Builder addTransportDiscoveryData(
-                @NonNull TransportDiscoveryData transportDiscoveryData) {
-            if (transportDiscoveryData == null) {
-                throw new IllegalArgumentException("transportDiscoveryData is null");
-            }
-            mTransportDiscoveryData.add(transportDiscoveryData);
-            return this;
-        }
-
-        /**
-         * Add manufacturer specific data.
-         * <p>
-         * Please refer to the Bluetooth Assigned Numbers document provided by the <a
-         * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company
-         * identifiers.
-         *
-         * @param manufacturerId Manufacturer ID assigned by Bluetooth SIG.
-         * @param manufacturerSpecificData Manufacturer specific data
-         * @throws IllegalArgumentException If the {@code manufacturerId} is negative or {@code
-         * manufacturerSpecificData} is null.
-         */
-        public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) {
-            if (manufacturerId < 0) {
-                throw new IllegalArgumentException(
-                        "invalid manufacturerId - " + manufacturerId);
-            }
-            if (manufacturerSpecificData == null) {
-                throw new IllegalArgumentException("manufacturerSpecificData is null");
-            }
-            mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData);
-            return this;
-        }
-
-        /**
-         * Whether the transmission power level should be included in the advertise packet. Tx power
-         * level field takes 3 bytes in advertise packet.
-         */
-        public Builder setIncludeTxPowerLevel(boolean includeTxPowerLevel) {
-            mIncludeTxPowerLevel = includeTxPowerLevel;
-            return this;
-        }
-
-        /**
-         * Set whether the device name should be included in advertise packet.
-         */
-        public Builder setIncludeDeviceName(boolean includeDeviceName) {
-            mIncludeDeviceName = includeDeviceName;
-            return this;
-        }
-
-        /**
-         * Build the {@link AdvertiseData}.
-         */
-        public AdvertiseData build() {
-            return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids,
-                    mTransportDiscoveryData, mManufacturerSpecificData, mServiceData,
-                    mIncludeTxPowerLevel, mIncludeDeviceName);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java
deleted file mode 100644
index c52a6ee..0000000
--- a/core/java/android/bluetooth/le/AdvertiseSettings.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.bluetooth.le.AdvertisingSetParameters.AddressTypeStatus;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * The {@link AdvertiseSettings} provide a way to adjust advertising preferences for each
- * Bluetooth LE advertisement instance. Use {@link AdvertiseSettings.Builder} to create an
- * instance of this class.
- */
-public final class AdvertiseSettings implements Parcelable {
-    /**
-     * Perform Bluetooth LE advertising in low power mode. This is the default and preferred
-     * advertising mode as it consumes the least power.
-     */
-    public static final int ADVERTISE_MODE_LOW_POWER = 0;
-
-    /**
-     * Perform Bluetooth LE advertising in balanced power mode. This is balanced between advertising
-     * frequency and power consumption.
-     */
-    public static final int ADVERTISE_MODE_BALANCED = 1;
-
-    /**
-     * Perform Bluetooth LE advertising in low latency, high power mode. This has the highest power
-     * consumption and should not be used for continuous background advertising.
-     */
-    public static final int ADVERTISE_MODE_LOW_LATENCY = 2;
-
-    /**
-     * Advertise using the lowest transmission (TX) power level. Low transmission power can be used
-     * to restrict the visibility range of advertising packets.
-     */
-    public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0;
-
-    /**
-     * Advertise using low TX power level.
-     */
-    public static final int ADVERTISE_TX_POWER_LOW = 1;
-
-    /**
-     * Advertise using medium TX power level.
-     */
-    public static final int ADVERTISE_TX_POWER_MEDIUM = 2;
-
-    /**
-     * Advertise using high TX power level. This corresponds to largest visibility range of the
-     * advertising packet.
-     */
-    public static final int ADVERTISE_TX_POWER_HIGH = 3;
-
-    /**
-     * The maximum limited advertisement duration as specified by the Bluetooth SIG
-     */
-    private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
-
-
-    private final int mAdvertiseMode;
-    private final int mAdvertiseTxPowerLevel;
-    private final int mAdvertiseTimeoutMillis;
-    private final boolean mAdvertiseConnectable;
-    private final int mOwnAddressType;
-
-    private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel,
-            boolean advertiseConnectable, int advertiseTimeout,
-            @AddressTypeStatus int ownAddressType) {
-        mAdvertiseMode = advertiseMode;
-        mAdvertiseTxPowerLevel = advertiseTxPowerLevel;
-        mAdvertiseConnectable = advertiseConnectable;
-        mAdvertiseTimeoutMillis = advertiseTimeout;
-        mOwnAddressType = ownAddressType;
-    }
-
-    private AdvertiseSettings(Parcel in) {
-        mAdvertiseMode = in.readInt();
-        mAdvertiseTxPowerLevel = in.readInt();
-        mAdvertiseConnectable = in.readInt() != 0;
-        mAdvertiseTimeoutMillis = in.readInt();
-        mOwnAddressType = in.readInt();
-    }
-
-    /**
-     * Returns the advertise mode.
-     */
-    public int getMode() {
-        return mAdvertiseMode;
-    }
-
-    /**
-     * Returns the TX power level for advertising.
-     */
-    public int getTxPowerLevel() {
-        return mAdvertiseTxPowerLevel;
-    }
-
-    /**
-     * Returns whether the advertisement will indicate connectable.
-     */
-    public boolean isConnectable() {
-        return mAdvertiseConnectable;
-    }
-
-    /**
-     * Returns the advertising time limit in milliseconds.
-     */
-    public int getTimeout() {
-        return mAdvertiseTimeoutMillis;
-    }
-
-    /**
-     * @return the own address type for advertising
-     *
-     * @hide
-     */
-    @SystemApi
-    public @AddressTypeStatus int getOwnAddressType() {
-        return mOwnAddressType;
-    }
-
-    @Override
-    public String toString() {
-        return "Settings [mAdvertiseMode=" + mAdvertiseMode
-                + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel
-                + ", mAdvertiseConnectable=" + mAdvertiseConnectable
-                + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis
-                + ", mOwnAddressType=" + mOwnAddressType + "]";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mAdvertiseMode);
-        dest.writeInt(mAdvertiseTxPowerLevel);
-        dest.writeInt(mAdvertiseConnectable ? 1 : 0);
-        dest.writeInt(mAdvertiseTimeoutMillis);
-        dest.writeInt(mOwnAddressType);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseSettings> CREATOR =
-            new Creator<AdvertiseSettings>() {
-                @Override
-                public AdvertiseSettings[] newArray(int size) {
-                    return new AdvertiseSettings[size];
-                }
-
-                @Override
-                public AdvertiseSettings createFromParcel(Parcel in) {
-                    return new AdvertiseSettings(in);
-                }
-            };
-
-    /**
-     * Builder class for {@link AdvertiseSettings}.
-     */
-    public static final class Builder {
-        private int mMode = ADVERTISE_MODE_LOW_POWER;
-        private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM;
-        private int mTimeoutMillis = 0;
-        private boolean mConnectable = true;
-        private int mOwnAddressType = AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT;
-
-        /**
-         * Set advertise mode to control the advertising power and latency.
-         *
-         * @param advertiseMode Bluetooth LE Advertising mode, can only be one of {@link
-         * AdvertiseSettings#ADVERTISE_MODE_LOW_POWER},
-         * {@link AdvertiseSettings#ADVERTISE_MODE_BALANCED},
-         * or {@link AdvertiseSettings#ADVERTISE_MODE_LOW_LATENCY}.
-         * @throws IllegalArgumentException If the advertiseMode is invalid.
-         */
-        public Builder setAdvertiseMode(int advertiseMode) {
-            if (advertiseMode < ADVERTISE_MODE_LOW_POWER
-                    || advertiseMode > ADVERTISE_MODE_LOW_LATENCY) {
-                throw new IllegalArgumentException("unknown mode " + advertiseMode);
-            }
-            mMode = advertiseMode;
-            return this;
-        }
-
-        /**
-         * Set advertise TX power level to control the transmission power level for the advertising.
-         *
-         * @param txPowerLevel Transmission power of Bluetooth LE Advertising, can only be one of
-         * {@link AdvertiseSettings#ADVERTISE_TX_POWER_ULTRA_LOW}, {@link
-         * AdvertiseSettings#ADVERTISE_TX_POWER_LOW},
-         * {@link AdvertiseSettings#ADVERTISE_TX_POWER_MEDIUM}
-         * or {@link AdvertiseSettings#ADVERTISE_TX_POWER_HIGH}.
-         * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid.
-         */
-        public Builder setTxPowerLevel(int txPowerLevel) {
-            if (txPowerLevel < ADVERTISE_TX_POWER_ULTRA_LOW
-                    || txPowerLevel > ADVERTISE_TX_POWER_HIGH) {
-                throw new IllegalArgumentException("unknown tx power level " + txPowerLevel);
-            }
-            mTxPowerLevel = txPowerLevel;
-            return this;
-        }
-
-        /**
-         * Set whether the advertisement type should be connectable or non-connectable.
-         *
-         * @param connectable Controls whether the advertisment type will be connectable (true) or
-         * non-connectable (false).
-         */
-        public Builder setConnectable(boolean connectable) {
-            mConnectable = connectable;
-            return this;
-        }
-
-        /**
-         * Limit advertising to a given amount of time.
-         *
-         * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds. A value
-         * of 0 will disable the time limit.
-         * @throws IllegalArgumentException If the provided timeout is over 180000 ms.
-         */
-        public Builder setTimeout(int timeoutMillis) {
-            if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) {
-                throw new IllegalArgumentException("timeoutMillis invalid (must be 0-"
-                        + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)");
-            }
-            mTimeoutMillis = timeoutMillis;
-            return this;
-        }
-
-        /**
-         * Set own address type for advertising to control public or privacy mode. If used to set
-         * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
-         * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
-         * time of starting advertising.
-         *
-         * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
-         *
-         * @hide
-         */
-        @SystemApi
-        public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
-            if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
-                    ||  ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
-                throw new IllegalArgumentException("unknown address type " + ownAddressType);
-            }
-            mOwnAddressType = ownAddressType;
-            return this;
-        }
-
-        /**
-         * Build the {@link AdvertiseSettings} object.
-         */
-        public AdvertiseSettings build() {
-            return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis,
-                mOwnAddressType);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
deleted file mode 100644
index bbdb695..0000000
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * This class provides a way to control single Bluetooth LE advertising instance.
- * <p>
- * To get an instance of {@link AdvertisingSet}, call the
- * {@link BluetoothLeAdvertiser#startAdvertisingSet} method.
- *
- * @see AdvertiseData
- */
-public final class AdvertisingSet {
-    private static final String TAG = "AdvertisingSet";
-
-    private final IBluetoothGatt mGatt;
-    private int mAdvertiserId;
-    private AttributionSource mAttributionSource;
-
-    /* package */ AdvertisingSet(int advertiserId, IBluetoothManager bluetoothManager,
-            AttributionSource attributionSource) {
-        mAdvertiserId = advertiserId;
-        mAttributionSource = attributionSource;
-        try {
-            mGatt = bluetoothManager.getBluetoothGatt();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
-            throw new IllegalStateException("Failed to get Bluetooth");
-        }
-    }
-
-    /* package */ void setAdvertiserId(int advertiserId) {
-        mAdvertiserId = advertiserId;
-    }
-
-    /**
-     * Enables Advertising. This method returns immediately, the operation status is
-     * delivered through {@code callback.onAdvertisingEnabled()}.
-     *
-     * @param enable whether the advertising should be enabled (true), or disabled (false)
-     * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
-     * (655,350 ms)
-     * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
-     * controller shall attempt to send prior to terminating the extended advertising, even if the
-     * duration has not expired. Valid range is from 1 to 255.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void enableAdvertising(boolean enable, int duration,
-            int maxExtendedAdvertisingEvents) {
-        try {
-            mGatt.enableAdvertisingSet(mAdvertiserId, enable, duration,
-                    maxExtendedAdvertisingEvents, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Set/update data being Advertised. Make sure that data doesn't exceed the size limit for
-     * specified AdvertisingSetParameters. This method returns immediately, the operation status is
-     * delivered through {@code callback.onAdvertisingDataSet()}.
-     * <p>
-     * Advertising data must be empty if non-legacy scannable advertising is used.
-     *
-     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
-     * three bytes will be added for flags. If the update takes place when the advertising set is
-     * enabled, the data can be maximum 251 bytes long.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void setAdvertisingData(AdvertiseData advertiseData) {
-        try {
-            mGatt.setAdvertisingData(mAdvertiserId, advertiseData, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Set/update scan response data. Make sure that data doesn't exceed the size limit for
-     * specified AdvertisingSetParameters. This method returns immediately, the operation status
-     * is delivered through {@code callback.onScanResponseDataSet()}.
-     *
-     * @param scanResponse Scan response associated with the advertisement data. Size must not
-     * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place
-     * when the advertising set is enabled, the data can be maximum 251 bytes long.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void setScanResponseData(AdvertiseData scanResponse) {
-        try {
-            mGatt.setScanResponseData(mAdvertiserId, scanResponse, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Update advertising parameters associated with this AdvertisingSet. Must be called when
-     * advertising is not active. This method returns immediately, the operation status is delivered
-     * through {@code callback.onAdvertisingParametersUpdated}.
-     *
-     * @param parameters advertising set parameters.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
-        try {
-            mGatt.setAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Update periodic advertising parameters associated with this set. Must be called when
-     * periodic advertising is not enabled. This method returns immediately, the operation
-     * status is delivered through {@code callback.onPeriodicAdvertisingParametersUpdated()}.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) {
-        try {
-            mGatt.setPeriodicAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Used to set periodic advertising data, must be called after setPeriodicAdvertisingParameters,
-     * or after advertising was started with periodic advertising data set. This method returns
-     * immediately, the operation status is delivered through
-     * {@code callback.onPeriodicAdvertisingDataSet()}.
-     *
-     * @param periodicData Periodic advertising data. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place when the
-     * periodic advertising is enabled for this set, the data can be maximum 251 bytes long.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
-        try {
-            mGatt.setPeriodicAdvertisingData(mAdvertiserId, periodicData, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Used to enable/disable periodic advertising. This method returns immediately, the operation
-     * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
-     *
-     * @param enable whether the periodic advertising should be enabled (true), or disabled
-     * (false).
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void setPeriodicAdvertisingEnabled(boolean enable) {
-        try {
-            mGatt.setPeriodicAdvertisingEnable(mAdvertiserId, enable, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Returns address associated with this advertising set.
-     * This method is exposed only for Bluetooth PTS tests, no app or system service
-     * should ever use it.
-     *
-     * @hide
-     */
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_ADVERTISE,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public void getOwnAddress() {
-        try {
-            mGatt.getOwnAddress(mAdvertiserId, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "remote exception - ", e);
-        }
-    }
-
-    /**
-     * Returns advertiserId associated with this advertising set.
-     *
-     * @hide
-     */
-    @RequiresNoPermission
-    public int getAdvertiserId() {
-        return mAdvertiserId;
-    }
-}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
deleted file mode 100644
index 51324fd..0000000
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-/**
- * Bluetooth LE advertising set callbacks, used to deliver advertising operation
- * status.
- */
-public abstract class AdvertisingSetCallback {
-
-    /**
-     * The requested operation was successful.
-     */
-    public static final int ADVERTISE_SUCCESS = 0;
-
-    /**
-     * Failed to start advertising as the advertise data to be broadcasted is too
-     * large.
-     */
-    public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;
-
-    /**
-     * Failed to start advertising because no advertising instance is available.
-     */
-    public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2;
-
-    /**
-     * Failed to start advertising as the advertising is already started.
-     */
-    public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3;
-
-    /**
-     * Operation failed due to an internal error.
-     */
-    public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4;
-
-    /**
-     * This feature is not supported on this platform.
-     */
-    public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5;
-
-    /**
-     * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
-     * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertisingSet
-     * contains the started set and it is advertising. If error occurred, advertisingSet is
-     * null, and status will be set to proper error code.
-     *
-     * @param advertisingSet The advertising set that was started or null if error.
-     * @param txPower tx power that will be used for this set.
-     * @param status Status of the operation.
-     */
-    public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet}
-     * indicating advertising set is stopped.
-     *
-     * @param advertisingSet The advertising set.
-     */
-    public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
-    }
-
-    /**
-     * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
-     * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertising set is
-     * advertising.
-     *
-     * @param advertisingSet The advertising set.
-     * @param status Status of the operation.
-     */
-    public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating
-     * result of the operation. If status is ADVERTISE_SUCCESS, then data was changed.
-     *
-     * @param advertisingSet The advertising set.
-     * @param status Status of the operation.
-     */
-    public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating
-     * result of the operation.
-     *
-     * @param advertisingSet The advertising set.
-     * @param status Status of the operation.
-     */
-    public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#setAdvertisingParameters}
-     * indicating result of the operation.
-     *
-     * @param advertisingSet The advertising set.
-     * @param txPower tx power that will be used for this set.
-     * @param status Status of the operation.
-     */
-    public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet,
-            int txPower, int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters}
-     * indicating result of the operation.
-     *
-     * @param advertisingSet The advertising set.
-     * @param status Status of the operation.
-     */
-    public void onPeriodicAdvertisingParametersUpdated(AdvertisingSet advertisingSet, int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingData}
-     * indicating result of the operation.
-     *
-     * @param advertisingSet The advertising set.
-     * @param status Status of the operation.
-     */
-    public void onPeriodicAdvertisingDataSet(AdvertisingSet advertisingSet,
-            int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingEnabled}
-     * indicating result of the operation.
-     *
-     * @param advertisingSet The advertising set.
-     * @param status Status of the operation.
-     */
-    public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
-            int status) {
-    }
-
-    /**
-     * Callback triggered in response to {@link AdvertisingSet#getOwnAddress()}
-     * indicating result of the operation.
-     *
-     * @param advertisingSet The advertising set.
-     * @param addressType type of address.
-     * @param address advertising set bluetooth address.
-     * @hide
-     */
-    public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) {
-    }
-}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
deleted file mode 100644
index 5c8fae6..0000000
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * The {@link AdvertisingSetParameters} provide a way to adjust advertising
- * preferences for each
- * Bluetooth LE advertising set. Use {@link AdvertisingSetParameters.Builder} to
- * create an
- * instance of this class.
- */
-public final class AdvertisingSetParameters implements Parcelable {
-
-    /**
-     * Advertise on low frequency, around every 1000ms. This is the default and
-     * preferred advertising mode as it consumes the least power.
-     */
-    public static final int INTERVAL_HIGH = 1600;
-
-    /**
-     * Advertise on medium frequency, around every 250ms. This is balanced
-     * between advertising frequency and power consumption.
-     */
-    public static final int INTERVAL_MEDIUM = 400;
-
-    /**
-     * Perform high frequency, low latency advertising, around every 100ms. This
-     * has the highest power consumption and should not be used for continuous
-     * background advertising.
-     */
-    public static final int INTERVAL_LOW = 160;
-
-    /**
-     * Minimum value for advertising interval.
-     */
-    public static final int INTERVAL_MIN = 160;
-
-    /**
-     * Maximum value for advertising interval.
-     */
-    public static final int INTERVAL_MAX = 16777215;
-
-    /**
-     * Advertise using the lowest transmission (TX) power level. Low transmission
-     * power can be used to restrict the visibility range of advertising packets.
-     */
-    public static final int TX_POWER_ULTRA_LOW = -21;
-
-    /**
-     * Advertise using low TX power level.
-     */
-    public static final int TX_POWER_LOW = -15;
-
-    /**
-     * Advertise using medium TX power level.
-     */
-    public static final int TX_POWER_MEDIUM = -7;
-
-    /**
-     * Advertise using high TX power level. This corresponds to largest visibility
-     * range of the advertising packet.
-     */
-    public static final int TX_POWER_HIGH = 1;
-
-    /**
-     * Minimum value for TX power.
-     */
-    public static final int TX_POWER_MIN = -127;
-
-    /**
-     * Maximum value for TX power.
-     */
-    public static final int TX_POWER_MAX = 1;
-
-    /**
-     * The maximum limited advertisement duration as specified by the Bluetooth
-     * SIG
-     */
-    private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
-
-    /** @hide */
-    @IntDef(prefix = "ADDRESS_TYPE_", value = {
-        ADDRESS_TYPE_DEFAULT,
-        ADDRESS_TYPE_PUBLIC,
-        ADDRESS_TYPE_RANDOM
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AddressTypeStatus {}
-
-    /**
-     * Advertise own address type that corresponds privacy settings of the device.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ADDRESS_TYPE_DEFAULT = -1;
-
-    /**
-     * Advertise own public address type.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ADDRESS_TYPE_PUBLIC = 0;
-
-    /**
-     * Generate and adverise own resolvable private address.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int ADDRESS_TYPE_RANDOM = 1;
-
-    private final boolean mIsLegacy;
-    private final boolean mIsAnonymous;
-    private final boolean mIncludeTxPower;
-    private final int mPrimaryPhy;
-    private final int mSecondaryPhy;
-    private final boolean mConnectable;
-    private final boolean mScannable;
-    private final int mInterval;
-    private final int mTxPowerLevel;
-    private final int mOwnAddressType;
-
-    private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy,
-            boolean isAnonymous, boolean includeTxPower,
-            int primaryPhy, int secondaryPhy,
-            int interval, int txPowerLevel, @AddressTypeStatus int ownAddressType) {
-        mConnectable = connectable;
-        mScannable = scannable;
-        mIsLegacy = isLegacy;
-        mIsAnonymous = isAnonymous;
-        mIncludeTxPower = includeTxPower;
-        mPrimaryPhy = primaryPhy;
-        mSecondaryPhy = secondaryPhy;
-        mInterval = interval;
-        mTxPowerLevel = txPowerLevel;
-        mOwnAddressType = ownAddressType;
-    }
-
-    private AdvertisingSetParameters(Parcel in) {
-        mConnectable = in.readInt() != 0;
-        mScannable = in.readInt() != 0;
-        mIsLegacy = in.readInt() != 0;
-        mIsAnonymous = in.readInt() != 0;
-        mIncludeTxPower = in.readInt() != 0;
-        mPrimaryPhy = in.readInt();
-        mSecondaryPhy = in.readInt();
-        mInterval = in.readInt();
-        mTxPowerLevel = in.readInt();
-        mOwnAddressType = in.readInt();
-    }
-
-    /**
-     * Returns whether the advertisement will be connectable.
-     */
-    public boolean isConnectable() {
-        return mConnectable;
-    }
-
-    /**
-     * Returns whether the advertisement will be scannable.
-     */
-    public boolean isScannable() {
-        return mScannable;
-    }
-
-    /**
-     * Returns whether the legacy advertisement will be used.
-     */
-    public boolean isLegacy() {
-        return mIsLegacy;
-    }
-
-    /**
-     * Returns whether the advertisement will be anonymous.
-     */
-    public boolean isAnonymous() {
-        return mIsAnonymous;
-    }
-
-    /**
-     * Returns whether the TX Power will be included.
-     */
-    public boolean includeTxPower() {
-        return mIncludeTxPower;
-    }
-
-    /**
-     * Returns the primary advertising phy.
-     */
-    public int getPrimaryPhy() {
-        return mPrimaryPhy;
-    }
-
-    /**
-     * Returns the secondary advertising phy.
-     */
-    public int getSecondaryPhy() {
-        return mSecondaryPhy;
-    }
-
-    /**
-     * Returns the advertising interval.
-     */
-    public int getInterval() {
-        return mInterval;
-    }
-
-    /**
-     * Returns the TX power level for advertising.
-     */
-    public int getTxPowerLevel() {
-        return mTxPowerLevel;
-    }
-
-    /**
-     * @return the own address type for advertising
-     *
-     * @hide
-     */
-    @SystemApi
-    public @AddressTypeStatus int getOwnAddressType() {
-        return mOwnAddressType;
-    }
-
-    @Override
-    public String toString() {
-        return "AdvertisingSetParameters [connectable=" + mConnectable
-                + ", isLegacy=" + mIsLegacy
-                + ", isAnonymous=" + mIsAnonymous
-                + ", includeTxPower=" + mIncludeTxPower
-                + ", primaryPhy=" + mPrimaryPhy
-                + ", secondaryPhy=" + mSecondaryPhy
-                + ", interval=" + mInterval
-                + ", txPowerLevel=" + mTxPowerLevel
-                + ", ownAddressType=" + mOwnAddressType + "]";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mConnectable ? 1 : 0);
-        dest.writeInt(mScannable ? 1 : 0);
-        dest.writeInt(mIsLegacy ? 1 : 0);
-        dest.writeInt(mIsAnonymous ? 1 : 0);
-        dest.writeInt(mIncludeTxPower ? 1 : 0);
-        dest.writeInt(mPrimaryPhy);
-        dest.writeInt(mSecondaryPhy);
-        dest.writeInt(mInterval);
-        dest.writeInt(mTxPowerLevel);
-        dest.writeInt(mOwnAddressType);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<AdvertisingSetParameters> CREATOR =
-            new Creator<AdvertisingSetParameters>() {
-                @Override
-                public AdvertisingSetParameters[] newArray(int size) {
-                    return new AdvertisingSetParameters[size];
-                }
-
-                @Override
-                public AdvertisingSetParameters createFromParcel(Parcel in) {
-                    return new AdvertisingSetParameters(in);
-                }
-            };
-
-    /**
-     * Builder class for {@link AdvertisingSetParameters}.
-     */
-    public static final class Builder {
-        private boolean mConnectable = false;
-        private boolean mScannable = false;
-        private boolean mIsLegacy = false;
-        private boolean mIsAnonymous = false;
-        private boolean mIncludeTxPower = false;
-        private int mPrimaryPhy = BluetoothDevice.PHY_LE_1M;
-        private int mSecondaryPhy = BluetoothDevice.PHY_LE_1M;
-        private int mInterval = INTERVAL_LOW;
-        private int mTxPowerLevel = TX_POWER_MEDIUM;
-        private int mOwnAddressType = ADDRESS_TYPE_DEFAULT;
-
-        /**
-         * Set whether the advertisement type should be connectable or
-         * non-connectable.
-         * Legacy advertisements can be both connectable and scannable. Non-legacy
-         * advertisements can be only scannable or only connectable.
-         *
-         * @param connectable Controls whether the advertisement type will be connectable (true) or
-         * non-connectable (false).
-         */
-        public Builder setConnectable(boolean connectable) {
-            mConnectable = connectable;
-            return this;
-        }
-
-        /**
-         * Set whether the advertisement type should be scannable.
-         * Legacy advertisements can be both connectable and scannable. Non-legacy
-         * advertisements can be only scannable or only connectable.
-         *
-         * @param scannable Controls whether the advertisement type will be scannable (true) or
-         * non-scannable (false).
-         */
-        public Builder setScannable(boolean scannable) {
-            mScannable = scannable;
-            return this;
-        }
-
-        /**
-         * When set to true, advertising set will advertise 4.x Spec compliant
-         * advertisements.
-         *
-         * @param isLegacy whether legacy advertising mode should be used.
-         */
-        public Builder setLegacyMode(boolean isLegacy) {
-            mIsLegacy = isLegacy;
-            return this;
-        }
-
-        /**
-         * Set whether advertiser address should be ommited from all packets. If this
-         * mode is used, periodic advertising can't be enabled for this set.
-         *
-         * This is used only if legacy mode is not used.
-         *
-         * @param isAnonymous whether anonymous advertising should be used.
-         */
-        public Builder setAnonymous(boolean isAnonymous) {
-            mIsAnonymous = isAnonymous;
-            return this;
-        }
-
-        /**
-         * Set whether TX power should be included in the extended header.
-         *
-         * This is used only if legacy mode is not used.
-         *
-         * @param includeTxPower whether TX power should be included in extended header
-         */
-        public Builder setIncludeTxPower(boolean includeTxPower) {
-            mIncludeTxPower = includeTxPower;
-            return this;
-        }
-
-        /**
-         * Set the primary physical channel used for this advertising set.
-         *
-         * This is used only if legacy mode is not used.
-         *
-         * Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
-         * supported on this device.
-         *
-         * @param primaryPhy Primary advertising physical channel, can only be {@link
-         * BluetoothDevice#PHY_LE_1M} or {@link BluetoothDevice#PHY_LE_CODED}.
-         * @throws IllegalArgumentException If the primaryPhy is invalid.
-         */
-        public Builder setPrimaryPhy(int primaryPhy) {
-            if (primaryPhy != BluetoothDevice.PHY_LE_1M
-                    && primaryPhy != BluetoothDevice.PHY_LE_CODED) {
-                throw new IllegalArgumentException("bad primaryPhy " + primaryPhy);
-            }
-            mPrimaryPhy = primaryPhy;
-            return this;
-        }
-
-        /**
-         * Set the secondary physical channel used for this advertising set.
-         *
-         * This is used only if legacy mode is not used.
-         *
-         * Use {@link BluetoothAdapter#isLeCodedPhySupported} and
-         * {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is
-         * supported on this device.
-         *
-         * @param secondaryPhy Secondary advertising physical channel, can only be one of {@link
-         * BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M} or {@link
-         * BluetoothDevice#PHY_LE_CODED}.
-         * @throws IllegalArgumentException If the secondaryPhy is invalid.
-         */
-        public Builder setSecondaryPhy(int secondaryPhy) {
-            if (secondaryPhy != BluetoothDevice.PHY_LE_1M
-                    && secondaryPhy != BluetoothDevice.PHY_LE_2M
-                    && secondaryPhy != BluetoothDevice.PHY_LE_CODED) {
-                throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy);
-            }
-            mSecondaryPhy = secondaryPhy;
-            return this;
-        }
-
-        /**
-         * Set advertising interval.
-         *
-         * @param interval Bluetooth LE Advertising interval, in 0.625ms unit. Valid range is from
-         * 160 (100ms) to 16777215 (10,485.759375 s). Recommended values are: {@link
-         * AdvertisingSetParameters#INTERVAL_LOW}, {@link AdvertisingSetParameters#INTERVAL_MEDIUM},
-         * or {@link AdvertisingSetParameters#INTERVAL_HIGH}.
-         * @throws IllegalArgumentException If the interval is invalid.
-         */
-        public Builder setInterval(int interval) {
-            if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
-                throw new IllegalArgumentException("unknown interval " + interval);
-            }
-            mInterval = interval;
-            return this;
-        }
-
-        /**
-         * Set the transmission power level for the advertising.
-         *
-         * @param txPowerLevel Transmission power of Bluetooth LE Advertising, in dBm. The valid
-         * range is [-127, 1] Recommended values are:
-         * {@link AdvertisingSetParameters#TX_POWER_ULTRA_LOW},
-         * {@link AdvertisingSetParameters#TX_POWER_LOW},
-         * {@link AdvertisingSetParameters#TX_POWER_MEDIUM},
-         * or {@link AdvertisingSetParameters#TX_POWER_HIGH}.
-         * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid.
-         */
-        public Builder setTxPowerLevel(int txPowerLevel) {
-            if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) {
-                throw new IllegalArgumentException("unknown txPowerLevel " + txPowerLevel);
-            }
-            mTxPowerLevel = txPowerLevel;
-            return this;
-        }
-
-        /**
-         * Set own address type for advertising to control public or privacy mode. If used to set
-         * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
-         * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
-         * time of starting advertising.
-         *
-         * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
-         *
-         * @hide
-         */
-        @SystemApi
-        public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
-            if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
-                    ||  ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
-                throw new IllegalArgumentException("unknown address type " + ownAddressType);
-            }
-            mOwnAddressType = ownAddressType;
-            return this;
-        }
-
-        /**
-         * Build the {@link AdvertisingSetParameters} object.
-         *
-         * @throws IllegalStateException if invalid combination of parameters is used.
-         */
-        public AdvertisingSetParameters build() {
-            if (mIsLegacy) {
-                if (mIsAnonymous) {
-                    throw new IllegalArgumentException("Legacy advertising can't be anonymous");
-                }
-
-                if (mConnectable && !mScannable) {
-                    throw new IllegalStateException(
-                            "Legacy advertisement can't be connectable and non-scannable");
-                }
-
-                if (mIncludeTxPower) {
-                    throw new IllegalStateException(
-                            "Legacy advertising can't include TX power level in header");
-                }
-            } else {
-                if (mConnectable && mScannable) {
-                    throw new IllegalStateException(
-                            "Advertising can't be both connectable and scannable");
-                }
-
-                if (mIsAnonymous && mConnectable) {
-                    throw new IllegalStateException(
-                            "Advertising can't be both connectable and anonymous");
-                }
-            }
-
-            return new AdvertisingSetParameters(mConnectable, mScannable, mIsLegacy, mIsAnonymous,
-                    mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel,
-                    mOwnAddressType);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
deleted file mode 100644
index 879dcee..0000000
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class provides a way to perform Bluetooth LE advertise operations, such as starting and
- * stopping advertising. An advertiser can broadcast up to 31 bytes of advertisement data
- * represented by {@link AdvertiseData}.
- * <p>
- * To get an instance of {@link BluetoothLeAdvertiser}, call the
- * {@link BluetoothAdapter#getBluetoothLeAdvertiser()} method.
- *
- * @see AdvertiseData
- */
-public final class BluetoothLeAdvertiser {
-
-    private static final String TAG = "BluetoothLeAdvertiser";
-
-    private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
-    private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31;
-    // Each fields need one byte for field length and another byte for field type.
-    private static final int OVERHEAD_BYTES_PER_FIELD = 2;
-    // Flags field will be set by system.
-    private static final int FLAGS_FIELD_BYTES = 3;
-    private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
-
-    private final BluetoothAdapter mBluetoothAdapter;
-    private final IBluetoothManager mBluetoothManager;
-    private final AttributionSource mAttributionSource;
-
-    private final Handler mHandler;
-    private final Map<AdvertiseCallback, AdvertisingSetCallback>
-            mLegacyAdvertisers = new HashMap<>();
-    private final Map<AdvertisingSetCallback, IAdvertisingSetCallback>
-            mCallbackWrappers = Collections.synchronizedMap(new HashMap<>());
-    private final Map<Integer, AdvertisingSet>
-            mAdvertisingSets = Collections.synchronizedMap(new HashMap<>());
-
-    /**
-     * Use BluetoothAdapter.getLeAdvertiser() instead.
-     *
-     * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management
-     * @hide
-     */
-    public BluetoothLeAdvertiser(BluetoothAdapter bluetoothAdapter) {
-        mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
-        mBluetoothManager = mBluetoothAdapter.getBluetoothManager();
-        mAttributionSource = mBluetoothAdapter.getAttributionSource();
-        mHandler = new Handler(Looper.getMainLooper());
-    }
-
-    /**
-     * Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be broadcasted.
-     * Returns immediately, the operation status is delivered through {@code callback}.
-     *
-     * @param settings Settings for Bluetooth LE advertising.
-     * @param advertiseData Advertisement data to be broadcasted.
-     * @param callback Callback for advertising status.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void startAdvertising(AdvertiseSettings settings,
-            AdvertiseData advertiseData, final AdvertiseCallback callback) {
-        startAdvertising(settings, advertiseData, null, callback);
-    }
-
-    /**
-     * Start Bluetooth LE Advertising. The {@code advertiseData} will be broadcasted if the
-     * operation succeeds. The {@code scanResponse} is returned when a scanning device sends an
-     * active scan request. This method returns immediately, the operation status is delivered
-     * through {@code callback}.
-     *
-     * @param settings Settings for Bluetooth LE advertising.
-     * @param advertiseData Advertisement data to be advertised in advertisement packet.
-     * @param scanResponse Scan response associated with the advertisement data.
-     * @param callback Callback for advertising status.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void startAdvertising(AdvertiseSettings settings,
-            AdvertiseData advertiseData, AdvertiseData scanResponse,
-            final AdvertiseCallback callback) {
-        synchronized (mLegacyAdvertisers) {
-            BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-            if (callback == null) {
-                throw new IllegalArgumentException("callback cannot be null");
-            }
-            boolean isConnectable = settings.isConnectable();
-            if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES
-                    || totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
-                postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
-                return;
-            }
-            if (mLegacyAdvertisers.containsKey(callback)) {
-                postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
-                return;
-            }
-
-            AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder();
-            parameters.setLegacyMode(true);
-            parameters.setConnectable(isConnectable);
-            parameters.setScannable(true); // legacy advertisements we support are always scannable
-            parameters.setOwnAddressType(settings.getOwnAddressType());
-            if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
-                parameters.setInterval(1600); // 1s
-            } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
-                parameters.setInterval(400); // 250ms
-            } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) {
-                parameters.setInterval(160); // 100ms
-            }
-
-            if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) {
-                parameters.setTxPowerLevel(-21);
-            } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) {
-                parameters.setTxPowerLevel(-15);
-            } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) {
-                parameters.setTxPowerLevel(-7);
-            } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
-                parameters.setTxPowerLevel(1);
-            }
-
-            int duration = 0;
-            int timeoutMillis = settings.getTimeout();
-            if (timeoutMillis > 0) {
-                duration = (timeoutMillis < 10) ? 1 : timeoutMillis / 10;
-            }
-
-            AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
-            mLegacyAdvertisers.put(callback, wrapped);
-            startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
-                    duration, 0, wrapped);
-        }
-    }
-
-    @SuppressLint({
-            "AndroidFrameworkBluetoothPermission",
-            "AndroidFrameworkRequiresPermission",
-    })
-    AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
-        return new AdvertisingSetCallback() {
-            @Override
-            public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower,
-                    int status) {
-                if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
-                    postStartFailure(callback, status);
-                    return;
-                }
-
-                postStartSuccess(callback, settings);
-            }
-
-            /* Legacy advertiser is disabled on timeout */
-            @Override
-            public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled,
-                    int status) {
-                if (enabled) {
-                    Log.e(TAG, "Legacy advertiser should be only disabled on timeout,"
-                            + " but was enabled!");
-                    return;
-                }
-
-                stopAdvertising(callback);
-            }
-
-        };
-    }
-
-    /**
-     * Stop Bluetooth LE advertising. The {@code callback} must be the same one use in
-     * {@link BluetoothLeAdvertiser#startAdvertising}.
-     *
-     * @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void stopAdvertising(final AdvertiseCallback callback) {
-        synchronized (mLegacyAdvertisers) {
-            if (callback == null) {
-                throw new IllegalArgumentException("callback cannot be null");
-            }
-            AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback);
-            if (wrapper == null) return;
-
-            stopAdvertisingSet(wrapper);
-
-            mLegacyAdvertisers.remove(callback);
-        }
-    }
-
-    /**
-     * Creates a new advertising set. If operation succeed, device will start advertising. This
-     * method returns immediately, the operation status is delivered through
-     * {@code callback.onAdvertisingSetStarted()}.
-     * <p>
-     *
-     * @param parameters advertising set parameters.
-     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
-     * three bytes will be added for flags.
-     * @param scanResponse Scan response associated with the advertisement data. Size must not
-     * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
-     * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
-     * not be started.
-     * @param periodicData Periodic advertising data. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
-     * @param callback Callback for advertising set.
-     * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
-     * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
-     * feature is made when it's not supported by the controller.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void startAdvertisingSet(AdvertisingSetParameters parameters,
-            AdvertiseData advertiseData, AdvertiseData scanResponse,
-            PeriodicAdvertisingParameters periodicParameters,
-            AdvertiseData periodicData, AdvertisingSetCallback callback) {
-        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                periodicData, 0, 0, callback, new Handler(Looper.getMainLooper()));
-    }
-
-    /**
-     * Creates a new advertising set. If operation succeed, device will start advertising. This
-     * method returns immediately, the operation status is delivered through
-     * {@code callback.onAdvertisingSetStarted()}.
-     * <p>
-     *
-     * @param parameters advertising set parameters.
-     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
-     * three bytes will be added for flags.
-     * @param scanResponse Scan response associated with the advertisement data. Size must not
-     * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
-     * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
-     * not be started.
-     * @param periodicData Periodic advertising data. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
-     * @param callback Callback for advertising set.
-     * @param handler thread upon which the callbacks will be invoked.
-     * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
-     * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
-     * feature is made when it's not supported by the controller.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void startAdvertisingSet(AdvertisingSetParameters parameters,
-            AdvertiseData advertiseData, AdvertiseData scanResponse,
-            PeriodicAdvertisingParameters periodicParameters,
-            AdvertiseData periodicData, AdvertisingSetCallback callback,
-            Handler handler) {
-        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                periodicData, 0, 0, callback, handler);
-    }
-
-    /**
-     * Creates a new advertising set. If operation succeed, device will start advertising. This
-     * method returns immediately, the operation status is delivered through
-     * {@code callback.onAdvertisingSetStarted()}.
-     * <p>
-     *
-     * @param parameters advertising set parameters.
-     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
-     * three bytes will be added for flags.
-     * @param scanResponse Scan response associated with the advertisement data. Size must not
-     * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
-     * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
-     * not be started.
-     * @param periodicData Periodic advertising data. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
-     * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
-     * (655,350 ms). 0 means advertising should continue until stopped.
-     * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
-     * controller shall attempt to send prior to terminating the extended advertising, even if the
-     * duration has not expired. Valid range is from 1 to 255. 0 means no maximum.
-     * @param callback Callback for advertising set.
-     * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
-     * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
-     * feature is made when it's not supported by the controller.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void startAdvertisingSet(AdvertisingSetParameters parameters,
-            AdvertiseData advertiseData, AdvertiseData scanResponse,
-            PeriodicAdvertisingParameters periodicParameters,
-            AdvertiseData periodicData, int duration,
-            int maxExtendedAdvertisingEvents,
-            AdvertisingSetCallback callback) {
-        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                periodicData, duration, maxExtendedAdvertisingEvents, callback,
-                new Handler(Looper.getMainLooper()));
-    }
-
-    /**
-     * Creates a new advertising set. If operation succeed, device will start advertising. This
-     * method returns immediately, the operation status is delivered through
-     * {@code callback.onAdvertisingSetStarted()}.
-     * <p>
-     *
-     * @param parameters Advertising set parameters.
-     * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
-     * three bytes will be added for flags.
-     * @param scanResponse Scan response associated with the advertisement data. Size must not
-     * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
-     * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will
-     * not be started.
-     * @param periodicData Periodic advertising data. Size must not exceed {@link
-     * BluetoothAdapter#getLeMaximumAdvertisingDataLength}
-     * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
-     * (655,350 ms). 0 means advertising should continue until stopped.
-     * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
-     * controller shall attempt to send prior to terminating the extended advertising, even if the
-     * duration has not expired. Valid range is from 1 to 255. 0 means no maximum.
-     * @param callback Callback for advertising set.
-     * @param handler Thread upon which the callbacks will be invoked.
-     * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable
-     * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
-     * feature is made when it's not supported by the controller, or when
-     * maxExtendedAdvertisingEvents is used on a controller that doesn't support the LE Extended
-     * Advertising
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void startAdvertisingSet(AdvertisingSetParameters parameters,
-            AdvertiseData advertiseData, AdvertiseData scanResponse,
-            PeriodicAdvertisingParameters periodicParameters,
-            AdvertiseData periodicData, int duration,
-            int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback,
-            Handler handler) {
-        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null");
-        }
-
-        boolean isConnectable = parameters.isConnectable();
-        if (parameters.isLegacy()) {
-            if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
-                throw new IllegalArgumentException("Legacy advertising data too big");
-            }
-
-            if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
-                throw new IllegalArgumentException("Legacy scan response data too big");
-            }
-        } else {
-            boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
-            boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
-            int pphy = parameters.getPrimaryPhy();
-            int sphy = parameters.getSecondaryPhy();
-            if (pphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) {
-                throw new IllegalArgumentException("Unsupported primary PHY selected");
-            }
-
-            if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy)
-                    || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) {
-                throw new IllegalArgumentException("Unsupported secondary PHY selected");
-            }
-
-            int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
-            if (totalBytes(advertiseData, isConnectable) > maxData) {
-                throw new IllegalArgumentException("Advertising data too big");
-            }
-
-            if (totalBytes(scanResponse, false) > maxData) {
-                throw new IllegalArgumentException("Scan response data too big");
-            }
-
-            if (totalBytes(periodicData, false) > maxData) {
-                throw new IllegalArgumentException("Periodic advertising data too big");
-            }
-
-            boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
-            if (periodicParameters != null && !supportPeriodic) {
-                throw new IllegalArgumentException(
-                        "Controller does not support LE Periodic Advertising");
-            }
-        }
-
-        if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) {
-            throw new IllegalArgumentException(
-                    "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents);
-        }
-
-        if (maxExtendedAdvertisingEvents != 0
-                && !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
-            throw new IllegalArgumentException(
-                    "Can't use maxExtendedAdvertisingEvents with controller that don't support "
-                            + "LE Extended Advertising");
-        }
-
-        if (duration < 0 || duration > 65535) {
-            throw new IllegalArgumentException("duration out of range: " + duration);
-        }
-
-        IBluetoothGatt gatt;
-        try {
-            gatt = mBluetoothManager.getBluetoothGatt();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get Bluetooth GATT - ", e);
-            postStartSetFailure(handler, callback,
-                    AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
-            return;
-        }
-
-        if (gatt == null) {
-            Log.e(TAG, "Bluetooth GATT is null");
-            postStartSetFailure(handler, callback,
-                    AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
-            return;
-        }
-
-        IAdvertisingSetCallback wrapped = wrap(callback, handler);
-        if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) {
-            throw new IllegalArgumentException(
-                    "callback instance already associated with advertising");
-        }
-
-        try {
-            gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                    periodicData, duration, maxExtendedAdvertisingEvents, wrapped,
-                    mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to start advertising set - ", e);
-            postStartSetFailure(handler, callback,
-                    AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
-            return;
-        }
-    }
-
-    /**
-     * Used to dispose of a {@link AdvertisingSet} object, obtained with {@link
-     * BluetoothLeAdvertiser#startAdvertisingSet}.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    public void stopAdvertisingSet(AdvertisingSetCallback callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null");
-        }
-
-        IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback);
-        if (wrapped == null) {
-            return;
-        }
-
-        IBluetoothGatt gatt;
-        try {
-            gatt = mBluetoothManager.getBluetoothGatt();
-            gatt.stopAdvertisingSet(wrapped, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to stop advertising - ", e);
-        }
-    }
-
-    /**
-     * Cleans up advertisers. Should be called when bluetooth is down.
-     *
-     * @hide
-     */
-    @RequiresNoPermission
-    public void cleanup() {
-        mLegacyAdvertisers.clear();
-        mCallbackWrappers.clear();
-        mAdvertisingSets.clear();
-    }
-
-    // Compute the size of advertisement data or scan resp
-    @RequiresBluetoothAdvertisePermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
-    private int totalBytes(AdvertiseData data, boolean isFlagsIncluded) {
-        if (data == null) return 0;
-        // Flags field is omitted if the advertising is not connectable.
-        int size = (isFlagsIncluded) ? FLAGS_FIELD_BYTES : 0;
-        if (data.getServiceUuids() != null) {
-            int num16BitUuids = 0;
-            int num32BitUuids = 0;
-            int num128BitUuids = 0;
-            for (ParcelUuid uuid : data.getServiceUuids()) {
-                if (BluetoothUuid.is16BitUuid(uuid)) {
-                    ++num16BitUuids;
-                } else if (BluetoothUuid.is32BitUuid(uuid)) {
-                    ++num32BitUuids;
-                } else {
-                    ++num128BitUuids;
-                }
-            }
-            // 16 bit service uuids are grouped into one field when doing advertising.
-            if (num16BitUuids != 0) {
-                size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
-            }
-            // 32 bit service uuids are grouped into one field when doing advertising.
-            if (num32BitUuids != 0) {
-                size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
-            }
-            // 128 bit service uuids are grouped into one field when doing advertising.
-            if (num128BitUuids != 0) {
-                size += OVERHEAD_BYTES_PER_FIELD
-                        + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
-            }
-        }
-        if (data.getServiceSolicitationUuids() != null) {
-            int num16BitUuids = 0;
-            int num32BitUuids = 0;
-            int num128BitUuids = 0;
-            for (ParcelUuid uuid : data.getServiceSolicitationUuids()) {
-                if (BluetoothUuid.is16BitUuid(uuid)) {
-                    ++num16BitUuids;
-                } else if (BluetoothUuid.is32BitUuid(uuid)) {
-                    ++num32BitUuids;
-                } else {
-                    ++num128BitUuids;
-                }
-            }
-            // 16 bit service uuids are grouped into one field when doing advertising.
-            if (num16BitUuids != 0) {
-                size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
-            }
-            // 32 bit service uuids are grouped into one field when doing advertising.
-            if (num32BitUuids != 0) {
-                size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
-            }
-            // 128 bit service uuids are grouped into one field when doing advertising.
-            if (num128BitUuids != 0) {
-                size += OVERHEAD_BYTES_PER_FIELD
-                        + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
-            }
-        }
-        for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) {
-            size += OVERHEAD_BYTES_PER_FIELD + transportDiscoveryData.totalBytes();
-        }
-        for (ParcelUuid uuid : data.getServiceData().keySet()) {
-            int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
-            size += OVERHEAD_BYTES_PER_FIELD + uuidLen
-                    + byteLength(data.getServiceData().get(uuid));
-        }
-        for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
-            size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH
-                    + byteLength(data.getManufacturerSpecificData().valueAt(i));
-        }
-        if (data.getIncludeTxPowerLevel()) {
-            size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte.
-        }
-        if (data.getIncludeDeviceName()) {
-            final int length = mBluetoothAdapter.getNameLengthForAdvertise();
-            if (length >= 0) {
-                size += OVERHEAD_BYTES_PER_FIELD + length;
-            }
-        }
-        return size;
-    }
-
-    private int byteLength(byte[] array) {
-        return array == null ? 0 : array.length;
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
-        return new IAdvertisingSetCallback.Stub() {
-            @Override
-            public void onAdvertisingSetStarted(int advertiserId, int txPower, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
-                            callback.onAdvertisingSetStarted(null, 0, status);
-                            mCallbackWrappers.remove(callback);
-                            return;
-                        }
-
-                        AdvertisingSet advertisingSet = new AdvertisingSet(
-                                advertiserId, mBluetoothManager, mAttributionSource);
-                        mAdvertisingSets.put(advertiserId, advertisingSet);
-                        callback.onAdvertisingSetStarted(advertisingSet, txPower, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onOwnAddressRead(int advertiserId, int addressType, String address) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onOwnAddressRead(advertisingSet, addressType, address);
-                    }
-                });
-            }
-
-            @Override
-            public void onAdvertisingSetStopped(int advertiserId) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onAdvertisingSetStopped(advertisingSet);
-                        mAdvertisingSets.remove(advertiserId);
-                        mCallbackWrappers.remove(callback);
-                    }
-                });
-            }
-
-            @Override
-            public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onAdvertisingEnabled(advertisingSet, enabled, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onAdvertisingDataSet(int advertiserId, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onAdvertisingDataSet(advertisingSet, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onScanResponseDataSet(int advertiserId, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onScanResponseDataSet(advertisingSet, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onAdvertisingParametersUpdated(advertisingSet, txPower, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onPeriodicAdvertisingDataSet(int advertiserId, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
-                    }
-                });
-            }
-
-            @Override
-            public void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
-                        callback.onPeriodicAdvertisingEnabled(advertisingSet, enable, status);
-                    }
-                });
-            }
-        };
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback,
-            final int error) {
-        handler.post(new Runnable() {
-            @Override
-            public void run() {
-                callback.onAdvertisingSetStarted(null, 0, error);
-            }
-        });
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private void postStartFailure(final AdvertiseCallback callback, final int error) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                callback.onStartFailure(error);
-            }
-        });
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private void postStartSuccess(final AdvertiseCallback callback,
-            final AdvertiseSettings settings) {
-        mHandler.post(new Runnable() {
-
-            @Override
-            public void run() {
-                callback.onStartSuccess(settings);
-            }
-        });
-    }
-}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
deleted file mode 100644
index 540e5a7..0000000
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresNoPermission;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.app.PendingIntent;
-import android.bluetooth.Attributable;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.WorkSource;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class provides methods to perform scan related operations for Bluetooth LE devices. An
- * application can scan for a particular type of Bluetooth LE devices using {@link ScanFilter}. It
- * can also request different types of callbacks for delivering the result.
- * <p>
- * Use {@link BluetoothAdapter#getBluetoothLeScanner()} to get an instance of
- * {@link BluetoothLeScanner}.
- *
- * @see ScanFilter
- */
-public final class BluetoothLeScanner {
-
-    private static final String TAG = "BluetoothLeScanner";
-    private static final boolean DBG = true;
-    private static final boolean VDBG = false;
-
-    /**
-     * Extra containing a list of ScanResults. It can have one or more results if there was no
-     * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
-     * extra will not be available.
-     */
-    public static final String EXTRA_LIST_SCAN_RESULT =
-            "android.bluetooth.le.extra.LIST_SCAN_RESULT";
-
-    /**
-     * Optional extra indicating the error code, if any. The error code will be one of the
-     * SCAN_FAILED_* codes in {@link ScanCallback}.
-     */
-    public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
-
-    /**
-     * Optional extra indicating the callback type, which will be one of
-     * CALLBACK_TYPE_* constants in {@link ScanSettings}.
-     *
-     * @see ScanCallback#onScanResult(int, ScanResult)
-     */
-    public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
-
-    private final BluetoothAdapter mBluetoothAdapter;
-    private final IBluetoothManager mBluetoothManager;
-    private final AttributionSource mAttributionSource;
-
-    private final Handler mHandler;
-    private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients;
-
-    /**
-     * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
-     *
-     * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
-     * @param opPackageName The opPackageName of the context this object was created from
-     * @param featureId  The featureId of the context this object was created from
-     * @hide
-     */
-    public BluetoothLeScanner(BluetoothAdapter bluetoothAdapter) {
-        mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
-        mBluetoothManager = mBluetoothAdapter.getBluetoothManager();
-        mAttributionSource = mBluetoothAdapter.getAttributionSource();
-        mHandler = new Handler(Looper.getMainLooper());
-        mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>();
-    }
-
-    /**
-     * Start Bluetooth LE scan with default parameters and no filters. The scan results will be
-     * delivered through {@code callback}. For unfiltered scans, scanning is stopped on screen
-     * off to save power. Scanning is resumed when screen is turned on again. To avoid this, use
-     * {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}.
-     * <p>
-     * An app must have
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
-     * in order to get results. An App targeting Android Q or later must have
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
-     * in order to get results.
-     *
-     * @param callback Callback used to deliver scan results.
-     * @throws IllegalArgumentException If {@code callback} is null.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void startScan(final ScanCallback callback) {
-        startScan(null, new ScanSettings.Builder().build(), callback);
-    }
-
-    /**
-     * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
-     * For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
-     * resumed when screen is turned on again. To avoid this, do filetered scanning by
-     * using proper {@link ScanFilter}.
-     * <p>
-     * An app must have
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
-     * in order to get results. An App targeting Android Q or later must have
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
-     * in order to get results.
-     *
-     * @param filters {@link ScanFilter}s for finding exact BLE devices.
-     * @param settings Settings for the scan.
-     * @param callback Callback used to deliver scan results.
-     * @throws IllegalArgumentException If {@code settings} or {@code callback} is null.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void startScan(List<ScanFilter> filters, ScanSettings settings,
-            final ScanCallback callback) {
-        startScan(filters, settings, null, callback, /*callbackIntent=*/ null);
-    }
-
-    /**
-     * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
-     * the PendingIntent. Use this method of scanning if your process is not always running and it
-     * should be started when scan results are available.
-     * <p>
-     * An app must have
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
-     * in order to get results. An App targeting Android Q or later must have
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
-     * in order to get results.
-     * <p>
-     * When the PendingIntent is delivered, the Intent passed to the receiver or activity
-     * will contain one or more of the extras {@link #EXTRA_CALLBACK_TYPE},
-     * {@link #EXTRA_ERROR_CODE} and {@link #EXTRA_LIST_SCAN_RESULT} to indicate the result of
-     * the scan.
-     *
-     * @param filters Optional list of ScanFilters for finding exact BLE devices.
-     * @param settings Optional settings for the scan.
-     * @param callbackIntent The PendingIntent to deliver the result to.
-     * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
-     * could not be sent.
-     * @see #stopScan(PendingIntent)
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
-            @NonNull PendingIntent callbackIntent) {
-        return startScan(filters,
-                settings != null ? settings : new ScanSettings.Builder().build(),
-                null, null, callbackIntent);
-    }
-
-    /**
-     * Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to
-     * specify on behalf of which application(s) the work is being done.
-     *
-     * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
-     * the scan.
-     * @param callback Callback used to deliver scan results.
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_SCAN,
-            android.Manifest.permission.UPDATE_DEVICE_STATS
-    })
-    public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) {
-        startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback);
-    }
-
-    /**
-     * Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but
-     * allows the caller to specify on behalf of which application(s) the work is being done.
-     *
-     * @param filters {@link ScanFilter}s for finding exact BLE devices.
-     * @param settings Settings for the scan.
-     * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
-     * the scan.
-     * @param callback Callback used to deliver scan results.
-     * @hide
-     */
-    @SystemApi
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_SCAN,
-            android.Manifest.permission.UPDATE_DEVICE_STATS
-    })
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
-            final WorkSource workSource, final ScanCallback callback) {
-        startScan(filters, settings, workSource, callback, null);
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    private int startScan(List<ScanFilter> filters, ScanSettings settings,
-            final WorkSource workSource, final ScanCallback callback,
-            final PendingIntent callbackIntent) {
-        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        if (callback == null && callbackIntent == null) {
-            throw new IllegalArgumentException("callback is null");
-        }
-        if (settings == null) {
-            throw new IllegalArgumentException("settings is null");
-        }
-        synchronized (mLeScanClients) {
-            if (callback != null && mLeScanClients.containsKey(callback)) {
-                return postCallbackErrorOrReturn(callback,
-                            ScanCallback.SCAN_FAILED_ALREADY_STARTED);
-            }
-            IBluetoothGatt gatt;
-            try {
-                gatt = mBluetoothManager.getBluetoothGatt();
-            } catch (RemoteException e) {
-                gatt = null;
-            }
-            if (gatt == null) {
-                return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
-            }
-            if (!isSettingsConfigAllowedForScan(settings)) {
-                return postCallbackErrorOrReturn(callback,
-                        ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
-            }
-            if (!isHardwareResourcesAvailableForScan(settings)) {
-                return postCallbackErrorOrReturn(callback,
-                        ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
-            }
-            if (!isSettingsAndFilterComboAllowed(settings, filters)) {
-                return postCallbackErrorOrReturn(callback,
-                        ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
-            }
-            if (callback != null) {
-                BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
-                        settings, workSource, callback);
-                wrapper.startRegistration();
-            } else {
-                try {
-                    gatt.startScanForIntent(callbackIntent, settings, filters,
-                            mAttributionSource);
-                } catch (RemoteException e) {
-                    return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
-                }
-            }
-        }
-        return ScanCallback.NO_ERROR;
-    }
-
-    /**
-     * Stops an ongoing Bluetooth LE scan.
-     *
-     * @param callback
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void stopScan(ScanCallback callback) {
-        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        synchronized (mLeScanClients) {
-            BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
-            if (wrapper == null) {
-                if (DBG) Log.d(TAG, "could not find callback wrapper");
-                return;
-            }
-            wrapper.stopLeScan();
-        }
-    }
-
-    /**
-     * Stops an ongoing Bluetooth LE scan started using a PendingIntent. When creating the
-     * PendingIntent parameter, please do not use the FLAG_CANCEL_CURRENT flag. Otherwise, the stop
-     * scan may have no effect.
-     *
-     * @param callbackIntent The PendingIntent that was used to start the scan.
-     * @see #startScan(List, ScanSettings, PendingIntent)
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void stopScan(PendingIntent callbackIntent) {
-        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        IBluetoothGatt gatt;
-        try {
-            gatt = mBluetoothManager.getBluetoothGatt();
-            gatt.stopScanForIntent(callbackIntent, mAttributionSource);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
-     * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
-     * will be delivered through the {@code callback}.
-     *
-     * @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one
-     * used to start scan.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void flushPendingScanResults(ScanCallback callback) {
-        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null!");
-        }
-        synchronized (mLeScanClients) {
-            BleScanCallbackWrapper wrapper = mLeScanClients.get(callback);
-            if (wrapper == null) {
-                return;
-            }
-            wrapper.flushPendingBatchResults();
-        }
-    }
-
-    /**
-     * Start truncated scan.
-     *
-     * @deprecated this is not used anywhere
-     *
-     * @hide
-     */
-    @Deprecated
-    @SystemApi
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void startTruncatedScan(List<TruncatedFilter> truncatedFilters, ScanSettings settings,
-            final ScanCallback callback) {
-        int filterSize = truncatedFilters.size();
-        List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(filterSize);
-        for (TruncatedFilter filter : truncatedFilters) {
-            scanFilters.add(filter.getFilter());
-        }
-        startScan(scanFilters, settings, null, callback, null);
-    }
-
-    /**
-     * Cleans up scan clients. Should be called when bluetooth is down.
-     *
-     * @hide
-     */
-    @RequiresNoPermission
-    public void cleanup() {
-        mLeScanClients.clear();
-    }
-
-    /**
-     * Bluetooth GATT interface callbacks
-     */
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    private class BleScanCallbackWrapper extends IScannerCallback.Stub {
-        private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000;
-
-        private final ScanCallback mScanCallback;
-        private final List<ScanFilter> mFilters;
-        private final WorkSource mWorkSource;
-        private ScanSettings mSettings;
-        private IBluetoothGatt mBluetoothGatt;
-
-        // mLeHandle 0: not registered
-        // -2: registration failed because app is scanning to frequently
-        // -1: scan stopped or registration failed
-        // > 0: registered and scan started
-        private int mScannerId;
-
-        public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt,
-                List<ScanFilter> filters, ScanSettings settings,
-                WorkSource workSource, ScanCallback scanCallback) {
-            mBluetoothGatt = bluetoothGatt;
-            mFilters = filters;
-            mSettings = settings;
-            mWorkSource = workSource;
-            mScanCallback = scanCallback;
-            mScannerId = 0;
-        }
-
-        public void startRegistration() {
-            synchronized (this) {
-                // Scan stopped.
-                if (mScannerId == -1 || mScannerId == -2) return;
-                try {
-                    mBluetoothGatt.registerScanner(this, mWorkSource, mAttributionSource);
-                    wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS);
-                } catch (InterruptedException | RemoteException e) {
-                    Log.e(TAG, "application registeration exception", e);
-                    postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
-                }
-                if (mScannerId > 0) {
-                    mLeScanClients.put(mScanCallback, this);
-                } else {
-                    // Registration timed out or got exception, reset RscannerId to -1 so no
-                    // subsequent operations can proceed.
-                    if (mScannerId == 0) mScannerId = -1;
-
-                    // If scanning too frequently, don't report anything to the app.
-                    if (mScannerId == -2) return;
-
-                    postCallbackError(mScanCallback,
-                            ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
-                }
-            }
-        }
-
-        @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-        public void stopLeScan() {
-            synchronized (this) {
-                if (mScannerId <= 0) {
-                    Log.e(TAG, "Error state, mLeHandle: " + mScannerId);
-                    return;
-                }
-                try {
-                    mBluetoothGatt.stopScan(mScannerId, mAttributionSource);
-                    mBluetoothGatt.unregisterScanner(mScannerId, mAttributionSource);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to stop scan and unregister", e);
-                }
-                mScannerId = -1;
-            }
-        }
-
-        @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-        void flushPendingBatchResults() {
-            synchronized (this) {
-                if (mScannerId <= 0) {
-                    Log.e(TAG, "Error state, mLeHandle: " + mScannerId);
-                    return;
-                }
-                try {
-                    mBluetoothGatt.flushPendingBatchResults(mScannerId, mAttributionSource);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to get pending scan results", e);
-                }
-            }
-        }
-
-        /**
-         * Application interface registered - app is ready to go
-         */
-        @Override
-        public void onScannerRegistered(int status, int scannerId) {
-            Log.d(TAG, "onScannerRegistered() - status=" + status
-                    + " scannerId=" + scannerId + " mScannerId=" + mScannerId);
-            synchronized (this) {
-                if (status == BluetoothGatt.GATT_SUCCESS) {
-                    try {
-                        if (mScannerId == -1) {
-                            // Registration succeeds after timeout, unregister scanner.
-                            mBluetoothGatt.unregisterScanner(scannerId, mAttributionSource);
-                        } else {
-                            mScannerId = scannerId;
-                            mBluetoothGatt.startScan(mScannerId, mSettings, mFilters,
-                                    mAttributionSource);
-                        }
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "fail to start le scan: " + e);
-                        mScannerId = -1;
-                    }
-                } else if (status == ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY) {
-                    // applicaiton was scanning too frequently
-                    mScannerId = -2;
-                } else {
-                    // registration failed
-                    mScannerId = -1;
-                }
-                notifyAll();
-            }
-        }
-
-        /**
-         * Callback reporting an LE scan result.
-         *
-         * @hide
-         */
-        @Override
-        public void onScanResult(final ScanResult scanResult) {
-            Attributable.setAttributionSource(scanResult, mAttributionSource);
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onScanResult() - mScannerId=" + mScannerId);
-            }
-            if (VDBG) Log.d(TAG, "onScanResult() - " + scanResult.toString());
-
-            // Check null in case the scan has been stopped
-            synchronized (this) {
-                if (mScannerId <= 0) {
-                    if (Log.isLoggable(TAG, Log.DEBUG)) {
-                        Log.d(TAG, "Ignoring result as scan stopped.");
-                    }
-                    return;
-                };
-            }
-            Handler handler = new Handler(Looper.getMainLooper());
-            handler.post(new Runnable() {
-                @Override
-                public void run() {
-                    if (Log.isLoggable(TAG, Log.DEBUG)) {
-                        Log.d(TAG, "onScanResult() - handler run");
-                    }
-                    mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
-                }
-            });
-        }
-
-        @Override
-        public void onBatchScanResults(final List<ScanResult> results) {
-            Attributable.setAttributionSource(results, mAttributionSource);
-            Handler handler = new Handler(Looper.getMainLooper());
-            handler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mScanCallback.onBatchScanResults(results);
-                }
-            });
-        }
-
-        @Override
-        public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) {
-            Attributable.setAttributionSource(scanResult, mAttributionSource);
-            if (VDBG) {
-                Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + " " + scanResult.toString());
-            }
-
-            // Check null in case the scan has been stopped
-            synchronized (this) {
-                if (mScannerId <= 0) {
-                    return;
-                }
-            }
-            Handler handler = new Handler(Looper.getMainLooper());
-            handler.post(new Runnable() {
-                @Override
-                public void run() {
-                    if (onFound) {
-                        mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH,
-                                scanResult);
-                    } else {
-                        mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST,
-                                scanResult);
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onScanManagerErrorCallback(final int errorCode) {
-            if (VDBG) {
-                Log.d(TAG, "onScanManagerErrorCallback() - errorCode = " + errorCode);
-            }
-            synchronized (this) {
-                if (mScannerId <= 0) {
-                    return;
-                }
-            }
-            postCallbackError(mScanCallback, errorCode);
-        }
-    }
-
-    private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
-        if (callback == null) {
-            return errorCode;
-        } else {
-            postCallbackError(callback, errorCode);
-            return ScanCallback.NO_ERROR;
-        }
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private void postCallbackError(final ScanCallback callback, final int errorCode) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                callback.onScanFailed(errorCode);
-            }
-        });
-    }
-
-    private boolean isSettingsConfigAllowedForScan(ScanSettings settings) {
-        if (mBluetoothAdapter.isOffloadedFilteringSupported()) {
-            return true;
-        }
-        final int callbackType = settings.getCallbackType();
-        // Only support regular scan if no offloaded filter support.
-        if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES
-                && settings.getReportDelayMillis() == 0) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean isSettingsAndFilterComboAllowed(ScanSettings settings,
-            List<ScanFilter> filterList) {
-        final int callbackType = settings.getCallbackType();
-        // If onlost/onfound is requested, a non-empty filter is expected
-        if ((callbackType & (ScanSettings.CALLBACK_TYPE_FIRST_MATCH
-                | ScanSettings.CALLBACK_TYPE_MATCH_LOST)) != 0) {
-            if (filterList == null) {
-                return false;
-            }
-            for (ScanFilter filter : filterList) {
-                if (filter.isAllFieldsEmpty()) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private boolean isHardwareResourcesAvailableForScan(ScanSettings settings) {
-        final int callbackType = settings.getCallbackType();
-        if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0
-                || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) {
-            // For onlost/onfound, we required hw support be available
-            return (mBluetoothAdapter.isOffloadedFilteringSupported()
-                    && mBluetoothAdapter.isHardwareTrackingFiltersAvailable());
-        }
-        return true;
-    }
-}
diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java
deleted file mode 100644
index ed50b09..0000000
--- a/core/java/android/bluetooth/le/BluetoothLeUtils.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothAdapter;
-import android.util.SparseArray;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Helper class for Bluetooth LE utils.
- *
- * @hide
- */
-public class BluetoothLeUtils {
-
-    /**
-     * Returns a string composed from a {@link SparseArray}.
-     */
-    static String toString(SparseArray<byte[]> array) {
-        if (array == null) {
-            return "null";
-        }
-        if (array.size() == 0) {
-            return "{}";
-        }
-        StringBuilder buffer = new StringBuilder();
-        buffer.append('{');
-        for (int i = 0; i < array.size(); ++i) {
-            buffer.append(array.keyAt(i)).append("=").append(Arrays.toString(array.valueAt(i)));
-        }
-        buffer.append('}');
-        return buffer.toString();
-    }
-
-    /**
-     * Returns a string composed from a {@link Map}.
-     */
-    static <T> String toString(Map<T, byte[]> map) {
-        if (map == null) {
-            return "null";
-        }
-        if (map.isEmpty()) {
-            return "{}";
-        }
-        StringBuilder buffer = new StringBuilder();
-        buffer.append('{');
-        Iterator<Map.Entry<T, byte[]>> it = map.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<T, byte[]> entry = it.next();
-            Object key = entry.getKey();
-            buffer.append(key).append("=").append(Arrays.toString(map.get(key)));
-            if (it.hasNext()) {
-                buffer.append(", ");
-            }
-        }
-        buffer.append('}');
-        return buffer.toString();
-    }
-
-    /**
-     * Check whether two {@link SparseArray} equal.
-     */
-    static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) {
-        if (array == otherArray) {
-            return true;
-        }
-        if (array == null || otherArray == null) {
-            return false;
-        }
-        if (array.size() != otherArray.size()) {
-            return false;
-        }
-
-        // Keys are guaranteed in ascending order when indices are in ascending order.
-        for (int i = 0; i < array.size(); ++i) {
-            if (array.keyAt(i) != otherArray.keyAt(i)
-                    || !Arrays.equals(array.valueAt(i), otherArray.valueAt(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Check whether two {@link Map} equal.
-     */
-    static <T> boolean equals(Map<T, byte[]> map, Map<T, byte[]> otherMap) {
-        if (map == otherMap) {
-            return true;
-        }
-        if (map == null || otherMap == null) {
-            return false;
-        }
-        if (map.size() != otherMap.size()) {
-            return false;
-        }
-        Set<T> keys = map.keySet();
-        if (!keys.equals(otherMap.keySet())) {
-            return false;
-        }
-        for (T key : keys) {
-            if (!Objects.deepEquals(map.get(key), otherMap.get(key))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Ensure Bluetooth is turned on.
-     *
-     * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not {@link
-     * BluetoothAdapter#STATE_ON}.
-     */
-    static void checkAdapterStateOn(BluetoothAdapter adapter) {
-        if (adapter == null || !adapter.isLeEnabled()) {
-            throw new IllegalStateException("BT Adapter is not turned ON");
-        }
-    }
-
-    /**
-     * Compares two UUIDs with a UUID mask.
-     *
-     * @param data first {@link #UUID} to compare.
-     * @param uuid second {@link #UUID} to compare.
-     * @param mask mask {@link #UUID}.
-     * @return true if both UUIDs are equals when masked, false otherwise.
-     */
-    static boolean maskedEquals(UUID data, UUID uuid, UUID mask) {
-        if (mask == null) {
-            return Objects.equals(data, uuid);
-        }
-        return (data.getLeastSignificantBits() & mask.getLeastSignificantBits())
-                == (uuid.getLeastSignificantBits() & mask.getLeastSignificantBits())
-                && (data.getMostSignificantBits() & mask.getMostSignificantBits())
-                == (uuid.getMostSignificantBits() & mask.getMostSignificantBits());
-    }
-}
diff --git a/core/java/android/bluetooth/le/OWNERS b/core/java/android/bluetooth/le/OWNERS
deleted file mode 100644
index 3523ee0..0000000
--- a/core/java/android/bluetooth/le/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 27441
-
-zachoverflow@google.com
-siyuanh@google.com
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
deleted file mode 100644
index 14ac911..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothDevice;
-
-/**
- * Bluetooth LE periodic advertising callbacks, used to deliver periodic
- * advertising operation status.
- *
- * @hide
- * @see PeriodicAdvertisingManager#createSync
- */
-public abstract class PeriodicAdvertisingCallback {
-
-    /**
-     * The requested operation was successful.
-     *
-     * @hide
-     */
-    public static final int SYNC_SUCCESS = 0;
-
-    /**
-     * Sync failed to be established because remote device did not respond.
-     */
-    public static final int SYNC_NO_RESPONSE = 1;
-
-    /**
-     * Sync failed to be established because controller can't support more syncs.
-     */
-    public static final int SYNC_NO_RESOURCES = 2;
-
-
-    /**
-     * Callback when synchronization was established.
-     *
-     * @param syncHandle handle used to identify this synchronization.
-     * @param device remote device.
-     * @param advertisingSid synchronized advertising set id.
-     * @param skip The number of periodic advertising packets that can be skipped after a successful
-     * receive in force. @see PeriodicAdvertisingManager#createSync
-     * @param timeout Synchronization timeout for the periodic advertising in force. One unit is
-     * 10ms. @see PeriodicAdvertisingManager#createSync
-     * @param timeout
-     * @param status operation status.
-     */
-    public void onSyncEstablished(int syncHandle, BluetoothDevice device,
-            int advertisingSid, int skip, int timeout,
-            int status) {
-    }
-
-    /**
-     * Callback when periodic advertising report is received.
-     *
-     * @param report periodic advertising report.
-     */
-    public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
-    }
-
-    /**
-     * Callback when periodic advertising synchronization was lost.
-     *
-     * @param syncHandle handle used to identify this synchronization.
-     */
-    public void onSyncLost(int syncHandle) {
-    }
-}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
deleted file mode 100644
index bbd3117..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.bluetooth.Attributable;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
-import android.content.AttributionSource;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * This class provides methods to perform periodic advertising related
- * operations. An application can register for periodic advertisements using
- * {@link PeriodicAdvertisingManager#registerSync}.
- * <p>
- * Use {@link BluetoothAdapter#getPeriodicAdvertisingManager()} to get an
- * instance of {@link PeriodicAdvertisingManager}.
- *
- * @hide
- */
-public final class PeriodicAdvertisingManager {
-
-    private static final String TAG = "PeriodicAdvertisingManager";
-
-    private static final int SKIP_MIN = 0;
-    private static final int SKIP_MAX = 499;
-    private static final int TIMEOUT_MIN = 10;
-    private static final int TIMEOUT_MAX = 16384;
-
-    private static final int SYNC_STARTING = -1;
-
-    private final BluetoothAdapter mBluetoothAdapter;
-    private final IBluetoothManager mBluetoothManager;
-    private final AttributionSource mAttributionSource;
-
-    /* maps callback, to callback wrapper and sync handle */
-    Map<PeriodicAdvertisingCallback,
-            IPeriodicAdvertisingCallback /* callbackWrapper */> mCallbackWrappers;
-
-    /**
-     * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
-     *
-     * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
-     * @hide
-     */
-    public PeriodicAdvertisingManager(BluetoothAdapter bluetoothAdapter) {
-        mBluetoothAdapter = Objects.requireNonNull(bluetoothAdapter);
-        mBluetoothManager = mBluetoothAdapter.getBluetoothManager();
-        mAttributionSource = mBluetoothAdapter.getAttributionSource();
-        mCallbackWrappers = new IdentityHashMap<>();
-    }
-
-    /**
-     * Synchronize with periodic advertising pointed to by the {@code scanResult}.
-     * The {@code scanResult} used must contain a valid advertisingSid. First
-     * call to registerSync will use the {@code skip} and {@code timeout} provided.
-     * Subsequent calls from other apps, trying to sync with same set will reuse
-     * existing sync, thus {@code skip} and {@code timeout} values will not take
-     * effect. The values in effect will be returned in
-     * {@link PeriodicAdvertisingCallback#onSyncEstablished}.
-     *
-     * @param scanResult Scan result containing advertisingSid.
-     * @param skip The number of periodic advertising packets that can be skipped after a successful
-     * receive. Must be between 0 and 499.
-     * @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must
-     * be between 10 (100ms) and 16384 (163.84s).
-     * @param callback Callback used to deliver all operations status.
-     * @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or
-     * {@code timeout} is invalid or {@code callback} is null.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void registerSync(ScanResult scanResult, int skip, int timeout,
-            PeriodicAdvertisingCallback callback) {
-        registerSync(scanResult, skip, timeout, callback, null);
-    }
-
-    /**
-     * Synchronize with periodic advertising pointed to by the {@code scanResult}.
-     * The {@code scanResult} used must contain a valid advertisingSid. First
-     * call to registerSync will use the {@code skip} and {@code timeout} provided.
-     * Subsequent calls from other apps, trying to sync with same set will reuse
-     * existing sync, thus {@code skip} and {@code timeout} values will not take
-     * effect. The values in effect will be returned in
-     * {@link PeriodicAdvertisingCallback#onSyncEstablished}.
-     *
-     * @param scanResult Scan result containing advertisingSid.
-     * @param skip The number of periodic advertising packets that can be skipped after a successful
-     * receive. Must be between 0 and 499.
-     * @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must
-     * be between 10 (100ms) and 16384 (163.84s).
-     * @param callback Callback used to deliver all operations status.
-     * @param handler thread upon which the callbacks will be invoked.
-     * @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or
-     * {@code timeout} is invalid or {@code callback} is null.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresBluetoothLocationPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void registerSync(ScanResult scanResult, int skip, int timeout,
-            PeriodicAdvertisingCallback callback, Handler handler) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback can't be null");
-        }
-
-        if (scanResult == null) {
-            throw new IllegalArgumentException("scanResult can't be null");
-        }
-
-        if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) {
-            throw new IllegalArgumentException("scanResult must contain a valid sid");
-        }
-
-        if (skip < SKIP_MIN || skip > SKIP_MAX) {
-            throw new IllegalArgumentException(
-                    "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
-        }
-
-        if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) {
-            throw new IllegalArgumentException(
-                    "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
-        }
-
-        IBluetoothGatt gatt;
-        try {
-            gatt = mBluetoothManager.getBluetoothGatt();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
-            callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(),
-                    skip, timeout,
-                    PeriodicAdvertisingCallback.SYNC_NO_RESOURCES);
-            return;
-        }
-
-        if (handler == null) {
-            handler = new Handler(Looper.getMainLooper());
-        }
-
-        IPeriodicAdvertisingCallback wrapped = wrap(callback, handler);
-        mCallbackWrappers.put(callback, wrapped);
-
-        try {
-            gatt.registerSync(
-                    scanResult, skip, timeout, wrapped, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to register sync - ", e);
-            return;
-        }
-    }
-
-    /**
-     * Cancel pending attempt to create sync, or terminate existing sync.
-     *
-     * @param callback Callback used to deliver all operations status.
-     * @throws IllegalArgumentException if {@code callback} is null, or not a properly registered
-     * callback.
-     */
-    @RequiresLegacyBluetoothAdminPermission
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void unregisterSync(PeriodicAdvertisingCallback callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback can't be null");
-        }
-
-        IBluetoothGatt gatt;
-        try {
-            gatt = mBluetoothManager.getBluetoothGatt();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
-            return;
-        }
-
-        IPeriodicAdvertisingCallback wrapper = mCallbackWrappers.remove(callback);
-        if (wrapper == null) {
-            throw new IllegalArgumentException("callback was not properly registered");
-        }
-
-        try {
-            gatt.unregisterSync(wrapper, mAttributionSource);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to cancel sync creation - ", e);
-            return;
-        }
-    }
-
-    @SuppressLint("AndroidFrameworkBluetoothPermission")
-    private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback,
-            Handler handler) {
-        return new IPeriodicAdvertisingCallback.Stub() {
-            public void onSyncEstablished(int syncHandle, BluetoothDevice device,
-                    int advertisingSid, int skip, int timeout, int status) {
-                Attributable.setAttributionSource(device, mAttributionSource);
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        callback.onSyncEstablished(syncHandle, device, advertisingSid, skip,
-                                timeout,
-                                status);
-
-                        if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) {
-                            // App can still unregister the sync until notified it failed. Remove
-                            // callback
-                            // after app was notifed.
-                            mCallbackWrappers.remove(callback);
-                        }
-                    }
-                });
-            }
-
-            public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        callback.onPeriodicAdvertisingReport(report);
-                    }
-                });
-            }
-
-            public void onSyncLost(int syncHandle) {
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        callback.onSyncLost(syncHandle);
-                        // App can still unregister the sync until notified it's lost.
-                        // Remove callback after app was notifed.
-                        mCallbackWrappers.remove(callback);
-                    }
-                });
-            }
-        };
-    }
-}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
deleted file mode 100644
index 4e64dbe..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * The {@link PeriodicAdvertisingParameters} provide a way to adjust periodic
- * advertising preferences for each Bluetooth LE advertising set. Use {@link
- * PeriodicAdvertisingParameters.Builder} to create an instance of this class.
- */
-public final class PeriodicAdvertisingParameters implements Parcelable {
-
-    private static final int INTERVAL_MIN = 80;
-    private static final int INTERVAL_MAX = 65519;
-
-    private final boolean mIncludeTxPower;
-    private final int mInterval;
-
-    private PeriodicAdvertisingParameters(boolean includeTxPower, int interval) {
-        mIncludeTxPower = includeTxPower;
-        mInterval = interval;
-    }
-
-    private PeriodicAdvertisingParameters(Parcel in) {
-        mIncludeTxPower = in.readInt() != 0;
-        mInterval = in.readInt();
-    }
-
-    /**
-     * Returns whether the TX Power will be included.
-     */
-    public boolean getIncludeTxPower() {
-        return mIncludeTxPower;
-    }
-
-    /**
-     * Returns the periodic advertising interval, in 1.25ms unit.
-     * Valid values are from 80 (100ms) to 65519 (81.89875s).
-     */
-    public int getInterval() {
-        return mInterval;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mIncludeTxPower ? 1 : 0);
-        dest.writeInt(mInterval);
-    }
-
-    public static final Parcelable
-            .Creator<PeriodicAdvertisingParameters> CREATOR =
-            new Creator<PeriodicAdvertisingParameters>() {
-                @Override
-                public PeriodicAdvertisingParameters[] newArray(int size) {
-                    return new PeriodicAdvertisingParameters[size];
-                }
-
-                @Override
-                public PeriodicAdvertisingParameters createFromParcel(Parcel in) {
-                    return new PeriodicAdvertisingParameters(in);
-                }
-            };
-
-    public static final class Builder {
-        private boolean mIncludeTxPower = false;
-        private int mInterval = INTERVAL_MAX;
-
-        /**
-         * Whether the transmission power level should be included in the periodic
-         * packet.
-         */
-        public Builder setIncludeTxPower(boolean includeTxPower) {
-            mIncludeTxPower = includeTxPower;
-            return this;
-        }
-
-        /**
-         * Set advertising interval for periodic advertising, in 1.25ms unit.
-         * Valid values are from 80 (100ms) to 65519 (81.89875s).
-         * Value from range [interval, interval+20ms] will be picked as the actual value.
-         *
-         * @throws IllegalArgumentException If the interval is invalid.
-         */
-        public Builder setInterval(int interval) {
-            if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) {
-                throw new IllegalArgumentException("Invalid interval (must be " + INTERVAL_MIN
-                        + "-" + INTERVAL_MAX + ")");
-            }
-            mInterval = interval;
-            return this;
-        }
-
-        /**
-         * Build the {@link AdvertisingSetParameters} object.
-         */
-        public PeriodicAdvertisingParameters build() {
-            return new PeriodicAdvertisingParameters(mIncludeTxPower, mInterval);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
deleted file mode 100644
index 54b953c..0000000
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
- *
- * @hide
- */
-public final class PeriodicAdvertisingReport implements Parcelable {
-
-    /**
-     * The data returned is complete
-     */
-    public static final int DATA_COMPLETE = 0;
-
-    /**
-     * The data returned is incomplete. The controller was unsuccessfull to
-     * receive all chained packets, returning only partial data.
-     */
-    public static final int DATA_INCOMPLETE_TRUNCATED = 2;
-
-    private int mSyncHandle;
-    private int mTxPower;
-    private int mRssi;
-    private int mDataStatus;
-
-    // periodic advertising data.
-    @Nullable
-    private ScanRecord mData;
-
-    // Device timestamp when the result was last seen.
-    private long mTimestampNanos;
-
-    /**
-     * Constructor of periodic advertising result.
-     */
-    public PeriodicAdvertisingReport(int syncHandle, int txPower, int rssi,
-            int dataStatus, ScanRecord data) {
-        mSyncHandle = syncHandle;
-        mTxPower = txPower;
-        mRssi = rssi;
-        mDataStatus = dataStatus;
-        mData = data;
-    }
-
-    private PeriodicAdvertisingReport(Parcel in) {
-        readFromParcel(in);
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mSyncHandle);
-        dest.writeInt(mTxPower);
-        dest.writeInt(mRssi);
-        dest.writeInt(mDataStatus);
-        if (mData != null) {
-            dest.writeInt(1);
-            dest.writeByteArray(mData.getBytes());
-        } else {
-            dest.writeInt(0);
-        }
-    }
-
-    private void readFromParcel(Parcel in) {
-        mSyncHandle = in.readInt();
-        mTxPower = in.readInt();
-        mRssi = in.readInt();
-        mDataStatus = in.readInt();
-        if (in.readInt() == 1) {
-            mData = ScanRecord.parseFromBytes(in.createByteArray());
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Returns the synchronization handle.
-     */
-    public int getSyncHandle() {
-        return mSyncHandle;
-    }
-
-    /**
-     * Returns the transmit power in dBm. The valid range is [-127, 126]. Value
-     * of 127 means information was not available.
-     */
-    public int getTxPower() {
-        return mTxPower;
-    }
-
-    /**
-     * Returns the received signal strength in dBm. The valid range is [-127, 20].
-     */
-    public int getRssi() {
-        return mRssi;
-    }
-
-    /**
-     * Returns the data status. Can be one of {@link PeriodicAdvertisingReport#DATA_COMPLETE}
-     * or {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}.
-     */
-    public int getDataStatus() {
-        return mDataStatus;
-    }
-
-    /**
-     * Returns the data contained in this periodic advertising report.
-     */
-    @Nullable
-    public ScanRecord getData() {
-        return mData;
-    }
-
-    /**
-     * Returns timestamp since boot when the scan record was observed.
-     */
-    public long getTimestampNanos() {
-        return mTimestampNanos;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mSyncHandle, mTxPower, mRssi, mDataStatus, mData, mTimestampNanos);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj;
-        return (mSyncHandle == other.mSyncHandle)
-                && (mTxPower == other.mTxPower)
-                && (mRssi == other.mRssi)
-                && (mDataStatus == other.mDataStatus)
-                && Objects.equals(mData, other.mData)
-                && (mTimestampNanos == other.mTimestampNanos);
-    }
-
-    @Override
-    public String toString() {
-        return "PeriodicAdvertisingReport{syncHandle=" + mSyncHandle
-                + ", txPower=" + mTxPower + ", rssi=" + mRssi + ", dataStatus=" + mDataStatus
-                + ", data=" + Objects.toString(mData) + ", timestampNanos=" + mTimestampNanos + '}';
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<PeriodicAdvertisingReport> CREATOR =
-            new Creator<PeriodicAdvertisingReport>() {
-                @Override
-                public PeriodicAdvertisingReport createFromParcel(Parcel source) {
-                    return new PeriodicAdvertisingReport(source);
-                }
-
-                @Override
-                public PeriodicAdvertisingReport[] newArray(int size) {
-                    return new PeriodicAdvertisingReport[size];
-                }
-            };
-}
diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.java b/core/java/android/bluetooth/le/ResultStorageDescriptor.java
deleted file mode 100644
index f650489..0000000
--- a/core/java/android/bluetooth/le/ResultStorageDescriptor.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Describes the way to store scan result.
- *
- * @deprecated this is not used anywhere
- *
- * @hide
- */
-@Deprecated
-@SystemApi
-public final class ResultStorageDescriptor implements Parcelable {
-    private int mType;
-    private int mOffset;
-    private int mLength;
-
-    public int getType() {
-        return mType;
-    }
-
-    public int getOffset() {
-        return mOffset;
-    }
-
-    public int getLength() {
-        return mLength;
-    }
-
-    /**
-     * Constructor of {@link ResultStorageDescriptor}
-     *
-     * @param type Type of the data.
-     * @param offset Offset from start of the advertise packet payload.
-     * @param length Byte length of the data
-     */
-    public ResultStorageDescriptor(int type, int offset, int length) {
-        mType = type;
-        mOffset = offset;
-        mLength = length;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mType);
-        dest.writeInt(mOffset);
-        dest.writeInt(mLength);
-    }
-
-    private ResultStorageDescriptor(Parcel in) {
-        ReadFromParcel(in);
-    }
-
-    private void ReadFromParcel(Parcel in) {
-        mType = in.readInt();
-        mOffset = in.readInt();
-        mLength = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<ResultStorageDescriptor> CREATOR =
-            new Creator<ResultStorageDescriptor>() {
-        @Override
-        public ResultStorageDescriptor createFromParcel(Parcel source) {
-            return new ResultStorageDescriptor(source);
-        }
-
-        @Override
-        public ResultStorageDescriptor[] newArray(int size) {
-            return new ResultStorageDescriptor[size];
-        }
-    };
-}
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
deleted file mode 100644
index 53d9310..0000000
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import java.util.List;
-
-/**
- * Bluetooth LE scan callbacks. Scan results are reported using these callbacks.
- *
- * @see BluetoothLeScanner#startScan
- */
-public abstract class ScanCallback {
-    /**
-     * Fails to start scan as BLE scan with the same settings is already started by the app.
-     */
-    public static final int SCAN_FAILED_ALREADY_STARTED = 1;
-
-    /**
-     * Fails to start scan as app cannot be registered.
-     */
-    public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2;
-
-    /**
-     * Fails to start scan due an internal error
-     */
-    public static final int SCAN_FAILED_INTERNAL_ERROR = 3;
-
-    /**
-     * Fails to start power optimized scan as this feature is not supported.
-     */
-    public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4;
-
-    /**
-     * Fails to start scan as it is out of hardware resources.
-     *
-     * @hide
-     */
-    public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5;
-
-    /**
-     * Fails to start scan as application tries to scan too frequently.
-     * @hide
-     */
-    public static final int SCAN_FAILED_SCANNING_TOO_FREQUENTLY = 6;
-
-    static final int NO_ERROR = 0;
-
-    /**
-     * Callback when a BLE advertisement has been found.
-     *
-     * @param callbackType Determines how this callback was triggered. Could be one of {@link
-     * ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or
-     * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST}
-     * @param result A Bluetooth LE scan result.
-     */
-    public void onScanResult(int callbackType, ScanResult result) {
-    }
-
-    /**
-     * Callback when batch results are delivered.
-     *
-     * @param results List of scan results that are previously scanned.
-     */
-    public void onBatchScanResults(List<ScanResult> results) {
-    }
-
-    /**
-     * Callback when scan could not be started.
-     *
-     * @param errorCode Error code (one of SCAN_FAILED_*) for scan failure.
-     */
-    public void onScanFailed(int errorCode) {
-    }
-}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
deleted file mode 100644
index b059193..0000000
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothDevice.AddressType;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * Criteria for filtering result from Bluetooth LE scans. A {@link ScanFilter} allows clients to
- * restrict scan results to only those that are of interest to them.
- * <p>
- * Current filtering on the following fields are supported:
- * <li>Service UUIDs which identify the bluetooth gatt services running on the device.
- * <li>Name of remote Bluetooth LE device.
- * <li>Mac address of the remote device.
- * <li>Service data which is the data associated with a service.
- * <li>Manufacturer specific data which is the data associated with a particular manufacturer.
- *
- * @see ScanResult
- * @see BluetoothLeScanner
- */
-public final class ScanFilter implements Parcelable {
-
-    @Nullable
-    private final String mDeviceName;
-
-    @Nullable
-    private final String mDeviceAddress;
-
-    private final @AddressType int mAddressType;
-
-    @Nullable
-    private final byte[] mIrk;
-
-    @Nullable
-    private final ParcelUuid mServiceUuid;
-    @Nullable
-    private final ParcelUuid mServiceUuidMask;
-
-    @Nullable
-    private final ParcelUuid mServiceSolicitationUuid;
-    @Nullable
-    private final ParcelUuid mServiceSolicitationUuidMask;
-
-    @Nullable
-    private final ParcelUuid mServiceDataUuid;
-    @Nullable
-    private final byte[] mServiceData;
-    @Nullable
-    private final byte[] mServiceDataMask;
-
-    private final int mManufacturerId;
-    @Nullable
-    private final byte[] mManufacturerData;
-    @Nullable
-    private final byte[] mManufacturerDataMask;
-
-    /** @hide */
-    public static final ScanFilter EMPTY = new ScanFilter.Builder().build();
-
-    private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
-            ParcelUuid uuidMask, ParcelUuid solicitationUuid,
-            ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
-            byte[] serviceData, byte[] serviceDataMask,
-            int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask,
-            @AddressType int addressType, @Nullable byte[] irk) {
-        mDeviceName = name;
-        mServiceUuid = uuid;
-        mServiceUuidMask = uuidMask;
-        mServiceSolicitationUuid = solicitationUuid;
-        mServiceSolicitationUuidMask = solicitationUuidMask;
-        mDeviceAddress = deviceAddress;
-        mServiceDataUuid = serviceDataUuid;
-        mServiceData = serviceData;
-        mServiceDataMask = serviceDataMask;
-        mManufacturerId = manufacturerId;
-        mManufacturerData = manufacturerData;
-        mManufacturerDataMask = manufacturerDataMask;
-        mAddressType = addressType;
-        mIrk = irk;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mDeviceName == null ? 0 : 1);
-        if (mDeviceName != null) {
-            dest.writeString(mDeviceName);
-        }
-        dest.writeInt(mDeviceAddress == null ? 0 : 1);
-        if (mDeviceAddress != null) {
-            dest.writeString(mDeviceAddress);
-        }
-        dest.writeInt(mServiceUuid == null ? 0 : 1);
-        if (mServiceUuid != null) {
-            dest.writeParcelable(mServiceUuid, flags);
-            dest.writeInt(mServiceUuidMask == null ? 0 : 1);
-            if (mServiceUuidMask != null) {
-                dest.writeParcelable(mServiceUuidMask, flags);
-            }
-        }
-        dest.writeInt(mServiceSolicitationUuid == null ? 0 : 1);
-        if (mServiceSolicitationUuid != null) {
-            dest.writeParcelable(mServiceSolicitationUuid, flags);
-            dest.writeInt(mServiceSolicitationUuidMask == null ? 0 : 1);
-            if (mServiceSolicitationUuidMask != null) {
-                dest.writeParcelable(mServiceSolicitationUuidMask, flags);
-            }
-        }
-        dest.writeInt(mServiceDataUuid == null ? 0 : 1);
-        if (mServiceDataUuid != null) {
-            dest.writeParcelable(mServiceDataUuid, flags);
-            dest.writeInt(mServiceData == null ? 0 : 1);
-            if (mServiceData != null) {
-                dest.writeInt(mServiceData.length);
-                dest.writeByteArray(mServiceData);
-
-                dest.writeInt(mServiceDataMask == null ? 0 : 1);
-                if (mServiceDataMask != null) {
-                    dest.writeInt(mServiceDataMask.length);
-                    dest.writeByteArray(mServiceDataMask);
-                }
-            }
-        }
-        dest.writeInt(mManufacturerId);
-        dest.writeInt(mManufacturerData == null ? 0 : 1);
-        if (mManufacturerData != null) {
-            dest.writeInt(mManufacturerData.length);
-            dest.writeByteArray(mManufacturerData);
-
-            dest.writeInt(mManufacturerDataMask == null ? 0 : 1);
-            if (mManufacturerDataMask != null) {
-                dest.writeInt(mManufacturerDataMask.length);
-                dest.writeByteArray(mManufacturerDataMask);
-            }
-        }
-
-        // IRK
-        if (mDeviceAddress != null) {
-            dest.writeInt(mAddressType);
-            dest.writeInt(mIrk == null ? 0 : 1);
-            if (mIrk != null) {
-                dest.writeByteArray(mIrk);
-            }
-        }
-    }
-
-    /**
-     * A {@link android.os.Parcelable.Creator} to create {@link ScanFilter} from parcel.
-     */
-    public static final @android.annotation.NonNull Creator<ScanFilter> CREATOR =
-            new Creator<ScanFilter>() {
-
-        @Override
-        public ScanFilter[] newArray(int size) {
-            return new ScanFilter[size];
-        }
-
-        @Override
-        public ScanFilter createFromParcel(Parcel in) {
-            Builder builder = new Builder();
-            if (in.readInt() == 1) {
-                builder.setDeviceName(in.readString());
-            }
-            String address = null;
-            // If we have a non-null address
-            if (in.readInt() == 1) {
-                address = in.readString();
-            }
-            if (in.readInt() == 1) {
-                ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader());
-                builder.setServiceUuid(uuid);
-                if (in.readInt() == 1) {
-                    ParcelUuid uuidMask = in.readParcelable(
-                            ParcelUuid.class.getClassLoader());
-                    builder.setServiceUuid(uuid, uuidMask);
-                }
-            }
-            if (in.readInt() == 1) {
-                ParcelUuid solicitationUuid = in.readParcelable(
-                        ParcelUuid.class.getClassLoader());
-                builder.setServiceSolicitationUuid(solicitationUuid);
-                if (in.readInt() == 1) {
-                    ParcelUuid solicitationUuidMask = in.readParcelable(
-                            ParcelUuid.class.getClassLoader());
-                    builder.setServiceSolicitationUuid(solicitationUuid,
-                            solicitationUuidMask);
-                }
-            }
-            if (in.readInt() == 1) {
-                ParcelUuid servcieDataUuid =
-                        in.readParcelable(ParcelUuid.class.getClassLoader());
-                if (in.readInt() == 1) {
-                    int serviceDataLength = in.readInt();
-                    byte[] serviceData = new byte[serviceDataLength];
-                    in.readByteArray(serviceData);
-                    if (in.readInt() == 0) {
-                        builder.setServiceData(servcieDataUuid, serviceData);
-                    } else {
-                        int serviceDataMaskLength = in.readInt();
-                        byte[] serviceDataMask = new byte[serviceDataMaskLength];
-                        in.readByteArray(serviceDataMask);
-                        builder.setServiceData(
-                                servcieDataUuid, serviceData, serviceDataMask);
-                    }
-                }
-            }
-
-            int manufacturerId = in.readInt();
-            if (in.readInt() == 1) {
-                int manufacturerDataLength = in.readInt();
-                byte[] manufacturerData = new byte[manufacturerDataLength];
-                in.readByteArray(manufacturerData);
-                if (in.readInt() == 0) {
-                    builder.setManufacturerData(manufacturerId, manufacturerData);
-                } else {
-                    int manufacturerDataMaskLength = in.readInt();
-                    byte[] manufacturerDataMask = new byte[manufacturerDataMaskLength];
-                    in.readByteArray(manufacturerDataMask);
-                    builder.setManufacturerData(manufacturerId, manufacturerData,
-                            manufacturerDataMask);
-                }
-            }
-
-            // 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();
-        }
-    };
-
-    /**
-     * Returns the filter set the device name field of Bluetooth advertisement data.
-     */
-    @Nullable
-    public String getDeviceName() {
-        return mDeviceName;
-    }
-
-    /**
-     * Returns the filter set on the service uuid.
-     */
-    @Nullable
-    public ParcelUuid getServiceUuid() {
-        return mServiceUuid;
-    }
-
-    @Nullable
-    public ParcelUuid getServiceUuidMask() {
-        return mServiceUuidMask;
-    }
-
-    /**
-     * Returns the filter set on the service Solicitation uuid.
-     */
-    @Nullable
-    public ParcelUuid getServiceSolicitationUuid() {
-        return mServiceSolicitationUuid;
-    }
-
-    /**
-     * Returns the filter set on the service Solicitation uuid mask.
-     */
-    @Nullable
-    public ParcelUuid getServiceSolicitationUuidMask() {
-        return mServiceSolicitationUuidMask;
-    }
-
-    @Nullable
-    public String getDeviceAddress() {
-        return mDeviceAddress;
-    }
-
-    /**
-     * @hide
-     */
-    @SystemApi
-    public @AddressType int getAddressType() {
-        return mAddressType;
-    }
-
-    /**
-     * @hide
-     */
-    @SystemApi
-    @Nullable
-    public byte[] getIrk() {
-        return mIrk;
-    }
-
-    @Nullable
-    public byte[] getServiceData() {
-        return mServiceData;
-    }
-
-    @Nullable
-    public byte[] getServiceDataMask() {
-        return mServiceDataMask;
-    }
-
-    @Nullable
-    public ParcelUuid getServiceDataUuid() {
-        return mServiceDataUuid;
-    }
-
-    /**
-     * Returns the manufacturer id. -1 if the manufacturer filter is not set.
-     */
-    public int getManufacturerId() {
-        return mManufacturerId;
-    }
-
-    @Nullable
-    public byte[] getManufacturerData() {
-        return mManufacturerData;
-    }
-
-    @Nullable
-    public byte[] getManufacturerDataMask() {
-        return mManufacturerDataMask;
-    }
-
-    /**
-     * Check if the scan filter matches a {@code scanResult}. A scan result is considered as a match
-     * if it matches all the field filters.
-     */
-    public boolean matches(ScanResult scanResult) {
-        if (scanResult == null) {
-            return false;
-        }
-        BluetoothDevice device = scanResult.getDevice();
-        // Device match.
-        if (mDeviceAddress != null
-                && (device == null || !mDeviceAddress.equals(device.getAddress()))) {
-            return false;
-        }
-
-        ScanRecord scanRecord = scanResult.getScanRecord();
-
-        // Scan record is null but there exist filters on it.
-        if (scanRecord == null
-                && (mDeviceName != null || mServiceUuid != null || mManufacturerData != null
-                || mServiceData != null || mServiceSolicitationUuid != null)) {
-            return false;
-        }
-
-        // Local name match.
-        if (mDeviceName != null && !mDeviceName.equals(scanRecord.getDeviceName())) {
-            return false;
-        }
-
-        // UUID match.
-        if (mServiceUuid != null && !matchesServiceUuids(mServiceUuid, mServiceUuidMask,
-                scanRecord.getServiceUuids())) {
-            return false;
-        }
-
-        // solicitation UUID match.
-        if (mServiceSolicitationUuid != null && !matchesServiceSolicitationUuids(
-                mServiceSolicitationUuid, mServiceSolicitationUuidMask,
-                scanRecord.getServiceSolicitationUuids())) {
-            return false;
-        }
-
-        // Service data match
-        if (mServiceDataUuid != null) {
-            if (!matchesPartialData(mServiceData, mServiceDataMask,
-                    scanRecord.getServiceData(mServiceDataUuid))) {
-                return false;
-            }
-        }
-
-        // Manufacturer data match.
-        if (mManufacturerId >= 0) {
-            if (!matchesPartialData(mManufacturerData, mManufacturerDataMask,
-                    scanRecord.getManufacturerSpecificData(mManufacturerId))) {
-                return false;
-            }
-        }
-        // All filters match.
-        return true;
-    }
-
-    /**
-     * Check if the uuid pattern is contained in a list of parcel uuids.
-     *
-     * @hide
-     */
-    public static boolean matchesServiceUuids(ParcelUuid uuid, ParcelUuid parcelUuidMask,
-            List<ParcelUuid> uuids) {
-        if (uuid == null) {
-            return true;
-        }
-        if (uuids == null) {
-            return false;
-        }
-
-        for (ParcelUuid parcelUuid : uuids) {
-            UUID uuidMask = parcelUuidMask == null ? null : parcelUuidMask.getUuid();
-            if (matchesServiceUuid(uuid.getUuid(), uuidMask, parcelUuid.getUuid())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // Check if the uuid pattern matches the particular service uuid.
-    private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
-        return BluetoothLeUtils.maskedEquals(data, uuid, mask);
-    }
-
-    /**
-     * Check if the solicitation uuid pattern is contained in a list of parcel uuids.
-     *
-     */
-    private static boolean matchesServiceSolicitationUuids(ParcelUuid solicitationUuid,
-            ParcelUuid parcelSolicitationUuidMask, List<ParcelUuid> solicitationUuids) {
-        if (solicitationUuid == null) {
-            return true;
-        }
-        if (solicitationUuids == null) {
-            return false;
-        }
-
-        for (ParcelUuid parcelSolicitationUuid : solicitationUuids) {
-            UUID solicitationUuidMask = parcelSolicitationUuidMask == null
-                    ? null : parcelSolicitationUuidMask.getUuid();
-            if (matchesServiceUuid(solicitationUuid.getUuid(), solicitationUuidMask,
-                    parcelSolicitationUuid.getUuid())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // Check if the solicitation uuid pattern matches the particular service solicitation uuid.
-    private static boolean matchesServiceSolicitationUuid(UUID solicitationUuid,
-            UUID solicitationUuidMask, UUID data) {
-        return BluetoothLeUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
-    }
-
-    // Check whether the data pattern matches the parsed data.
-    private boolean matchesPartialData(byte[] data, byte[] dataMask, byte[] parsedData) {
-        if (parsedData == null || parsedData.length < data.length) {
-            return false;
-        }
-        if (dataMask == null) {
-            for (int i = 0; i < data.length; ++i) {
-                if (parsedData[i] != data[i]) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        for (int i = 0; i < data.length; ++i) {
-            if ((dataMask[i] & parsedData[i]) != (dataMask[i] & data[i])) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return "BluetoothLeScanFilter [mDeviceName=" + mDeviceName + ", mDeviceAddress="
-                + mDeviceAddress
-                + ", mUuid=" + mServiceUuid + ", mUuidMask=" + mServiceUuidMask
-                + ", mServiceSolicitationUuid=" + mServiceSolicitationUuid
-                + ", mServiceSolicitationUuidMask=" + mServiceSolicitationUuidMask
-                + ", mServiceDataUuid=" + Objects.toString(mServiceDataUuid) + ", mServiceData="
-                + Arrays.toString(mServiceData) + ", mServiceDataMask="
-                + Arrays.toString(mServiceDataMask) + ", mManufacturerId=" + mManufacturerId
-                + ", mManufacturerData=" + Arrays.toString(mManufacturerData)
-                + ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask) + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mDeviceName, mDeviceAddress, mManufacturerId,
-                Arrays.hashCode(mManufacturerData),
-                Arrays.hashCode(mManufacturerDataMask),
-                mServiceDataUuid,
-                Arrays.hashCode(mServiceData),
-                Arrays.hashCode(mServiceDataMask),
-                mServiceUuid, mServiceUuidMask,
-                mServiceSolicitationUuid, mServiceSolicitationUuidMask);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        ScanFilter other = (ScanFilter) obj;
-        return Objects.equals(mDeviceName, other.mDeviceName)
-                && Objects.equals(mDeviceAddress, other.mDeviceAddress)
-                && mManufacturerId == other.mManufacturerId
-                && Objects.deepEquals(mManufacturerData, other.mManufacturerData)
-                && Objects.deepEquals(mManufacturerDataMask, other.mManufacturerDataMask)
-                && Objects.equals(mServiceDataUuid, other.mServiceDataUuid)
-                && Objects.deepEquals(mServiceData, other.mServiceData)
-                && Objects.deepEquals(mServiceDataMask, other.mServiceDataMask)
-                && Objects.equals(mServiceUuid, other.mServiceUuid)
-                && Objects.equals(mServiceUuidMask, other.mServiceUuidMask)
-                && Objects.equals(mServiceSolicitationUuid, other.mServiceSolicitationUuid)
-                && Objects.equals(mServiceSolicitationUuidMask,
-                        other.mServiceSolicitationUuidMask);
-    }
-
-    /**
-     * Checks if the scanfilter is empty
-     *
-     * @hide
-     */
-    public boolean isAllFieldsEmpty() {
-        return EMPTY.equals(this);
-    }
-
-    /**
-     * Builder class for {@link ScanFilter}.
-     */
-    public static final class Builder {
-
-        /**
-         * @hide
-         */
-        @SystemApi
-        public static final int LEN_IRK_OCTETS = 16;
-
-        private String mDeviceName;
-        private String mDeviceAddress;
-        private @AddressType int mAddressType = BluetoothDevice.ADDRESS_TYPE_PUBLIC;
-        private byte[] mIrk;
-
-        private ParcelUuid mServiceUuid;
-        private ParcelUuid mUuidMask;
-
-        private ParcelUuid mServiceSolicitationUuid;
-        private ParcelUuid mServiceSolicitationUuidMask;
-
-        private ParcelUuid mServiceDataUuid;
-        private byte[] mServiceData;
-        private byte[] mServiceDataMask;
-
-        private int mManufacturerId = -1;
-        private byte[] mManufacturerData;
-        private byte[] mManufacturerDataMask;
-
-        /**
-         * Set filter on device name.
-         */
-        public Builder setDeviceName(String deviceName) {
-            mDeviceName = deviceName;
-            return this;
-        }
-
-        /**
-         * Set filter on device address.
-         *
-         * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
-         * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
-         * BluetoothAdapter#checkBluetoothAddress}.  The @AddressType is defaulted to {@link
-         * BluetoothDevice#ADDRESS_TYPE_PUBLIC}
-         * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
-         */
-        public Builder setDeviceAddress(String deviceAddress) {
-            if (deviceAddress == null) {
-                mDeviceAddress = deviceAddress;
-                return this;
-            }
-            return setDeviceAddress(deviceAddress, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
-        }
-
-        /**
-         * Set filter on Address with AddressType
-         *
-         * <p>This key is used to resolve a private address from a public address.
-         *
-         * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
-         * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
-         * BluetoothAdapter#checkBluetoothAddress}. May be any type of address.
-         * @param addressType indication of the type of address
-         * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
-         * or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM}
-         *
-         * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
-         * @throws IllegalArgumentException If the {@code addressType} is invalid length
-         * @throws NullPointerException if {@code deviceAddress} is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public Builder setDeviceAddress(@NonNull String deviceAddress,
-                                        @AddressType int addressType) {
-            return setDeviceAddressInternal(deviceAddress, addressType, null);
-        }
-
-        /**
-         * Set filter on Address with AddressType and the Identity Resolving Key (IRK).
-         *
-         * <p>The IRK is used to resolve a {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC} from
-         * a PRIVATE_ADDRESS type.
-         *
-         * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
-         * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
-         * BluetoothAdapter#checkBluetoothAddress}.  This Address type must only be PUBLIC OR RANDOM
-         * STATIC.
-         * @param addressType indication of the type of address
-         * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
-         * or {@link BluetoothDevice#ADDRESS_TYPE_RANDOM}
-         * @param irk non-null byte array representing the Identity Resolving Key
-         *
-         * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
-         * @throws IllegalArgumentException if the {@code irk} is invalid length.
-         * @throws IllegalArgumentException If the {@code addressType} is invalid length or is not
-         * PUBLIC or RANDOM STATIC when an IRK is present.
-         * @throws NullPointerException if {@code deviceAddress} or {@code irk} is null.
-         *
-         * @hide
-         */
-        @NonNull
-        @SystemApi
-        public Builder setDeviceAddress(@NonNull String deviceAddress,
-                                        @AddressType int addressType,
-                                        @NonNull byte[] irk) {
-            requireNonNull(irk);
-            if (irk.length != LEN_IRK_OCTETS) {
-                throw new IllegalArgumentException("'irk' is invalid length!");
-            }
-            return setDeviceAddressInternal(deviceAddress, addressType, irk);
-        }
-
-        /**
-         * Set filter on Address with AddressType and the Identity Resolving Key (IRK).
-         *
-         * <p>Internal setter for the device address
-         *
-         * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
-         * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link
-         * BluetoothAdapter#checkBluetoothAddress}.
-         * @param addressType indication of the type of address
-         * e.g. {@link BluetoothDevice#ADDRESS_TYPE_PUBLIC}
-         * @param irk non-null byte array representing the Identity Resolving Address; nullable
-         * internally.
-         *
-         * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
-         * @throws IllegalArgumentException If the {@code addressType} is invalid length.
-         * @throws NullPointerException if {@code deviceAddress} is null.
-         *
-         * @hide
-         */
-        @NonNull
-        private Builder setDeviceAddressInternal(@NonNull String deviceAddress,
-                                                 @AddressType int addressType,
-                                                 @Nullable byte[] irk) {
-
-            // Make sure our deviceAddress is valid!
-            requireNonNull(deviceAddress);
-            if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
-                throw new IllegalArgumentException("invalid device address " + deviceAddress);
-            }
-
-            // Verify type range
-            if (addressType < BluetoothDevice.ADDRESS_TYPE_PUBLIC
-                || addressType > BluetoothDevice.ADDRESS_TYPE_RANDOM) {
-                throw new IllegalArgumentException("'addressType' is invalid!");
-            }
-
-            // IRK can only be used for a PUBLIC or RANDOM (STATIC) Address.
-            if (addressType == BluetoothDevice.ADDRESS_TYPE_RANDOM) {
-                // Don't want a bad combination of address and irk!
-                if (irk != null) {
-                    // Since there are 3 possible RANDOM subtypes we must check to make sure
-                    // the correct type of address is used.
-                    if (!BluetoothAdapter.isAddressRandomStatic(deviceAddress)) {
-                        throw new IllegalArgumentException(
-                                "Invalid combination: IRK requires either a PUBLIC or "
-                                + "RANDOM (STATIC) Address");
-                    }
-                }
-            }
-
-            // PUBLIC doesn't require extra work
-            // Without an IRK any address may be accepted
-
-            mDeviceAddress = deviceAddress;
-            mAddressType = addressType;
-            mIrk = irk;
-            return this;
-        }
-
-        /**
-         * Set filter on service uuid.
-         */
-        public Builder setServiceUuid(ParcelUuid serviceUuid) {
-            mServiceUuid = serviceUuid;
-            mUuidMask = null; // clear uuid mask
-            return this;
-        }
-
-        /**
-         * Set filter on partial service uuid. The {@code uuidMask} is the bit mask for the
-         * {@code serviceUuid}. Set any bit in the mask to 1 to indicate a match is needed for the
-         * bit in {@code serviceUuid}, and 0 to ignore that bit.
-         *
-         * @throws IllegalArgumentException If {@code serviceUuid} is {@code null} but {@code
-         * uuidMask} is not {@code null}.
-         */
-        public Builder setServiceUuid(ParcelUuid serviceUuid, ParcelUuid uuidMask) {
-            if (mUuidMask != null && mServiceUuid == null) {
-                throw new IllegalArgumentException("uuid is null while uuidMask is not null!");
-            }
-            mServiceUuid = serviceUuid;
-            mUuidMask = uuidMask;
-            return this;
-        }
-
-
-        /**
-         * Set filter on service solicitation uuid.
-         */
-        public @NonNull Builder setServiceSolicitationUuid(
-                @Nullable ParcelUuid serviceSolicitationUuid) {
-            mServiceSolicitationUuid = serviceSolicitationUuid;
-            if (serviceSolicitationUuid == null) {
-                mServiceSolicitationUuidMask = null;
-            }
-            return this;
-        }
-
-
-        /**
-         * Set filter on partial service Solicitation uuid. The {@code SolicitationUuidMask} is the
-         * bit mask for the {@code serviceSolicitationUuid}. Set any bit in the mask to 1 to
-         * indicate a match is needed for the bit in {@code serviceSolicitationUuid}, and 0 to
-         * ignore that bit.
-         *
-         * @param serviceSolicitationUuid can only be null if solicitationUuidMask is null.
-         * @param solicitationUuidMask can be null or a mask with no restriction.
-         *
-         * @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but
-         *             {@code serviceSolicitationUuidMask} is not {@code null}.
-         */
-        public @NonNull Builder setServiceSolicitationUuid(
-                @Nullable ParcelUuid serviceSolicitationUuid,
-                @Nullable ParcelUuid solicitationUuidMask) {
-            if (solicitationUuidMask != null && serviceSolicitationUuid == null) {
-                throw new IllegalArgumentException(
-                        "SolicitationUuid is null while SolicitationUuidMask is not null!");
-            }
-            mServiceSolicitationUuid = serviceSolicitationUuid;
-            mServiceSolicitationUuidMask = solicitationUuidMask;
-            return this;
-        }
-
-        /**
-         * Set filtering on service data.
-         *
-         * @throws IllegalArgumentException If {@code serviceDataUuid} is null.
-         */
-        public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
-            if (serviceDataUuid == null) {
-                throw new IllegalArgumentException("serviceDataUuid is null");
-            }
-            mServiceDataUuid = serviceDataUuid;
-            mServiceData = serviceData;
-            mServiceDataMask = null; // clear service data mask
-            return this;
-        }
-
-        /**
-         * Set partial filter on service data. For any bit in the mask, set it to 1 if it needs to
-         * match the one in service data, otherwise set it to 0 to ignore that bit.
-         * <p>
-         * The {@code serviceDataMask} must have the same length of the {@code serviceData}.
-         *
-         * @throws IllegalArgumentException If {@code serviceDataUuid} is null or {@code
-         * serviceDataMask} is {@code null} while {@code serviceData} is not or {@code
-         * serviceDataMask} and {@code serviceData} has different length.
-         */
-        public Builder setServiceData(ParcelUuid serviceDataUuid,
-                byte[] serviceData, byte[] serviceDataMask) {
-            if (serviceDataUuid == null) {
-                throw new IllegalArgumentException("serviceDataUuid is null");
-            }
-            if (mServiceDataMask != null) {
-                if (mServiceData == null) {
-                    throw new IllegalArgumentException(
-                            "serviceData is null while serviceDataMask is not null");
-                }
-                // Since the mServiceDataMask is a bit mask for mServiceData, the lengths of the two
-                // byte array need to be the same.
-                if (mServiceData.length != mServiceDataMask.length) {
-                    throw new IllegalArgumentException(
-                            "size mismatch for service data and service data mask");
-                }
-            }
-            mServiceDataUuid = serviceDataUuid;
-            mServiceData = serviceData;
-            mServiceDataMask = serviceDataMask;
-            return this;
-        }
-
-        /**
-         * Set filter on on manufacturerData. A negative manufacturerId is considered as invalid id.
-         *
-         * @throws IllegalArgumentException If the {@code manufacturerId} is invalid.
-         */
-        public Builder setManufacturerData(int manufacturerId, byte[] manufacturerData) {
-            if (manufacturerData != null && manufacturerId < 0) {
-                throw new IllegalArgumentException("invalid manufacture id");
-            }
-            mManufacturerId = manufacturerId;
-            mManufacturerData = manufacturerData;
-            mManufacturerDataMask = null; // clear manufacturer data mask
-            return this;
-        }
-
-        /**
-         * Set filter on partial manufacture data. For any bit in the mask, set it the 1 if it needs
-         * to match the one in manufacturer data, otherwise set it to 0.
-         * <p>
-         * The {@code manufacturerDataMask} must have the same length of {@code manufacturerData}.
-         *
-         * @throws IllegalArgumentException If the {@code manufacturerId} is invalid, or {@code
-         * manufacturerData} is null while {@code manufacturerDataMask} is not, or {@code
-         * manufacturerData} and {@code manufacturerDataMask} have different length.
-         */
-        public Builder setManufacturerData(int manufacturerId, byte[] manufacturerData,
-                byte[] manufacturerDataMask) {
-            if (manufacturerData != null && manufacturerId < 0) {
-                throw new IllegalArgumentException("invalid manufacture id");
-            }
-            if (mManufacturerDataMask != null) {
-                if (mManufacturerData == null) {
-                    throw new IllegalArgumentException(
-                            "manufacturerData is null while manufacturerDataMask is not null");
-                }
-                // Since the mManufacturerDataMask is a bit mask for mManufacturerData, the lengths
-                // of the two byte array need to be the same.
-                if (mManufacturerData.length != mManufacturerDataMask.length) {
-                    throw new IllegalArgumentException(
-                            "size mismatch for manufacturerData and manufacturerDataMask");
-                }
-            }
-            mManufacturerId = manufacturerId;
-            mManufacturerData = manufacturerData;
-            mManufacturerDataMask = manufacturerDataMask;
-            return this;
-        }
-
-        /**
-         * Build {@link ScanFilter}.
-         *
-         * @throws IllegalArgumentException If the filter cannot be built.
-         */
-        public ScanFilter build() {
-            return new ScanFilter(mDeviceName, mDeviceAddress,
-                    mServiceUuid, mUuidMask, mServiceSolicitationUuid,
-                    mServiceSolicitationUuidMask,
-                    mServiceDataUuid, mServiceData, mServiceDataMask,
-                    mManufacturerId, mManufacturerData, mManufacturerDataMask,
-                    mAddressType, mIrk);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
deleted file mode 100644
index 9b8c2ea..0000000
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.bluetooth.BluetoothUuid;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.ParcelUuid;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Predicate;
-
-/**
- * Represents a scan record from Bluetooth LE scan.
- */
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class ScanRecord {
-
-    private static final String TAG = "ScanRecord";
-
-    // The following data type values are assigned by Bluetooth SIG.
-    // For more details refer to Bluetooth 4.1 specification, Volume 3, Part C, Section 18.
-    private static final int DATA_TYPE_FLAGS = 0x01;
-    private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02;
-    private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03;
-    private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04;
-    private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05;
-    private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06;
-    private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07;
-    private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
-    private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
-    private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
-    private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16;
-    private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20;
-    private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21;
-    private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14;
-    private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F;
-    private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15;
-    private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
-
-    // Flags of the advertising data.
-    private final int mAdvertiseFlags;
-
-    @Nullable
-    private final List<ParcelUuid> mServiceUuids;
-    @Nullable
-    private final List<ParcelUuid> mServiceSolicitationUuids;
-
-    private final SparseArray<byte[]> mManufacturerSpecificData;
-
-    private final Map<ParcelUuid, byte[]> mServiceData;
-
-    // Transmission power level(in dB).
-    private final int mTxPowerLevel;
-
-    // Local name of the Bluetooth LE device.
-    private final String mDeviceName;
-
-    // Raw bytes of scan record.
-    private final byte[] mBytes;
-
-    /**
-     * Returns the advertising flags indicating the discoverable mode and capability of the device.
-     * Returns -1 if the flag field is not set.
-     */
-    public int getAdvertiseFlags() {
-        return mAdvertiseFlags;
-    }
-
-    /**
-     * Returns a list of service UUIDs within the advertisement that are used to identify the
-     * bluetooth GATT services.
-     */
-    public List<ParcelUuid> getServiceUuids() {
-        return mServiceUuids;
-    }
-
-    /**
-     * Returns a list of service solicitation UUIDs within the advertisement that are used to
-     * identify the Bluetooth GATT services.
-     */
-    @NonNull
-    public List<ParcelUuid> getServiceSolicitationUuids() {
-        return mServiceSolicitationUuids;
-    }
-
-    /**
-     * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
-     * data.
-     */
-    public SparseArray<byte[]> getManufacturerSpecificData() {
-        return mManufacturerSpecificData;
-    }
-
-    /**
-     * Returns the manufacturer specific data associated with the manufacturer id. Returns
-     * {@code null} if the {@code manufacturerId} is not found.
-     */
-    @Nullable
-    public byte[] getManufacturerSpecificData(int manufacturerId) {
-        if (mManufacturerSpecificData == null) {
-            return null;
-        }
-        return mManufacturerSpecificData.get(manufacturerId);
-    }
-
-    /**
-     * Returns a map of service UUID and its corresponding service data.
-     */
-    public Map<ParcelUuid, byte[]> getServiceData() {
-        return mServiceData;
-    }
-
-    /**
-     * Returns the service data byte array associated with the {@code serviceUuid}. Returns
-     * {@code null} if the {@code serviceDataUuid} is not found.
-     */
-    @Nullable
-    public byte[] getServiceData(ParcelUuid serviceDataUuid) {
-        if (serviceDataUuid == null || mServiceData == null) {
-            return null;
-        }
-        return mServiceData.get(serviceDataUuid);
-    }
-
-    /**
-     * Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE}
-     * if the field is not set. This value can be used to calculate the path loss of a received
-     * packet using the following equation:
-     * <p>
-     * <code>pathloss = txPowerLevel - rssi</code>
-     */
-    public int getTxPowerLevel() {
-        return mTxPowerLevel;
-    }
-
-    /**
-     * Returns the local name of the BLE device. This is a UTF-8 encoded string.
-     */
-    @Nullable
-    public String getDeviceName() {
-        return mDeviceName;
-    }
-
-    /**
-     * Returns raw bytes of scan record.
-     */
-    public byte[] getBytes() {
-        return mBytes;
-    }
-
-    /**
-     * Test if any fields contained inside this scan record are matched by the
-     * given matcher.
-     *
-     * @hide
-     */
-    public boolean matchesAnyField(@NonNull Predicate<byte[]> matcher) {
-        int pos = 0;
-        while (pos < mBytes.length) {
-            final int length = mBytes[pos] & 0xFF;
-            if (length == 0) {
-                break;
-            }
-            if (matcher.test(Arrays.copyOfRange(mBytes, pos, pos + length + 1))) {
-                return true;
-            }
-            pos += length + 1;
-        }
-        return false;
-    }
-
-    private ScanRecord(List<ParcelUuid> serviceUuids,
-            List<ParcelUuid> serviceSolicitationUuids,
-            SparseArray<byte[]> manufacturerData,
-            Map<ParcelUuid, byte[]> serviceData,
-            int advertiseFlags, int txPowerLevel,
-            String localName, byte[] bytes) {
-        mServiceSolicitationUuids = serviceSolicitationUuids;
-        mServiceUuids = serviceUuids;
-        mManufacturerSpecificData = manufacturerData;
-        mServiceData = serviceData;
-        mDeviceName = localName;
-        mAdvertiseFlags = advertiseFlags;
-        mTxPowerLevel = txPowerLevel;
-        mBytes = bytes;
-    }
-
-    /**
-     * Parse scan record bytes to {@link ScanRecord}.
-     * <p>
-     * The format is defined in Bluetooth 4.1 specification, Volume 3, Part C, Section 11 and 18.
-     * <p>
-     * All numerical multi-byte entities and values shall use little-endian <strong>byte</strong>
-     * order.
-     *
-     * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static ScanRecord parseFromBytes(byte[] scanRecord) {
-        if (scanRecord == null) {
-            return null;
-        }
-
-        int currentPos = 0;
-        int advertiseFlag = -1;
-        List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
-        List<ParcelUuid> serviceSolicitationUuids = new ArrayList<ParcelUuid>();
-        String localName = null;
-        int txPowerLevel = Integer.MIN_VALUE;
-
-        SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>();
-        Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>();
-
-        try {
-            while (currentPos < scanRecord.length) {
-                // length is unsigned int.
-                int length = scanRecord[currentPos++] & 0xFF;
-                if (length == 0) {
-                    break;
-                }
-                // Note the length includes the length of the field type itself.
-                int dataLength = length - 1;
-                // fieldType is unsigned int.
-                int fieldType = scanRecord[currentPos++] & 0xFF;
-                switch (fieldType) {
-                    case DATA_TYPE_FLAGS:
-                        advertiseFlag = scanRecord[currentPos] & 0xFF;
-                        break;
-                    case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL:
-                    case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
-                        parseServiceUuid(scanRecord, currentPos,
-                                dataLength, BluetoothUuid.UUID_BYTES_16_BIT, serviceUuids);
-                        break;
-                    case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
-                    case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
-                        parseServiceUuid(scanRecord, currentPos, dataLength,
-                                BluetoothUuid.UUID_BYTES_32_BIT, serviceUuids);
-                        break;
-                    case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
-                    case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
-                        parseServiceUuid(scanRecord, currentPos, dataLength,
-                                BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids);
-                        break;
-                    case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT:
-                        parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
-                                BluetoothUuid.UUID_BYTES_16_BIT, serviceSolicitationUuids);
-                        break;
-                    case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT:
-                        parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
-                                BluetoothUuid.UUID_BYTES_32_BIT, serviceSolicitationUuids);
-                        break;
-                    case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT:
-                        parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
-                                BluetoothUuid.UUID_BYTES_128_BIT, serviceSolicitationUuids);
-                        break;
-                    case DATA_TYPE_LOCAL_NAME_SHORT:
-                    case DATA_TYPE_LOCAL_NAME_COMPLETE:
-                        localName = new String(
-                                extractBytes(scanRecord, currentPos, dataLength));
-                        break;
-                    case DATA_TYPE_TX_POWER_LEVEL:
-                        txPowerLevel = scanRecord[currentPos];
-                        break;
-                    case DATA_TYPE_SERVICE_DATA_16_BIT:
-                    case DATA_TYPE_SERVICE_DATA_32_BIT:
-                    case DATA_TYPE_SERVICE_DATA_128_BIT:
-                        int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
-                        if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) {
-                            serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT;
-                        } else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) {
-                            serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT;
-                        }
-
-                        byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
-                                serviceUuidLength);
-                        ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
-                                serviceDataUuidBytes);
-                        byte[] serviceDataArray = extractBytes(scanRecord,
-                                currentPos + serviceUuidLength, dataLength - serviceUuidLength);
-                        serviceData.put(serviceDataUuid, serviceDataArray);
-                        break;
-                    case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
-                        // The first two bytes of the manufacturer specific data are
-                        // manufacturer ids in little endian.
-                        int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8)
-                                + (scanRecord[currentPos] & 0xFF);
-                        byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
-                                dataLength - 2);
-                        manufacturerData.put(manufacturerId, manufacturerDataBytes);
-                        break;
-                    default:
-                        // Just ignore, we don't handle such data type.
-                        break;
-                }
-                currentPos += dataLength;
-            }
-
-            if (serviceUuids.isEmpty()) {
-                serviceUuids = null;
-            }
-            return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData,
-                    serviceData, advertiseFlag, txPowerLevel, localName, scanRecord);
-        } catch (Exception e) {
-            Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
-            // As the record is invalid, ignore all the parsed results for this packet
-            // and return an empty record with raw scanRecord bytes in results
-            return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, scanRecord);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
-                + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids
-                + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(
-                mManufacturerSpecificData)
-                + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData)
-                + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]";
-    }
-
-    // Parse service UUIDs.
-    private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength,
-            int uuidLength, List<ParcelUuid> serviceUuids) {
-        while (dataLength > 0) {
-            byte[] uuidBytes = extractBytes(scanRecord, currentPos,
-                    uuidLength);
-            serviceUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes));
-            dataLength -= uuidLength;
-            currentPos += uuidLength;
-        }
-        return currentPos;
-    }
-
-    /**
-     * Parse service Solicitation UUIDs.
-     */
-    private static int parseServiceSolicitationUuid(byte[] scanRecord, int currentPos,
-            int dataLength, int uuidLength, List<ParcelUuid> serviceSolicitationUuids) {
-        while (dataLength > 0) {
-            byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength);
-            serviceSolicitationUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes));
-            dataLength -= uuidLength;
-            currentPos += uuidLength;
-        }
-        return currentPos;
-    }
-
-    // Helper method to extract bytes from byte array.
-    private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
-        byte[] bytes = new byte[length];
-        System.arraycopy(scanRecord, start, bytes, 0, length);
-        return bytes;
-    }
-}
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
deleted file mode 100644
index f437d86..0000000
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.bluetooth.Attributable;
-import android.bluetooth.BluetoothDevice;
-import android.content.AttributionSource;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * ScanResult for Bluetooth LE scan.
- */
-public final class ScanResult implements Parcelable, Attributable {
-
-    /**
-     * For chained advertisements, inidcates tha the data contained in this
-     * scan result is complete.
-     */
-    public static final int DATA_COMPLETE = 0x00;
-
-    /**
-     * For chained advertisements, indicates that the controller was
-     * unable to receive all chained packets and the scan result contains
-     * incomplete truncated data.
-     */
-    public static final int DATA_TRUNCATED = 0x02;
-
-    /**
-     * Indicates that the secondary physical layer was not used.
-     */
-    public static final int PHY_UNUSED = 0x00;
-
-    /**
-     * Advertising Set ID is not present in the packet.
-     */
-    public static final int SID_NOT_PRESENT = 0xFF;
-
-    /**
-     * TX power is not present in the packet.
-     */
-    public static final int TX_POWER_NOT_PRESENT = 0x7F;
-
-    /**
-     * Periodic advertising interval is not present in the packet.
-     */
-    public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0x00;
-
-    /**
-     * Mask for checking whether event type represents legacy advertisement.
-     */
-    private static final int ET_LEGACY_MASK = 0x10;
-
-    /**
-     * Mask for checking whether event type represents connectable advertisement.
-     */
-    private static final int ET_CONNECTABLE_MASK = 0x01;
-
-    // Remote Bluetooth device.
-    private BluetoothDevice mDevice;
-
-    // Scan record, including advertising data and scan response data.
-    @Nullable
-    private ScanRecord mScanRecord;
-
-    // Received signal strength.
-    private int mRssi;
-
-    // Device timestamp when the result was last seen.
-    private long mTimestampNanos;
-
-    private int mEventType;
-    private int mPrimaryPhy;
-    private int mSecondaryPhy;
-    private int mAdvertisingSid;
-    private int mTxPower;
-    private int mPeriodicAdvertisingInterval;
-
-    /**
-     * Constructs a new ScanResult.
-     *
-     * @param device Remote Bluetooth device found.
-     * @param scanRecord Scan record including both advertising data and scan response data.
-     * @param rssi Received signal strength.
-     * @param timestampNanos Timestamp at which the scan result was observed.
-     * @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int,
-     * ScanRecord, long)}
-     */
-    @Deprecated
-    public ScanResult(BluetoothDevice device, ScanRecord scanRecord, int rssi,
-            long timestampNanos) {
-        mDevice = device;
-        mScanRecord = scanRecord;
-        mRssi = rssi;
-        mTimestampNanos = timestampNanos;
-        mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK;
-        mPrimaryPhy = BluetoothDevice.PHY_LE_1M;
-        mSecondaryPhy = PHY_UNUSED;
-        mAdvertisingSid = SID_NOT_PRESENT;
-        mTxPower = 127;
-        mPeriodicAdvertisingInterval = 0;
-    }
-
-    /**
-     * Constructs a new ScanResult.
-     *
-     * @param device Remote Bluetooth device found.
-     * @param eventType Event type.
-     * @param primaryPhy Primary advertising phy.
-     * @param secondaryPhy Secondary advertising phy.
-     * @param advertisingSid Advertising set ID.
-     * @param txPower Transmit power.
-     * @param rssi Received signal strength.
-     * @param periodicAdvertisingInterval Periodic advertising interval.
-     * @param scanRecord Scan record including both advertising data and scan response data.
-     * @param timestampNanos Timestamp at which the scan result was observed.
-     */
-    public ScanResult(BluetoothDevice device, int eventType, int primaryPhy, int secondaryPhy,
-            int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval,
-            ScanRecord scanRecord, long timestampNanos) {
-        mDevice = device;
-        mEventType = eventType;
-        mPrimaryPhy = primaryPhy;
-        mSecondaryPhy = secondaryPhy;
-        mAdvertisingSid = advertisingSid;
-        mTxPower = txPower;
-        mRssi = rssi;
-        mPeriodicAdvertisingInterval = periodicAdvertisingInterval;
-        mScanRecord = scanRecord;
-        mTimestampNanos = timestampNanos;
-    }
-
-    private ScanResult(Parcel in) {
-        readFromParcel(in);
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        if (mDevice != null) {
-            dest.writeInt(1);
-            mDevice.writeToParcel(dest, flags);
-        } else {
-            dest.writeInt(0);
-        }
-        if (mScanRecord != null) {
-            dest.writeInt(1);
-            dest.writeByteArray(mScanRecord.getBytes());
-        } else {
-            dest.writeInt(0);
-        }
-        dest.writeInt(mRssi);
-        dest.writeLong(mTimestampNanos);
-        dest.writeInt(mEventType);
-        dest.writeInt(mPrimaryPhy);
-        dest.writeInt(mSecondaryPhy);
-        dest.writeInt(mAdvertisingSid);
-        dest.writeInt(mTxPower);
-        dest.writeInt(mPeriodicAdvertisingInterval);
-    }
-
-    private void readFromParcel(Parcel in) {
-        if (in.readInt() == 1) {
-            mDevice = BluetoothDevice.CREATOR.createFromParcel(in);
-        }
-        if (in.readInt() == 1) {
-            mScanRecord = ScanRecord.parseFromBytes(in.createByteArray());
-        }
-        mRssi = in.readInt();
-        mTimestampNanos = in.readLong();
-        mEventType = in.readInt();
-        mPrimaryPhy = in.readInt();
-        mSecondaryPhy = in.readInt();
-        mAdvertisingSid = in.readInt();
-        mTxPower = in.readInt();
-        mPeriodicAdvertisingInterval = in.readInt();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** {@hide} */
-    public void setAttributionSource(@NonNull AttributionSource attributionSource) {
-        Attributable.setAttributionSource(mDevice, attributionSource);
-    }
-
-    /**
-     * Returns the remote Bluetooth device identified by the Bluetooth device address.
-     */
-    public BluetoothDevice getDevice() {
-        return mDevice;
-    }
-
-    /**
-     * Returns the scan record, which is a combination of advertisement and scan response.
-     */
-    @Nullable
-    public ScanRecord getScanRecord() {
-        return mScanRecord;
-    }
-
-    /**
-     * Returns the received signal strength in dBm. The valid range is [-127, 126].
-     */
-    public int getRssi() {
-        return mRssi;
-    }
-
-    /**
-     * Returns timestamp since boot when the scan record was observed.
-     */
-    public long getTimestampNanos() {
-        return mTimestampNanos;
-    }
-
-    /**
-     * Returns true if this object represents legacy scan result.
-     * Legacy scan results do not contain advanced advertising information
-     * as specified in the Bluetooth Core Specification v5.
-     */
-    public boolean isLegacy() {
-        return (mEventType & ET_LEGACY_MASK) != 0;
-    }
-
-    /**
-     * Returns true if this object represents connectable scan result.
-     */
-    public boolean isConnectable() {
-        return (mEventType & ET_CONNECTABLE_MASK) != 0;
-    }
-
-    /**
-     * Returns the data status.
-     * Can be one of {@link ScanResult#DATA_COMPLETE} or
-     * {@link ScanResult#DATA_TRUNCATED}.
-     */
-    public int getDataStatus() {
-        // return bit 5 and 6
-        return (mEventType >> 5) & 0x03;
-    }
-
-    /**
-     * Returns the primary Physical Layer
-     * on which this advertisment was received.
-     * Can be one of {@link BluetoothDevice#PHY_LE_1M} or
-     * {@link BluetoothDevice#PHY_LE_CODED}.
-     */
-    public int getPrimaryPhy() {
-        return mPrimaryPhy;
-    }
-
-    /**
-     * Returns the secondary Physical Layer
-     * on which this advertisment was received.
-     * Can be one of {@link BluetoothDevice#PHY_LE_1M},
-     * {@link BluetoothDevice#PHY_LE_2M}, {@link BluetoothDevice#PHY_LE_CODED}
-     * or {@link ScanResult#PHY_UNUSED} - if the advertisement
-     * was not received on a secondary physical channel.
-     */
-    public int getSecondaryPhy() {
-        return mSecondaryPhy;
-    }
-
-    /**
-     * Returns the advertising set id.
-     * May return {@link ScanResult#SID_NOT_PRESENT} if
-     * no set id was is present.
-     */
-    public int getAdvertisingSid() {
-        return mAdvertisingSid;
-    }
-
-    /**
-     * Returns the transmit power in dBm.
-     * Valid range is [-127, 126]. A value of {@link ScanResult#TX_POWER_NOT_PRESENT}
-     * indicates that the TX power is not present.
-     */
-    public int getTxPower() {
-        return mTxPower;
-    }
-
-    /**
-     * Returns the periodic advertising interval in units of 1.25ms.
-     * Valid range is 6 (7.5ms) to 65536 (81918.75ms). A value of
-     * {@link ScanResult#PERIODIC_INTERVAL_NOT_PRESENT} means periodic
-     * advertising interval is not present.
-     */
-    public int getPeriodicAdvertisingInterval() {
-        return mPeriodicAdvertisingInterval;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos,
-                mEventType, mPrimaryPhy, mSecondaryPhy,
-                mAdvertisingSid, mTxPower,
-                mPeriodicAdvertisingInterval);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        ScanResult other = (ScanResult) obj;
-        return Objects.equals(mDevice, other.mDevice) && (mRssi == other.mRssi)
-                && Objects.equals(mScanRecord, other.mScanRecord)
-                && (mTimestampNanos == other.mTimestampNanos)
-                && mEventType == other.mEventType
-                && mPrimaryPhy == other.mPrimaryPhy
-                && mSecondaryPhy == other.mSecondaryPhy
-                && mAdvertisingSid == other.mAdvertisingSid
-                && mTxPower == other.mTxPower
-                && mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval;
-    }
-
-    @Override
-    public String toString() {
-        return "ScanResult{" + "device=" + mDevice + ", scanRecord="
-                + Objects.toString(mScanRecord) + ", rssi=" + mRssi
-                + ", timestampNanos=" + mTimestampNanos + ", eventType=" + mEventType
-                + ", primaryPhy=" + mPrimaryPhy + ", secondaryPhy=" + mSecondaryPhy
-                + ", advertisingSid=" + mAdvertisingSid + ", txPower=" + mTxPower
-                + ", periodicAdvertisingInterval=" + mPeriodicAdvertisingInterval + '}';
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<ScanResult> CREATOR = new Creator<ScanResult>() {
-        @Override
-        public ScanResult createFromParcel(Parcel source) {
-            return new ScanResult(source);
-        }
-
-        @Override
-        public ScanResult[] newArray(int size) {
-            return new ScanResult[size];
-        }
-    };
-
-}
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
deleted file mode 100644
index 1aa7cb5..0000000
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.SystemApi;
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Bluetooth LE scan settings are passed to {@link BluetoothLeScanner#startScan} to define the
- * parameters for the scan.
- */
-public final class ScanSettings implements Parcelable {
-
-    /**
-     * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for
-     * other scan results without starting BLE scans themselves.
-     */
-    public static final int SCAN_MODE_OPPORTUNISTIC = -1;
-
-    /**
-     * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
-     * least power. This mode is enforced if the scanning application is not in foreground.
-     */
-    public static final int SCAN_MODE_LOW_POWER = 0;
-
-    /**
-     * Perform Bluetooth LE scan in balanced power mode. Scan results are returned at a rate that
-     * provides a good trade-off between scan frequency and power consumption.
-     */
-    public static final int SCAN_MODE_BALANCED = 1;
-
-    /**
-     * Scan using highest duty cycle. It's recommended to only use this mode when the application is
-     * running in the foreground.
-     */
-    public static final int SCAN_MODE_LOW_LATENCY = 2;
-
-    /**
-     * Perform Bluetooth LE scan in ambient discovery mode. This mode has lower duty cycle and more
-     * aggressive scan interval than balanced mode that provides a good trade-off between scan
-     * latency and power consumption.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3;
-
-    /**
-     * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria.
-     * If no filter is active, all advertisement packets are reported.
-     */
-    public static final int CALLBACK_TYPE_ALL_MATCHES = 1;
-
-    /**
-     * A result callback is only triggered for the first advertisement packet received that matches
-     * the filter criteria.
-     */
-    public static final int CALLBACK_TYPE_FIRST_MATCH = 2;
-
-    /**
-     * Receive a callback when advertisements are no longer received from a device that has been
-     * previously reported by a first match callback.
-     */
-    public static final int CALLBACK_TYPE_MATCH_LOST = 4;
-
-
-    /**
-     * Determines how many advertisements to match per filter, as this is scarce hw resource
-     */
-    /**
-     * Match one advertisement per filter
-     */
-    public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1;
-
-    /**
-     * Match few advertisement per filter, depends on current capability and availibility of
-     * the resources in hw
-     */
-    public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2;
-
-    /**
-     * Match as many advertisement per filter as hw could allow, depends on current
-     * capability and availibility of the resources in hw
-     */
-    public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3;
-
-
-    /**
-     * In Aggressive mode, hw will determine a match sooner even with feeble signal strength
-     * and few number of sightings/match in a duration.
-     */
-    public static final int MATCH_MODE_AGGRESSIVE = 1;
-
-    /**
-     * For sticky mode, higher threshold of signal strength and sightings is required
-     * before reporting by hw
-     */
-    public static final int MATCH_MODE_STICKY = 2;
-
-    /**
-     * Request full scan results which contain the device, rssi, advertising data, scan response
-     * as well as the scan timestamp.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int SCAN_RESULT_TYPE_FULL = 0;
-
-    /**
-     * Request abbreviated scan results which contain the device, rssi and scan timestamp.
-     * <p>
-     * <b>Note:</b> It is possible for an application to get more scan results than it asked for, if
-     * there are multiple apps using this type.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
-
-    /**
-     * Use all supported PHYs for scanning.
-     * This will check the controller capabilities, and start
-     * the scan on 1Mbit and LE Coded PHYs if supported, or on
-     * the 1Mbit PHY only.
-     */
-    public static final int PHY_LE_ALL_SUPPORTED = 255;
-
-    // Bluetooth LE scan mode.
-    private int mScanMode;
-
-    // Bluetooth LE scan callback type
-    private int mCallbackType;
-
-    // Bluetooth LE scan result type
-    private int mScanResultType;
-
-    // Time of delay for reporting the scan result
-    private long mReportDelayMillis;
-
-    private int mMatchMode;
-
-    private int mNumOfMatchesPerFilter;
-
-    // Include only legacy advertising results
-    private boolean mLegacy;
-
-    private int mPhy;
-
-    public int getScanMode() {
-        return mScanMode;
-    }
-
-    public int getCallbackType() {
-        return mCallbackType;
-    }
-
-    public int getScanResultType() {
-        return mScanResultType;
-    }
-
-    /**
-     * @hide
-     */
-    public int getMatchMode() {
-        return mMatchMode;
-    }
-
-    /**
-     * @hide
-     */
-    public int getNumOfMatches() {
-        return mNumOfMatchesPerFilter;
-    }
-
-    /**
-     * Returns whether only legacy advertisements will be returned.
-     * Legacy advertisements include advertisements as specified
-     * by the Bluetooth core specification 4.2 and below.
-     */
-    public boolean getLegacy() {
-        return mLegacy;
-    }
-
-    /**
-     * Returns the physical layer used during a scan.
-     */
-    public int getPhy() {
-        return mPhy;
-    }
-
-    /**
-     * Returns report delay timestamp based on the device clock.
-     */
-    public long getReportDelayMillis() {
-        return mReportDelayMillis;
-    }
-
-    private ScanSettings(int scanMode, int callbackType, int scanResultType,
-            long reportDelayMillis, int matchMode,
-            int numOfMatchesPerFilter, boolean legacy, int phy) {
-        mScanMode = scanMode;
-        mCallbackType = callbackType;
-        mScanResultType = scanResultType;
-        mReportDelayMillis = reportDelayMillis;
-        mNumOfMatchesPerFilter = numOfMatchesPerFilter;
-        mMatchMode = matchMode;
-        mLegacy = legacy;
-        mPhy = phy;
-    }
-
-    private ScanSettings(Parcel in) {
-        mScanMode = in.readInt();
-        mCallbackType = in.readInt();
-        mScanResultType = in.readInt();
-        mReportDelayMillis = in.readLong();
-        mMatchMode = in.readInt();
-        mNumOfMatchesPerFilter = in.readInt();
-        mLegacy = in.readInt() != 0;
-        mPhy = in.readInt();
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mScanMode);
-        dest.writeInt(mCallbackType);
-        dest.writeInt(mScanResultType);
-        dest.writeLong(mReportDelayMillis);
-        dest.writeInt(mMatchMode);
-        dest.writeInt(mNumOfMatchesPerFilter);
-        dest.writeInt(mLegacy ? 1 : 0);
-        dest.writeInt(mPhy);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<ScanSettings> CREATOR =
-            new Creator<ScanSettings>() {
-        @Override
-        public ScanSettings[] newArray(int size) {
-            return new ScanSettings[size];
-        }
-
-        @Override
-        public ScanSettings createFromParcel(Parcel in) {
-            return new ScanSettings(in);
-        }
-    };
-
-    /**
-     * Builder for {@link ScanSettings}.
-     */
-    public static final class Builder {
-        private int mScanMode = SCAN_MODE_LOW_POWER;
-        private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
-        private int mScanResultType = SCAN_RESULT_TYPE_FULL;
-        private long mReportDelayMillis = 0;
-        private int mMatchMode = MATCH_MODE_AGGRESSIVE;
-        private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT;
-        private boolean mLegacy = true;
-        private int mPhy = PHY_LE_ALL_SUPPORTED;
-
-        /**
-         * Set scan mode for Bluetooth LE scan.
-         *
-         * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER},
-         * {@link ScanSettings#SCAN_MODE_BALANCED} or {@link ScanSettings#SCAN_MODE_LOW_LATENCY}.
-         * @throws IllegalArgumentException If the {@code scanMode} is invalid.
-         */
-        public Builder setScanMode(int scanMode) {
-            switch (scanMode) {
-                case SCAN_MODE_OPPORTUNISTIC:
-                case SCAN_MODE_LOW_POWER:
-                case SCAN_MODE_BALANCED:
-                case SCAN_MODE_LOW_LATENCY:
-                case SCAN_MODE_AMBIENT_DISCOVERY:
-                    mScanMode = scanMode;
-                    break;
-                default:
-                    throw new IllegalArgumentException("invalid scan mode " + scanMode);
-            }
-            return this;
-        }
-
-        /**
-         * Set callback type for Bluetooth LE scan.
-         *
-         * @param callbackType The callback type flags for the scan.
-         * @throws IllegalArgumentException If the {@code callbackType} is invalid.
-         */
-        public Builder setCallbackType(int callbackType) {
-
-            if (!isValidCallbackType(callbackType)) {
-                throw new IllegalArgumentException("invalid callback type - " + callbackType);
-            }
-            mCallbackType = callbackType;
-            return this;
-        }
-
-        // Returns true if the callbackType is valid.
-        private boolean isValidCallbackType(int callbackType) {
-            if (callbackType == CALLBACK_TYPE_ALL_MATCHES
-                    || callbackType == CALLBACK_TYPE_FIRST_MATCH
-                    || callbackType == CALLBACK_TYPE_MATCH_LOST) {
-                return true;
-            }
-            return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST);
-        }
-
-        /**
-         * Set scan result type for Bluetooth LE scan.
-         *
-         * @param scanResultType Type for scan result, could be either {@link
-         * ScanSettings#SCAN_RESULT_TYPE_FULL} or {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}.
-         * @throws IllegalArgumentException If the {@code scanResultType} is invalid.
-         * @hide
-         */
-        @SystemApi
-        public Builder setScanResultType(int scanResultType) {
-            if (scanResultType < SCAN_RESULT_TYPE_FULL
-                    || scanResultType > SCAN_RESULT_TYPE_ABBREVIATED) {
-                throw new IllegalArgumentException(
-                        "invalid scanResultType - " + scanResultType);
-            }
-            mScanResultType = scanResultType;
-            return this;
-        }
-
-        /**
-         * Set report delay timestamp for Bluetooth LE scan. If set to 0, you will be notified of
-         * scan results immediately. If &gt; 0, scan results are queued up and delivered after the
-         * requested delay or 5000 milliseconds (whichever is higher). Note scan results may be
-         * delivered sooner if the internal buffers fill up.
-         *
-         * @param reportDelayMillis         how frequently scan results should be delivered in
-         *                                  milliseconds
-         * @throws IllegalArgumentException if {@code reportDelayMillis} &lt; 0
-         */
-        public Builder setReportDelay(long reportDelayMillis) {
-            if (reportDelayMillis < 0) {
-                throw new IllegalArgumentException("reportDelay must be > 0");
-            }
-            mReportDelayMillis = reportDelayMillis;
-            return this;
-        }
-
-        /**
-         * Set the number of matches for Bluetooth LE scan filters hardware match
-         *
-         * @param numOfMatches The num of matches can be one of
-         * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT}
-         * or {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or {@link
-         * ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT}
-         * @throws IllegalArgumentException If the {@code matchMode} is invalid.
-         */
-        public Builder setNumOfMatches(int numOfMatches) {
-            if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT
-                    || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) {
-                throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches);
-            }
-            mNumOfMatchesPerFilter = numOfMatches;
-            return this;
-        }
-
-        /**
-         * Set match mode for Bluetooth LE scan filters hardware match
-         *
-         * @param matchMode The match mode can be one of {@link ScanSettings#MATCH_MODE_AGGRESSIVE}
-         * or {@link ScanSettings#MATCH_MODE_STICKY}
-         * @throws IllegalArgumentException If the {@code matchMode} is invalid.
-         */
-        public Builder setMatchMode(int matchMode) {
-            if (matchMode < MATCH_MODE_AGGRESSIVE
-                    || matchMode > MATCH_MODE_STICKY) {
-                throw new IllegalArgumentException("invalid matchMode " + matchMode);
-            }
-            mMatchMode = matchMode;
-            return this;
-        }
-
-        /**
-         * Set whether only legacy advertisments should be returned in scan results.
-         * Legacy advertisements include advertisements as specified by the
-         * Bluetooth core specification 4.2 and below. This is true by default
-         * for compatibility with older apps.
-         *
-         * @param legacy true if only legacy advertisements will be returned
-         */
-        public Builder setLegacy(boolean legacy) {
-            mLegacy = legacy;
-            return this;
-        }
-
-        /**
-         * Set the Physical Layer to use during this scan.
-         * This is used only if {@link ScanSettings.Builder#setLegacy}
-         * is set to false.
-         * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}
-         * may be used to check whether LE Coded phy is supported by calling
-         * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}.
-         * Selecting an unsupported phy will result in failure to start scan.
-         *
-         * @param phy Can be one of {@link BluetoothDevice#PHY_LE_1M}, {@link
-         * BluetoothDevice#PHY_LE_CODED} or {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
-         */
-        public Builder setPhy(int phy) {
-            mPhy = phy;
-            return this;
-        }
-
-        /**
-         * Build {@link ScanSettings}.
-         */
-        public ScanSettings build() {
-            return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
-                    mReportDelayMillis, mMatchMode,
-                    mNumOfMatchesPerFilter, mLegacy, mPhy);
-        }
-    }
-}
diff --git a/core/java/android/bluetooth/le/TransportBlock.java b/core/java/android/bluetooth/le/TransportBlock.java
deleted file mode 100644
index 18bad9c..0000000
--- a/core/java/android/bluetooth/le/TransportBlock.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-/**
- * Wrapper for Transport Discovery Data Transport Blocks.
- * This class represents a Transport Block from a Transport Discovery Data.
- *
- * @see TransportDiscoveryData
- * @see AdvertiseData
- */
-public final class TransportBlock implements Parcelable {
-    private static final String TAG = "TransportBlock";
-    private final int mOrgId;
-    private final int mTdsFlags;
-    private final int mTransportDataLength;
-    private final byte[] mTransportData;
-
-    /**
-     * Creates an instance of TransportBlock from raw data.
-     *
-     * @param orgId the Organization ID
-     * @param tdsFlags the TDS flags
-     * @param transportDataLength the total length of the Transport Data
-     * @param transportData the Transport Data
-     */
-    public TransportBlock(int orgId, int tdsFlags, int transportDataLength,
-            @Nullable byte[] transportData) {
-        mOrgId = orgId;
-        mTdsFlags = tdsFlags;
-        mTransportDataLength = transportDataLength;
-        mTransportData = transportData;
-    }
-
-    private TransportBlock(Parcel in) {
-        mOrgId = in.readInt();
-        mTdsFlags = in.readInt();
-        mTransportDataLength = in.readInt();
-        if (mTransportDataLength > 0) {
-            mTransportData = new byte[mTransportDataLength];
-            in.readByteArray(mTransportData);
-        } else {
-            mTransportData = null;
-        }
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mOrgId);
-        dest.writeInt(mTdsFlags);
-        dest.writeInt(mTransportDataLength);
-        if (mTransportData != null) {
-            dest.writeByteArray(mTransportData);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        TransportBlock other = (TransportBlock) obj;
-        return Arrays.equals(toByteArray(), other.toByteArray());
-    }
-
-    public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() {
-        @Override
-        public TransportBlock createFromParcel(Parcel in) {
-            return new TransportBlock(in);
-        }
-
-        @Override
-        public TransportBlock[] newArray(int size) {
-            return new TransportBlock[size];
-        }
-    };
-
-    /**
-     * Gets the Organization ID of the Transport Block which corresponds to one of the
-     * the Bluetooth SIG Assigned Numbers.
-     */
-    public int getOrgId() {
-        return mOrgId;
-    }
-
-    /**
-     * Gets the TDS flags of the Transport Block which represents the role of the device and
-     * information about its state and supported features.
-     */
-    public int getTdsFlags() {
-        return mTdsFlags;
-    }
-
-    /**
-     * Gets the total number of octets in the Transport Data field in this Transport Block.
-     */
-    public int getTransportDataLength() {
-        return mTransportDataLength;
-    }
-
-    /**
-     * Gets the Transport Data of the Transport Block which contains organization-specific data.
-     */
-    @Nullable
-    public byte[] getTransportData() {
-        return mTransportData;
-    }
-
-    /**
-     * Converts this TransportBlock to byte array
-     *
-     * @return byte array representation of this Transport Block or null if the conversion failed
-     */
-    @Nullable
-    public byte[] toByteArray() {
-        try {
-            ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
-            buffer.put((byte) mOrgId);
-            buffer.put((byte) mTdsFlags);
-            buffer.put((byte) mTransportDataLength);
-            if (mTransportData != null) {
-                buffer.put(mTransportData);
-            }
-            return buffer.array();
-        } catch (BufferOverflowException e) {
-            Log.e(TAG, "Error converting to byte array: " + e.toString());
-            return null;
-        }
-    }
-
-    /**
-     * @return total byte count of this TransportBlock
-     */
-    public int totalBytes() {
-        // 3 uint8 + byte[] length
-        int size = 3 + mTransportDataLength;
-        return size;
-    }
-}
diff --git a/core/java/android/bluetooth/le/TransportDiscoveryData.java b/core/java/android/bluetooth/le/TransportDiscoveryData.java
deleted file mode 100644
index 2b52f19..0000000
--- a/core/java/android/bluetooth/le/TransportDiscoveryData.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Wrapper for Transport Discovery Data AD Type.
- * This class contains the Transport Discovery Data AD Type Code as well as
- * a list of potential Transport Blocks.
- *
- * @see AdvertiseData
- */
-public final class TransportDiscoveryData implements Parcelable {
-    private static final String TAG = "TransportDiscoveryData";
-    private final int mTransportDataType;
-    private final List<TransportBlock> mTransportBlocks;
-
-    /**
-     * Creates a TransportDiscoveryData instance.
-     *
-     * @param transportDataType the Transport Discovery Data AD Type
-     * @param transportBlocks the list of Transport Blocks
-     */
-    public TransportDiscoveryData(int transportDataType,
-            @NonNull List<TransportBlock> transportBlocks) {
-        mTransportDataType = transportDataType;
-        mTransportBlocks = transportBlocks;
-    }
-
-    /**
-     * Creates a TransportDiscoveryData instance from byte arrays.
-     *
-     * Uses the transport discovery data bytes and parses them into an usable class.
-     *
-     * @param transportDiscoveryData the raw discovery data
-     */
-    public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) {
-        ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData);
-        mTransportBlocks = new ArrayList();
-        if (byteBuffer.remaining() > 0) {
-            mTransportDataType = byteBuffer.get();
-        } else {
-            mTransportDataType = -1;
-        }
-        try {
-            while (byteBuffer.remaining() > 0) {
-                int orgId = byteBuffer.get();
-                int tdsFlags = byteBuffer.get();
-                int transportDataLength = byteBuffer.get();
-                byte[] transportData = new byte[transportDataLength];
-                byteBuffer.get(transportData, 0, transportDataLength);
-                mTransportBlocks.add(new TransportBlock(orgId, tdsFlags,
-                        transportDataLength, transportData));
-            }
-        } catch (BufferUnderflowException e) {
-            Log.e(TAG, "Error while parsing data: " + e.toString());
-        }
-    }
-
-    private TransportDiscoveryData(Parcel in) {
-        mTransportDataType = in.readInt();
-        mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        TransportDiscoveryData other = (TransportDiscoveryData) obj;
-        return Arrays.equals(toByteArray(), other.toByteArray());
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mTransportDataType);
-        dest.writeTypedList(mTransportBlocks);
-    }
-
-    public static final @NonNull Creator<TransportDiscoveryData> CREATOR =
-            new Creator<TransportDiscoveryData>() {
-                @Override
-                public TransportDiscoveryData createFromParcel(Parcel in) {
-                    return new TransportDiscoveryData(in);
-                }
-
-                @Override
-                public TransportDiscoveryData[] newArray(int size) {
-                    return new TransportDiscoveryData[size];
-                }
-    };
-
-    /**
-     * Gets the transport data type.
-     */
-    public int getTransportDataType() {
-        return mTransportDataType;
-    }
-
-    /**
-     * @return the list of {@link TransportBlock} in this TransportDiscoveryData
-     *         or an empty list if there are no Transport Blocks
-     */
-    @NonNull
-    public List<TransportBlock> getTransportBlocks() {
-        if (mTransportBlocks == null) {
-            return Collections.emptyList();
-        }
-        return mTransportBlocks;
-    }
-
-    /**
-     * Converts this TransportDiscoveryData to byte array
-     *
-     * @return byte array representation of this Transport Discovery Data or null if the
-     *         conversion failed
-     */
-    @Nullable
-    public byte[] toByteArray() {
-        try {
-            ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
-            buffer.put((byte) mTransportDataType);
-            for (TransportBlock transportBlock : getTransportBlocks()) {
-                buffer.put(transportBlock.toByteArray());
-            }
-            return buffer.array();
-        } catch (BufferOverflowException e) {
-            Log.e(TAG, "Error converting to byte array: " + e.toString());
-            return null;
-        }
-    }
-
-    /**
-     * @return total byte count of this TransportDataDiscovery
-     */
-    public int totalBytes() {
-        int size = 1; // Counting Transport Data Type here.
-        for (TransportBlock transportBlock : getTransportBlocks()) {
-            size += transportBlock.totalBytes();
-        }
-        return size;
-    }
-}
diff --git a/core/java/android/bluetooth/le/TruncatedFilter.java b/core/java/android/bluetooth/le/TruncatedFilter.java
deleted file mode 100644
index 2592588..0000000
--- a/core/java/android/bluetooth/le/TruncatedFilter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-
-import java.util.List;
-
-/**
- * A special scan filter that lets the client decide how the scan record should be stored.
- *
- * @deprecated this is not used anywhere
- *
- * @hide
- */
-@Deprecated
-@SystemApi
-@SuppressLint("AndroidFrameworkBluetoothPermission")
-public final class TruncatedFilter {
-    private final ScanFilter mFilter;
-    private final List<ResultStorageDescriptor> mStorageDescriptors;
-
-    /**
-     * Constructor for {@link TruncatedFilter}.
-     *
-     * @param filter Scan filter of the truncated filter.
-     * @param storageDescriptors Describes how the scan should be stored.
-     */
-    public TruncatedFilter(ScanFilter filter, List<ResultStorageDescriptor> storageDescriptors) {
-        mFilter = filter;
-        mStorageDescriptors = storageDescriptors;
-    }
-
-    /**
-     * Returns the scan filter.
-     */
-    public ScanFilter getFilter() {
-        return mFilter;
-    }
-
-    /**
-     * Returns a list of descriptor for scan result storage.
-     */
-    public List<ResultStorageDescriptor> getStorageDescriptors() {
-        return mStorageDescriptors;
-    }
-
-
-}
diff --git a/core/java/android/bluetooth/package.html b/core/java/android/bluetooth/package.html
deleted file mode 100644
index d9ca4f1..0000000
--- a/core/java/android/bluetooth/package.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<HTML>
-<BODY>
-<p>Provides classes that manage Bluetooth functionality, such as scanning for
-devices, connecting with devices, and managing data transfer between devices.
-The Bluetooth API supports both "Classic Bluetooth" and Bluetooth Low Energy.</p>
-
-<p>For more information about Classic Bluetooth, see the
-<a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> guide.
-For more information about Bluetooth Low Energy, see the
-<a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">
-Bluetooth Low Energy</a> (BLE) guide.</p>
-{@more}
-
-<p>The Bluetooth APIs let applications:</p>
-<ul>
-  <li>Scan for other Bluetooth devices (including BLE devices).</li>
-  <li>Query the local Bluetooth adapter for paired Bluetooth devices.</li>
-  <li>Establish RFCOMM channels/sockets.</li>
-  <li>Connect to specified sockets on other devices.</li>
-  <li>Transfer data to and from other devices.</li>
-  <li>Communicate with BLE devices, such as proximity sensors, heart rate
-    monitors, fitness devices, and so on.</li>
-  <li>Act as a GATT client or a GATT server (BLE).</li>
-</ul>
-
-<p>
-To perform Bluetooth communication using these APIs, an application must
-declare the {@link android.Manifest.permission#BLUETOOTH} permission. Some
-additional functionality, such as requesting device discovery,
-also requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-permission.
-</p>
-
-<p class="note"><strong>Note:</strong>
-Not all Android-powered devices provide Bluetooth functionality.</p>
-
-</BODY>
-</HTML>
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 98e124d..001be57 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3434,7 +3434,7 @@
     public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
 
     /**
-     * Connect to an application service, creating it if needed.  This defines
+     * Connects to an application service, creating it if needed.  This defines
      * a dependency between your application and the service.  The given
      * <var>conn</var> will receive the service object when it is created and be
      * told if it dies and restarts.  The service will be considered required
@@ -3449,11 +3449,8 @@
      * will be invoked instead of
      * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder) onServiceConnected()}.
      *
-     * <p>This method will throw {@link SecurityException} if the calling app does not
-     * have permission to bind to the given service.
-     *
-     * <p class="note">Note: this method <em>cannot be called from a
-     * {@link BroadcastReceiver} component</em>.  A pattern you can use to
+     * <p class="note"><b>Note:</b> This method <em>cannot</em> be called from a
+     * {@link BroadcastReceiver} component.  A pattern you can use to
      * communicate from a BroadcastReceiver to a Service is to call
      * {@link #startService} with the arguments containing the command to be
      * sent, with the service calling its
@@ -3468,34 +3465,34 @@
      *      specify an explicit component name.
      * @param conn Receives information as the service is started and stopped.
      *      This must be a valid ServiceConnection object; it must not be null.
-     * @param flags Operation options for the binding.  May be 0,
-     *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
-     *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
-     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
-     *          {@link #BIND_IMPORTANT}, {@link #BIND_ADJUST_WITH_ACTIVITY},
-     *          {@link #BIND_NOT_PERCEPTIBLE}, or {@link #BIND_INCLUDE_CAPABILITIES}.
-     * @return {@code true} if the system is in the process of bringing up a
+     * @param flags Operation options for the binding. Can be:
+     *      <ul>
+     *          <li>0
+     *          <li>{@link #BIND_AUTO_CREATE}
+     *          <li>{@link #BIND_DEBUG_UNBIND}
+     *          <li>{@link #BIND_NOT_FOREGROUND}
+     *          <li>{@link #BIND_ABOVE_CLIENT}
+     *          <li>{@link #BIND_ALLOW_OOM_MANAGEMENT}
+     *          <li>{@link #BIND_WAIVE_PRIORITY}
+     *          <li>{@link #BIND_IMPORTANT}
+     *          <li>{@link #BIND_ADJUST_WITH_ACTIVITY}
+     *          <li>{@link #BIND_NOT_PERCEPTIBLE}
+     *          <li>{@link #BIND_INCLUDE_CAPABILITIES}
+     *      </ul>
+     *
+      * @return {@code true} if the system is in the process of bringing up a
      *         service that your client has permission to bind to; {@code false}
      *         if the system couldn't find the service or if your client doesn't
-     *         have permission to bind to it. If this value is {@code true}, you
-     *         should later call {@link #unbindService} to release the
-     *         connection.
+     *         have permission to bind to it. You should call {@link #unbindService}
+     *         to release the connection even if this method returned {@code false}.
      *
-     * @throws SecurityException If the caller does not have permission to access the service
-     * or the service can not be found.
+     * @throws SecurityException If the caller does not have permission to
+     *      access the service or the service cannot be found. Call
+     *      {@link #unbindService} to release the connection when this exception
+     *      is thrown.
      *
      * @see #unbindService
      * @see #startService
-     * @see #BIND_AUTO_CREATE
-     * @see #BIND_DEBUG_UNBIND
-     * @see #BIND_NOT_FOREGROUND
-     * @see #BIND_ABOVE_CLIENT
-     * @see #BIND_ALLOW_OOM_MANAGEMENT
-     * @see #BIND_WAIVE_PRIORITY
-     * @see #BIND_IMPORTANT
-     * @see #BIND_ADJUST_WITH_ACTIVITY
-     * @see #BIND_NOT_PERCEPTIBLE
-     * @see #BIND_INCLUDE_CAPABILITIES
      */
     public abstract boolean bindService(@RequiresPermission Intent service,
             @NonNull ServiceConnection conn, @BindServiceFlags int flags);
@@ -5778,6 +5775,17 @@
     public static final String DISPLAY_HASH_SERVICE = "display_hash";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.nearby.NearbyManager} to discover nearby devices.
+     *
+     * @see #getSystemService(String)
+     * @see android.nearby.NearbyManager
+     * @hide
+     */
+    @SystemApi
+    public static final String NEARBY_SERVICE = "nearby";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9659df6..8a5e097 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4206,9 +4206,9 @@
      * restored from (corresponds to {@link android.os.Build.VERSION#SDK_INT}). The first three
      * values are represented as strings, the fourth one as int.
      *
-     * <p>This broadcast is sent only for settings provider entries known to require special handling
-     * around restore time.  These entries are found in the BROADCAST_ON_RESTORE table within
-     * the provider's backup agent implementation.
+     * <p>This broadcast is sent only for settings provider entries known to require special
+     * handling around restore time to specific receivers. These entries are found in the
+     * BROADCAST_ON_RESTORE table within the provider's backup agent implementation.
      *
      * @see #EXTRA_SETTING_NAME
      * @see #EXTRA_SETTING_PREVIOUS_VALUE
@@ -4216,15 +4216,46 @@
      * @see #EXTRA_SETTING_RESTORED_FROM_SDK_INT
      * {@hide}
      */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @SuppressLint("ActionValue")
     public static final String ACTION_SETTING_RESTORED = "android.os.action.SETTING_RESTORED";
 
-    /** {@hide} */
+    /**
+     * String intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+     * Contain the name of the restored setting.
+     * {@hide}
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @SuppressLint("ActionValue")
     public static final String EXTRA_SETTING_NAME = "setting_name";
-    /** {@hide} */
+
+    /**
+     * String intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+     * Contain the value of the {@link EXTRA_SETTING_NAME} settings entry prior to the restore
+     * operation.
+     * {@hide}
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @SuppressLint("ActionValue")
     public static final String EXTRA_SETTING_PREVIOUS_VALUE = "previous_value";
-    /** {@hide} */
+
+    /**
+     * String intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+     * Contain the value of the {@link EXTRA_SETTING_NAME} settings entry being restored.
+     * {@hide}
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @SuppressLint("ActionValue")
     public static final String EXTRA_SETTING_NEW_VALUE = "new_value";
-    /** {@hide} */
+
+    /**
+     * Int intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+     * Contain the version of the SDK that the setting has been restored from (corresponds to
+     * {@link android.os.Build.VERSION#SDK_INT}).
+     * {@hide}
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @SuppressLint("ActionValue")
     public static final String EXTRA_SETTING_RESTORED_FROM_SDK_INT = "restored_from_sdk_int";
 
     /**
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index 21398f6..660a7f0 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -63,8 +63,12 @@
      * happen, for example, if the application hosting the service it is bound to
      * has been updated.
      *
-     * @param name The concrete component name of the service whose
-     * connection is dead.
+     * <p class="note"><b>Note:</b> The app that requested the binding must call
+     * {@link Context#unbindService(ServiceConnection)} to release the tracking
+     * resources associated with this ServiceConnection even if this callback was
+     * invoked following {@link Context#bindService Context.bindService() bindService()}.
+     *
+     * @param name The concrete component name of the service whose connection is dead.
      */
     default void onBindingDied(ComponentName name) {
     }
@@ -72,10 +76,10 @@
     /**
      * Called when the service being bound has returned {@code null} from its
      * {@link android.app.Service#onBind(Intent) onBind()} method.  This indicates
-     * that the attempting service binding represented by this ServiceConnection
+     * that the attempted service binding represented by this ServiceConnection
      * will never become usable.
      *
-     * <p class="note">The app which requested the binding must still call
+     * <p class="note"><b>Note:</b> The app that requested the binding must still call
      * {@link Context#unbindService(ServiceConnection)} to release the tracking
      * resources associated with this ServiceConnection even if this callback was
      * invoked following {@link Context#bindService Context.bindService() bindService()}.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2ed00b5..7cd7e7ac 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2485,6 +2485,8 @@
      * API shipped in Android 11.
      * <li><code>202101</code>: corresponds to the features included in the Identity Credential
      * API shipped in Android 12.
+     * <li><code>202201</code>: corresponds to the features included in the Identity Credential
+     * API shipped in Android 13.
      * </ul>
      */
     @SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5b727cc..5031faa 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -198,7 +198,7 @@
             // Prune the cache before adding new items.
             final int N = sCache.size();
             for (int i = N - 1; i >= 0; i--) {
-                if (sCache.valueAt(i).get() == null) {
+                if (sCache.valueAt(i).refersTo(null)) {
                     sCache.removeAt(i);
                 }
             }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 12e41e2..932cc8e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -2011,7 +2011,7 @@
 
             // Clean up references to garbage collected themes
             if (mThemeRefs.size() > mThemeRefsNextFlushSize) {
-                mThemeRefs.removeIf(ref -> ref.get() == null);
+                mThemeRefs.removeIf(ref -> ref.refersTo(null));
                 mThemeRefsNextFlushSize = Math.max(MIN_THEME_REFS_FLUSH_SIZE,
                         2 * mThemeRefs.size());
             }
diff --git a/core/java/android/content/res/loader/ResourcesLoader.java b/core/java/android/content/res/loader/ResourcesLoader.java
index c308400..cf6e166 100644
--- a/core/java/android/content/res/loader/ResourcesLoader.java
+++ b/core/java/android/content/res/loader/ResourcesLoader.java
@@ -257,7 +257,7 @@
 
         for (int i = mChangeCallbacks.size() - 1; i >= 0; i--) {
             final WeakReference<Object> key = mChangeCallbacks.keyAt(i);
-            if (key.get() == null) {
+            if (key.refersTo(null)) {
                 mChangeCallbacks.removeAt(i);
             } else {
                 uniqueCallbacks.add(mChangeCallbacks.valueAt(i));
diff --git a/core/java/android/hardware/ISerialManager.aidl b/core/java/android/hardware/ISerialManager.aidl
index 74d30f7..65a0fa4 100644
--- a/core/java/android/hardware/ISerialManager.aidl
+++ b/core/java/android/hardware/ISerialManager.aidl
@@ -22,8 +22,10 @@
 interface ISerialManager
 {
     /* Returns a list of all available serial ports */
+    @EnforcePermission("SERIAL_PORT")
     String[] getSerialPorts();
 
     /* Returns a file descriptor for the serial port. */
+    @EnforcePermission("SERIAL_PORT")
     ParcelFileDescriptor openSerialPort(String name);
 }
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 4143bfc..ce5cf67 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -1,3 +1,9 @@
+# Generic
+etalvala@google.com
+jreck@google.com
+michaelwr@google.com
+sumir@google.com
+
 # Camera
 per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,zhijunhe@google.com,jchowdhary@google.com
 
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index e3ff089..ee62170 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -638,7 +638,7 @@
     /**
      * Unregisters a listener for the sensors with which it is registered.
      *
-     * <p class="note"></p>
+     * <p class="note">
      * Note: Don't use this method with a one shot trigger sensor such as
      * {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
      * Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index c8c122d..9fb70d6 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -38,6 +38,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.security.identity.IdentityCredential;
+import android.security.identity.PresentationSession;
 import android.security.keystore.KeyProperties;
 import android.text.TextUtils;
 import android.util.Log;
@@ -653,8 +654,8 @@
     /**
      * A wrapper class for the cryptographic operations supported by BiometricPrompt.
      *
-     * <p>Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac}, and
-     * {@link IdentityCredential}.
+     * <p>Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac},
+     * {@link IdentityCredential}, and {@link PresentationSession}.
      *
      * <p>Cryptographic operations in Android can be split into two categories: auth-per-use and
      * time-based. This is specified during key creation via the timeout parameter of the
@@ -684,10 +685,21 @@
             super(mac);
         }
 
+        /**
+         * Create from a {@link IdentityCredential} object.
+         *
+         * @param credential a {@link IdentityCredential} object.
+         * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
+         */
+        @Deprecated
         public CryptoObject(@NonNull IdentityCredential credential) {
             super(credential);
         }
 
+        public CryptoObject(@NonNull PresentationSession session) {
+            super(session);
+        }
+
         /**
          * Get {@link Signature} object.
          * @return {@link Signature} object or null if this doesn't contain one.
@@ -715,10 +727,20 @@
         /**
          * Get {@link IdentityCredential} object.
          * @return {@link IdentityCredential} object or null if this doesn't contain one.
+         * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
          */
+        @Deprecated
         public @Nullable IdentityCredential getIdentityCredential() {
             return super.getIdentityCredential();
         }
+
+        /**
+         * Get {@link PresentationSession} object.
+         * @return {@link PresentationSession} object or null if this doesn't contain one.
+         */
+        public @Nullable PresentationSession getPresentationSession() {
+            return super.getPresentationSession();
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index 7648cf2..d415706 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.security.identity.IdentityCredential;
+import android.security.identity.PresentationSession;
 import android.security.keystore2.AndroidKeyStoreProvider;
 
 import java.security.Signature;
@@ -27,8 +28,8 @@
 
 /**
  * A wrapper class for the crypto objects supported by BiometricPrompt and FingerprintManager.
- * Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac} and
- * {@link IdentityCredential} objects.
+ * Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac},
+ * {@link IdentityCredential}, and {@link PresentationSession} objects.
  * @hide
  */
 public class CryptoObject {
@@ -46,10 +47,21 @@
         mCrypto = mac;
     }
 
+    /**
+     * Create from a {@link IdentityCredential} object.
+     *
+     * @param credential a {@link IdentityCredential} object.
+     * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
+     */
+    @Deprecated
     public CryptoObject(@NonNull IdentityCredential credential) {
         mCrypto = credential;
     }
 
+    public CryptoObject(@NonNull PresentationSession session) {
+        mCrypto = session;
+    }
+
     /**
      * Get {@link Signature} object.
      * @return {@link Signature} object or null if this doesn't contain one.
@@ -77,12 +89,22 @@
     /**
      * Get {@link IdentityCredential} object.
      * @return {@link IdentityCredential} object or null if this doesn't contain one.
+     * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
      */
+    @Deprecated
     public IdentityCredential getIdentityCredential() {
         return mCrypto instanceof IdentityCredential ? (IdentityCredential) mCrypto : null;
     }
 
     /**
+     * Get {@link PresentationSession} object.
+     * @return {@link PresentationSession} object or null if this doesn't contain one.
+     */
+    public PresentationSession getPresentationSession() {
+        return mCrypto instanceof PresentationSession ? (PresentationSession) mCrypto : null;
+    }
+
+    /**
      * @hide
      * @return the opId associated with this object or 0 if none
      */
@@ -91,6 +113,8 @@
             return 0;
         } else if (mCrypto instanceof IdentityCredential) {
             return ((IdentityCredential) mCrypto).getCredstoreOperationHandle();
+        } else if (mCrypto instanceof PresentationSession) {
+            return ((PresentationSession) mCrypto).getCredstoreOperationHandle();
         }
         return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto);
     }
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index a3d595c..480923e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -58,6 +58,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.security.identity.IdentityCredential;
+import android.security.identity.PresentationSession;
 import android.util.Slog;
 import android.view.Surface;
 
@@ -264,10 +265,21 @@
          * Get {@link IdentityCredential} object.
          * @return {@link IdentityCredential} object or null if this doesn't contain one.
          * @hide
+         * @deprecated Use {@link PresentationSession} instead of {@link IdentityCredential}.
          */
+        @Deprecated
         public IdentityCredential getIdentityCredential() {
             return super.getIdentityCredential();
         }
+
+        /**
+         * Get {@link PresentationSession} object.
+         * @return {@link PresentationSession} object or null if this doesn't contain one.
+         * @hide
+         */
+        public PresentationSession getPresentationSession() {
+            return super.getPresentationSession();
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index 0c21746..066de11 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -17,6 +17,8 @@
 public abstract class HdmiClient {
     private static final String TAG = "HdmiClient";
 
+    private static final int UNKNOWN_VENDOR_ID = 0xFFFFFF;
+
     /* package */ final IHdmiControlService mService;
 
     private IHdmiVendorCommandListener mIHdmiVendorCommandListener;
@@ -94,11 +96,25 @@
     }
 
     /**
-     * Sets a listener used to receive incoming vendor-specific command.
+     * Sets a listener used to receive incoming vendor-specific command. This listener will only
+     * receive {@code <Vendor Command>} but will not receive any {@code <Vendor Command with ID>}
+     * messages.
      *
      * @param listener listener object
      */
     public void setVendorCommandListener(@NonNull VendorCommandListener listener) {
+        // Set the vendor ID to INVALID_VENDOR_ID.
+        setVendorCommandListener(listener, UNKNOWN_VENDOR_ID);
+    }
+
+    /**
+     * Sets a listener used to receive incoming vendor-specific command.
+     *
+     * @param listener listener object
+     * @param vendorId The listener is interested in {@code <Vendor Command with ID>} received with
+     *     this vendorId and all {@code <Vendor Command>} messages.
+     */
+    public void setVendorCommandListener(@NonNull VendorCommandListener listener, int vendorId) {
         if (listener == null) {
             throw new IllegalArgumentException("listener cannot be null");
         }
@@ -107,7 +123,7 @@
         }
         try {
             IHdmiVendorCommandListener wrappedListener = getListenerWrapper(listener);
-            mService.addVendorCommandListener(wrappedListener, getDeviceType());
+            mService.addVendorCommandListener(wrappedListener, vendorId);
             mIHdmiVendorCommandListener = wrappedListener;
         } catch (RemoteException e) {
             Log.e(TAG, "failed to set vendor command listener: ", e);
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 9a9e945..45b0689 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -221,8 +221,8 @@
         }
 
         @Override
-        public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
-            HdmiControlServiceWrapper.this.addVendorCommandListener(listener, deviceType);
+        public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {
+            HdmiControlServiceWrapper.this.addVendorCommandListener(listener, vendorId);
         }
 
         @Override
@@ -471,7 +471,7 @@
             boolean hasVendorId) {}
 
     /** @hide */
-    public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {}
+    public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {}
 
     /** @hide */
     public void sendStandby(int deviceType, int deviceId) {}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 7f0e53e..48177e1 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -76,7 +76,7 @@
     void askRemoteDeviceToBecomeActiveSource(int physicalAddress);
     void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
             boolean hasVendorId);
-    void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
+    void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId);
     void sendStandby(int deviceType, int deviceId);
     void setHdmiRecordListener(IHdmiRecordListener callback);
     void startOneTouchRecord(int recorderAddress, in byte[] recordSource);
diff --git a/core/java/android/net/DhcpResults.aidl b/core/java/android/net/DhcpResults.aidl
deleted file mode 100644
index f4db3c3..0000000
--- a/core/java/android/net/DhcpResults.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * 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.net;
-
-parcelable DhcpResults;
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
deleted file mode 100644
index 82ba156..0000000
--- a/core/java/android/net/DhcpResults.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * 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.net;
-
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.net.module.util.InetAddressUtils;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A simple object for retrieving the results of a DHCP request.
- * Optimized (attempted) for that jni interface
- * TODO: remove this class and replace with other existing constructs
- * @hide
- */
-public final class DhcpResults implements Parcelable {
-    private static final String TAG = "DhcpResults";
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public LinkAddress ipAddress;
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public InetAddress gateway;
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public final ArrayList<InetAddress> dnsServers = new ArrayList<>();
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public String domains;
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public Inet4Address serverAddress;
-
-    /** Vendor specific information (from RFC 2132). */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public String vendorInfo;
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int leaseDuration;
-
-    /** Link MTU option. 0 means unset. */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int mtu;
-
-    public String serverHostName;
-
-    @Nullable
-    public String captivePortalApiUrl;
-
-    public DhcpResults() {
-        super();
-    }
-
-    /**
-     * Create a {@link StaticIpConfiguration} based on the DhcpResults.
-     */
-    public StaticIpConfiguration toStaticIpConfiguration() {
-        return new StaticIpConfiguration.Builder()
-                .setIpAddress(ipAddress)
-                .setGateway(gateway)
-                .setDnsServers(dnsServers)
-                .setDomains(domains)
-                .build();
-    }
-
-    public DhcpResults(StaticIpConfiguration source) {
-        if (source != null) {
-            ipAddress = source.getIpAddress();
-            gateway = source.getGateway();
-            dnsServers.addAll(source.getDnsServers());
-            domains = source.getDomains();
-        }
-    }
-
-    /** copy constructor */
-    public DhcpResults(DhcpResults source) {
-        this(source == null ? null : source.toStaticIpConfiguration());
-        if (source != null) {
-            serverAddress = source.serverAddress;
-            vendorInfo = source.vendorInfo;
-            leaseDuration = source.leaseDuration;
-            mtu = source.mtu;
-            serverHostName = source.serverHostName;
-            captivePortalApiUrl = source.captivePortalApiUrl;
-        }
-    }
-
-    /**
-     * @see StaticIpConfiguration#getRoutes(String)
-     * @hide
-     */
-    public List<RouteInfo> getRoutes(String iface) {
-        return toStaticIpConfiguration().getRoutes(iface);
-    }
-
-    /**
-     * Test if this DHCP lease includes vendor hint that network link is
-     * metered, and sensitive to heavy data transfers.
-     */
-    public boolean hasMeteredHint() {
-        if (vendorInfo != null) {
-            return vendorInfo.contains("ANDROID_METERED");
-        } else {
-            return false;
-        }
-    }
-
-    public void clear() {
-        ipAddress = null;
-        gateway = null;
-        dnsServers.clear();
-        domains = null;
-        serverAddress = null;
-        vendorInfo = null;
-        leaseDuration = 0;
-        mtu = 0;
-        serverHostName = null;
-        captivePortalApiUrl = null;
-    }
-
-    @Override
-    public String toString() {
-        StringBuffer str = new StringBuffer(super.toString());
-
-        str.append(" DHCP server ").append(serverAddress);
-        str.append(" Vendor info ").append(vendorInfo);
-        str.append(" lease ").append(leaseDuration).append(" seconds");
-        if (mtu != 0) str.append(" MTU ").append(mtu);
-        str.append(" Servername ").append(serverHostName);
-        if (captivePortalApiUrl != null) {
-            str.append(" CaptivePortalApiUrl ").append(captivePortalApiUrl);
-        }
-
-        return str.toString();
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) return true;
-
-        if (!(obj instanceof DhcpResults)) return false;
-
-        DhcpResults target = (DhcpResults)obj;
-
-        return toStaticIpConfiguration().equals(target.toStaticIpConfiguration())
-                && Objects.equals(serverAddress, target.serverAddress)
-                && Objects.equals(vendorInfo, target.vendorInfo)
-                && Objects.equals(serverHostName, target.serverHostName)
-                && leaseDuration == target.leaseDuration
-                && mtu == target.mtu
-                && Objects.equals(captivePortalApiUrl, target.captivePortalApiUrl);
-    }
-
-    /**
-     * Implement the Parcelable interface
-     */
-    public static final @android.annotation.NonNull Creator<DhcpResults> CREATOR =
-        new Creator<DhcpResults>() {
-            public DhcpResults createFromParcel(Parcel in) {
-                return readFromParcel(in);
-            }
-
-            public DhcpResults[] newArray(int size) {
-                return new DhcpResults[size];
-            }
-        };
-
-    /** Implement the Parcelable interface */
-    public void writeToParcel(Parcel dest, int flags) {
-        toStaticIpConfiguration().writeToParcel(dest, flags);
-        dest.writeInt(leaseDuration);
-        dest.writeInt(mtu);
-        InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
-        dest.writeString(vendorInfo);
-        dest.writeString(serverHostName);
-        dest.writeString(captivePortalApiUrl);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    private static DhcpResults readFromParcel(Parcel in) {
-        final StaticIpConfiguration s = StaticIpConfiguration.CREATOR.createFromParcel(in);
-        final DhcpResults dhcpResults = new DhcpResults(s);
-        dhcpResults.leaseDuration = in.readInt();
-        dhcpResults.mtu = in.readInt();
-        dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
-        dhcpResults.vendorInfo = in.readString();
-        dhcpResults.serverHostName = in.readString();
-        dhcpResults.captivePortalApiUrl = in.readString();
-        return dhcpResults;
-    }
-
-    // Utils for jni population - false on success
-    // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
-    public boolean setIpAddress(String addrString, int prefixLength) {
-        try {
-            Inet4Address addr = (Inet4Address) InetAddresses.parseNumericAddress(addrString);
-            ipAddress = new LinkAddress(addr, prefixLength);
-        } catch (IllegalArgumentException|ClassCastException e) {
-            Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean setGateway(String addrString) {
-        try {
-            gateway = InetAddresses.parseNumericAddress(addrString);
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "setGateway failed with addrString " + addrString);
-            return true;
-        }
-        return false;
-    }
-
-    public boolean addDns(String addrString) {
-        if (TextUtils.isEmpty(addrString) == false) {
-            try {
-                dnsServers.add(InetAddresses.parseNumericAddress(addrString));
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "addDns failed with addrString " + addrString);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public LinkAddress getIpAddress() {
-        return ipAddress;
-    }
-
-    public void setIpAddress(LinkAddress ipAddress) {
-        this.ipAddress = ipAddress;
-    }
-
-    public InetAddress getGateway() {
-        return gateway;
-    }
-
-    public void setGateway(InetAddress gateway) {
-        this.gateway = gateway;
-    }
-
-    public List<InetAddress> getDnsServers() {
-        return dnsServers;
-    }
-
-    /**
-     * Add a DNS server to this configuration.
-     */
-    public void addDnsServer(InetAddress server) {
-        dnsServers.add(server);
-    }
-
-    public String getDomains() {
-        return domains;
-    }
-
-    public void setDomains(String domains) {
-        this.domains = domains;
-    }
-
-    public Inet4Address getServerAddress() {
-        return serverAddress;
-    }
-
-    public void setServerAddress(Inet4Address addr) {
-        serverAddress = addr;
-    }
-
-    public int getLeaseDuration() {
-        return leaseDuration;
-    }
-
-    public void setLeaseDuration(int duration) {
-        leaseDuration = duration;
-    }
-
-    public String getVendorInfo() {
-        return vendorInfo;
-    }
-
-    public void setVendorInfo(String info) {
-        vendorInfo = info;
-    }
-
-    public int getMtu() {
-        return mtu;
-    }
-
-    public void setMtu(int mtu) {
-        this.mtu = mtu;
-    }
-
-    public String getCaptivePortalApiUrl() {
-        return captivePortalApiUrl;
-    }
-
-    public void setCaptivePortalApiUrl(String url) {
-        captivePortalApiUrl = url;
-    }
-}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index f50aa99..6284f56 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -69,6 +69,8 @@
 
     int getMultipathPreference(in Network network);
 
+    SubscriptionPlan getSubscriptionPlan(in NetworkTemplate template);
+    void notifyStatsProviderWarningOrLimitReached();
     SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
     void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
     String getSubscriptionPlansOwner(int subId);
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index 271efe4..070efa3 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -38,7 +38,7 @@
     /** VpnManager APIs */
     boolean provisionVpnProfile(in VpnProfile profile, String packageName);
     void deleteVpnProfile(String packageName);
-    void startVpnProfile(String packageName);
+    String startVpnProfile(String packageName);
     void stopVpnProfile(String packageName);
 
     /** Always-on VPN APIs */
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 5554137..0fd3e03 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -25,6 +25,12 @@
 import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
 import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
 import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
+import static android.net.eap.EapSessionConfig.EapMsChapV2Config;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility;
 import static com.android.internal.util.Preconditions.checkStringNotEmpty;
@@ -34,6 +40,14 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.content.pm.PackageManager;
+import android.net.ipsec.ike.IkeFqdnIdentification;
+import android.net.ipsec.ike.IkeIdentification;
+import android.net.ipsec.ike.IkeIpv4AddrIdentification;
+import android.net.ipsec.ike.IkeIpv6AddrIdentification;
+import android.net.ipsec.ike.IkeKeyIdIdentification;
+import android.net.ipsec.ike.IkeRfc822AddrIdentification;
+import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
 import android.security.Credentials;
 import android.util.Log;
 
@@ -145,8 +159,9 @@
             boolean isMetered,
             int maxMtu,
             boolean restrictToTestNetworks,
-            boolean excludeLocalRoutes) {
-        super(type, excludeLocalRoutes);
+            boolean excludeLocalRoutes,
+            boolean requiresInternetValidation) {
+        super(type, excludeLocalRoutes, requiresInternetValidation);
 
         checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
         checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
@@ -167,7 +182,7 @@
         mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms));
         if (excludeLocalRoutes && !isBypassable) {
             throw new IllegalArgumentException(
-                    "Vpn should be byassable if excludeLocalRoutes is set");
+                    "Vpn must be bypassable if excludeLocalRoutes is set");
         }
 
         mIsBypassable = isBypassable;
@@ -224,7 +239,7 @@
      * that provides Authentication, and one that provides Encryption. Authenticated Encryption with
      * Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption.
      *
-     * @param allowedAlgorithms The list to be validated
+     * @param algorithmNames The list to be validated
      */
     private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) {
         // First, make sure no insecure algorithms were proposed.
@@ -386,7 +401,9 @@
                 mIsBypassable,
                 mIsMetered,
                 mMaxMtu,
-                mIsRestrictedToTestNetworks);
+                mIsRestrictedToTestNetworks,
+                mExcludeLocalRoutes,
+                mRequiresInternetValidation);
     }
 
     @Override
@@ -411,7 +428,8 @@
                 && mIsMetered == other.mIsMetered
                 && mMaxMtu == other.mMaxMtu
                 && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
-                && mExcludeLocalRoutes == other.mExcludeLocalRoutes;
+                && mExcludeLocalRoutes == other.mExcludeLocalRoutes
+                && mRequiresInternetValidation == other.mRequiresInternetValidation;
     }
 
     /**
@@ -425,7 +443,7 @@
     @NonNull
     public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
         final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
-                mIsRestrictedToTestNetworks, mExcludeLocalRoutes);
+                mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation);
         profile.type = mType;
         profile.server = mServerAddr;
         profile.ipsecIdentifier = mUserIdentity;
@@ -529,7 +547,9 @@
         if (profile.excludeLocalRoutes && !profile.isBypassable) {
             Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
         }
-        builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable);
+
+        builder.setLocalRoutesExcluded(profile.excludeLocalRoutes && profile.isBypassable);
+        builder.setRequiresInternetValidation(profile.requiresInternetValidation);
 
         return builder.build();
     }
@@ -644,6 +664,102 @@
         return Objects.requireNonNull(reference, String.format(messageTemplate, messageArgs));
     }
 
+    private static void checkBuilderSetter(boolean constructedFromIkeTunConParams,
+            @NonNull String message) {
+        if (constructedFromIkeTunConParams) {
+            throw new IllegalArgumentException("Constructed using IkeTunnelConnectionParams "
+                    + "should not set " + message);
+        }
+    }
+
+    private static int getTypeFromIkeSession(@NonNull IkeSessionParams params) {
+        final IkeAuthConfig config = params.getLocalAuthConfig();
+        if (config instanceof IkeAuthDigitalSignLocalConfig) {
+            return TYPE_IKEV2_IPSEC_RSA;
+        } else if (config instanceof IkeAuthEapConfig) {
+            return TYPE_IKEV2_IPSEC_USER_PASS;
+        } else if (config instanceof IkeAuthPskConfig) {
+            return TYPE_IKEV2_IPSEC_PSK;
+        } else {
+            throw new IllegalStateException("Invalid local IkeAuthConfig");
+        }
+    }
+
+    @Nullable
+    private static String getPasswordFromIkeSession(@NonNull IkeSessionParams params) {
+        if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
+
+        final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
+        final EapMsChapV2Config eapMsChapV2Config =
+                ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
+        return (eapMsChapV2Config != null) ? eapMsChapV2Config.getPassword() : null;
+    }
+
+    @Nullable
+    private static String getUsernameFromIkeSession(@NonNull IkeSessionParams params) {
+        if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
+
+        final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
+        final EapMsChapV2Config eapMsChapV2Config =
+                ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
+        return (eapMsChapV2Config != null) ? eapMsChapV2Config.getUsername() : null;
+    }
+
+    @Nullable
+    private static X509Certificate getUserCertFromIkeSession(@NonNull IkeSessionParams params) {
+        if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
+
+        final IkeAuthDigitalSignLocalConfig config =
+                (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
+        return config.getClientEndCertificate();
+    }
+
+    @Nullable
+    private static X509Certificate getServerRootCaCertFromIkeSession(
+            @NonNull IkeSessionParams params) {
+        if (!(params.getRemoteAuthConfig() instanceof IkeAuthDigitalSignRemoteConfig)) return null;
+
+        final IkeAuthDigitalSignRemoteConfig config =
+                (IkeAuthDigitalSignRemoteConfig) params.getRemoteAuthConfig();
+        return config.getRemoteCaCert();
+    }
+
+    @Nullable
+    private static PrivateKey getRsaPrivateKeyFromIkeSession(@NonNull IkeSessionParams params) {
+        if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
+
+        final IkeAuthDigitalSignLocalConfig config =
+                (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
+        return config.getPrivateKey();
+    }
+
+    @Nullable
+    private static byte[] getPresharedKeyFromIkeSession(@NonNull IkeSessionParams params) {
+        if (!(params.getLocalAuthConfig() instanceof IkeAuthPskConfig)) return null;
+
+        final IkeAuthPskConfig config = (IkeAuthPskConfig) params.getLocalAuthConfig();
+        return config.getPsk();
+    }
+
+    @NonNull
+    private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) {
+        final IkeIdentification ident = params.getLocalIdentification();
+        // Refer to VpnIkev2Utils.parseIkeIdentification().
+        if (ident instanceof IkeKeyIdIdentification) {
+            return "@#" + new String(((IkeKeyIdIdentification) ident).keyId);
+        } else if (ident instanceof IkeRfc822AddrIdentification) {
+            return "@@" + ((IkeRfc822AddrIdentification) ident).rfc822Name;
+        } else if (ident instanceof IkeFqdnIdentification) {
+            return "@" + ((IkeFqdnIdentification) ident).fqdn;
+        } else if (ident instanceof IkeIpv4AddrIdentification) {
+            return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress();
+        } else if (ident instanceof IkeIpv6AddrIdentification) {
+            return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress();
+        } else {
+            throw new IllegalArgumentException("Unknown IkeIdentification to get user identity");
+        }
+    }
+
     /** A incremental builder for IKEv2 VPN profiles */
     public static final class Builder {
         private int mType = -1;
@@ -666,11 +782,13 @@
 
         @Nullable private ProxyInfo mProxyInfo;
         @NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS;
+        private boolean mRequiresInternetValidation = false;
         private boolean mIsBypassable = false;
         private boolean mIsMetered = true;
         private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
         private boolean mIsRestrictedToTestNetworks = false;
         private boolean mExcludeLocalRoutes = false;
+        @Nullable private IkeTunnelConnectionParams mIkeTunConnParams;
 
         /**
          * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -687,6 +805,32 @@
             mUserIdentity = identity;
         }
 
+        /**
+         * Creates a new builder from a {@link IkeTunnelConnectionParams}
+         *
+         * @param ikeTunConnParams the {@link IkeTunnelConnectionParams} contains IKEv2
+         *                         configurations
+         */
+        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+        public Builder(@NonNull IkeTunnelConnectionParams ikeTunConnParams) {
+            checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams");
+
+            mIkeTunConnParams = ikeTunConnParams;
+
+            final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
+            mServerAddr = ikeSessionParams.getServerHostname();
+
+            mType = getTypeFromIkeSession(ikeSessionParams);
+            mUserCert = getUserCertFromIkeSession(ikeSessionParams);
+            mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
+            mRsaPrivateKey = getRsaPrivateKeyFromIkeSession(ikeSessionParams);
+            mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
+            mUsername = getUsernameFromIkeSession(ikeSessionParams);
+            mPassword = getPasswordFromIkeSession(ikeSessionParams);
+            mPresharedKey = getPresharedKeyFromIkeSession(ikeSessionParams);
+            mUserIdentity = getUserIdentityFromIkeSession(ikeSessionParams);
+        }
+
         private void resetAuthParams() {
             mPresharedKey = null;
             mServerRootCaCert = null;
@@ -719,6 +863,7 @@
                 @Nullable X509Certificate serverRootCa) {
             checkNotNull(user, MISSING_PARAM_MSG_TMPL, "user");
             checkNotNull(pass, MISSING_PARAM_MSG_TMPL, "pass");
+            checkBuilderSetter(mIkeTunConnParams != null, "authUsernamePassword");
 
             // Test to make sure all auth params can be encoded safely.
             if (serverRootCa != null) checkCert(serverRootCa);
@@ -755,6 +900,7 @@
                 @Nullable X509Certificate serverRootCa) {
             checkNotNull(userCert, MISSING_PARAM_MSG_TMPL, "userCert");
             checkNotNull(key, MISSING_PARAM_MSG_TMPL, "key");
+            checkBuilderSetter(mIkeTunConnParams != null, "authDigitalSignature");
 
             // Test to make sure all auth params can be encoded safely.
             checkCert(userCert);
@@ -782,6 +928,7 @@
         @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
         public Builder setAuthPsk(@NonNull byte[] psk) {
             checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk");
+            checkBuilderSetter(mIkeTunConnParams != null, "authPsk");
 
             resetAuthParams();
             mPresharedKey = psk;
@@ -848,6 +995,30 @@
         }
 
         /**
+         * Request that this VPN undergoes Internet validation.
+         *
+         * If this is true, the platform will perform basic validation checks for Internet
+         * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+         * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+         * capability.
+         *
+         * If this is false, the platform assumes the VPN either is always capable of reaching the
+         * Internet or intends not to. In this case, the VPN network capabilities will
+         * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+         * immediately after it connects, whether it can reach public Internet destinations or not.
+         *
+         * @param requiresInternetValidation {@code true} if the framework should attempt to
+         *                                   validate this VPN for Internet connectivity. Defaults
+         *                                   to {@code false}.
+         */
+        @NonNull
+        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+        public Builder setRequiresInternetValidation(boolean requiresInternetValidation) {
+            mRequiresInternetValidation = requiresInternetValidation;
+            return this;
+        }
+
+        /**
          * Marks the VPN network as metered.
          *
          * <p>A VPN network is classified as metered when the user is sensitive to heavy data usage
@@ -931,12 +1102,10 @@
          *
          * Note that because the local traffic will always bypass the VPN,
          * it is not possible to set this flag on a non-bypassable VPN.
-         *
-         * @hide TODO(184750836): unhide once the implementation is completed
          */
         @NonNull
         @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-        public Builder setExcludeLocalRoutes(boolean excludeLocalRoutes) {
+        public Builder setLocalRoutesExcluded(boolean excludeLocalRoutes) {
             mExcludeLocalRoutes = excludeLocalRoutes;
             return this;
         }
@@ -965,7 +1134,8 @@
                     mIsMetered,
                     mMaxMtu,
                     mIsRestrictedToTestNetworks,
-                    mExcludeLocalRoutes);
+                    mExcludeLocalRoutes,
+                    mRequiresInternetValidation);
         }
     }
 }
diff --git a/core/java/android/net/InternalNetworkManagementException.java b/core/java/android/net/InternalNetworkManagementException.java
deleted file mode 100644
index 7f4e403..0000000
--- a/core/java/android/net/InternalNetworkManagementException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.net;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public final class InternalNetworkManagementException
-        extends RuntimeException implements Parcelable {
-
-    /* @hide */
-    public InternalNetworkManagementException(@NonNull final Throwable t) {
-        super(t);
-    }
-
-    private InternalNetworkManagementException(@NonNull final Parcel source) {
-        super(source.readString());
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(getCause().getMessage());
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR =
-            new Parcelable.Creator<InternalNetworkManagementException>() {
-                @Override
-                public InternalNetworkManagementException[] newArray(int size) {
-                    return new InternalNetworkManagementException[size];
-                }
-
-                @Override
-                public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) {
-                    return new InternalNetworkManagementException(source);
-                }
-            };
-}
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index d1f49d2..506cbcb 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -55,7 +55,9 @@
      * Create a LocalServerSocket from a file descriptor that's already
      * been created and bound. listen() will be called immediately on it.
      * Used for cases where file descriptors are passed in via environment
-     * variables
+     * variables. The passed-in FileDescriptor is not managed by this class
+     * and must be closed by the caller. Calling {@link #close()} on a socket
+     * created by this method has no effect.
      *
      * @param fd bound file descriptor
      * @throws IOException
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 5b38f78..b69410c 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -16,7 +16,14 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.system.ErrnoException;
+import android.system.Os;
 
 import java.io.Closeable;
 import java.io.FileDescriptor;
@@ -74,32 +81,39 @@
         this.isBound = false;
     }
 
+    private void checkConnected() {
+        try {
+            Os.getpeername(impl.getFileDescriptor());
+        } catch (ErrnoException e) {
+            throw new IllegalArgumentException("Not a connected socket", e);
+        }
+        isConnected = true;
+        isBound = true;
+        implCreated = true;
+    }
+
     /**
-     * Creates a LocalSocket instances using the FileDescriptor for an already-connected
-     * AF_LOCAL/UNIX domain stream socket. Note: the FileDescriptor must be closed by the caller:
-     * closing the LocalSocket will not close it.
+     * Creates a LocalSocket instance using the {@link FileDescriptor} for an already-connected
+     * AF_LOCAL/UNIX domain stream socket. The passed-in FileDescriptor is not managed by this class
+     * and must be closed by the caller. Calling {@link #close()} on a socket created by this
+     * method has no effect.
      *
-     * @hide - used by BluetoothSocket.
+     * @param fd the filedescriptor to adopt
+     *
+     * @hide
      */
-    public static LocalSocket createConnectedLocalSocket(FileDescriptor fd) {
-        return createConnectedLocalSocket(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
+    @SystemApi(client = MODULE_LIBRARIES)
+    public LocalSocket(@NonNull @SuppressLint("UseParcelFileDescriptor") FileDescriptor fd) {
+        this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
+        checkConnected();
     }
 
     /**
      * for use with LocalServerSocket.accept()
      */
     static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl) {
-        return createConnectedLocalSocket(impl, SOCKET_UNKNOWN);
-    }
-
-    /**
-     * Creates a LocalSocket from an existing LocalSocketImpl that is already connected.
-     */
-    private static LocalSocket createConnectedLocalSocket(LocalSocketImpl impl, int sockType) {
-        LocalSocket socket = new LocalSocket(impl, sockType);
-        socket.isConnected = true;
-        socket.isBound = true;
-        socket.implCreated = true;
+        LocalSocket socket = new LocalSocket(impl, SOCKET_UNKNOWN);
+        socket.checkConnected();
         return socket;
     }
 
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index ab1f542..4b35b0d 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -338,7 +338,9 @@
         out.writeInt(TEMPLATE_BACKUP_VERSION_LATEST);
 
         out.writeInt(template.getMatchRule());
-        BackupUtils.writeString(out, template.getSubscriberIds().iterator().next());
+        final Set<String> subscriberIds = template.getSubscriberIds();
+        BackupUtils.writeString(out, subscriberIds.isEmpty()
+                ? null : subscriberIds.iterator().next());
         BackupUtils.writeString(out, template.getWifiNetworkKeys().isEmpty()
                 ? null : template.getWifiNetworkKeys().iterator().next());
         out.writeInt(template.getMeteredness());
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 7ebb646..0e39f42 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -167,6 +167,8 @@
     public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
     /** @hide */
     public static final String FIREWALL_CHAIN_NAME_RESTRICTED = "restricted";
+    /** @hide */
+    public static final String FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY = "low_power_standby";
 
     private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
 
@@ -535,6 +537,46 @@
     }
 
     /**
+     * Get subscription plan for the given networkTemplate.
+     *
+     * @param template the networkTemplate to get the subscription plan for.
+     * @return the active {@link SubscriptionPlan} for the given template, or
+     *         {@code null} if not found.
+     * @hide
+     */
+    @Nullable
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK})
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public SubscriptionPlan getSubscriptionPlan(@NonNull NetworkTemplate template) {
+        try {
+            return mService.getSubscriptionPlan(template);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Notifies that the specified {@link NetworkStatsProvider} has reached its quota
+     * which was set through {@link NetworkStatsProvider#onSetLimit(String, long)} or
+     * {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}.
+     *
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK})
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public void notifyStatsProviderWarningOrLimitReached() {
+        try {
+            mService.notifyStatsProviderWarningOrLimitReached();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Resets network policy settings back to factory defaults.
      *
      * @hide
diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java
index 777a90c..c0fb4cf 100644
--- a/core/java/android/net/PlatformVpnProfile.java
+++ b/core/java/android/net/PlatformVpnProfile.java
@@ -16,10 +16,6 @@
 
 package android.net;
 
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 
@@ -67,11 +63,15 @@
 
     /** @hide */
     protected final boolean mExcludeLocalRoutes;
+    /** @hide */
+    protected final boolean mRequiresInternetValidation;
 
     /** @hide */
-    PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes) {
+    PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes,
+            boolean requiresValidation) {
         mType = type;
         mExcludeLocalRoutes = excludeLocalRoutes;
+        mRequiresInternetValidation = requiresValidation;
     }
 
     /** Returns the profile integer type. */
@@ -80,14 +80,28 @@
         return mType;
     }
 
+    /**
+     * Returns whether the local traffic is exempted from the VPN.
+     */
+    public final boolean areLocalRoutesExcluded() {
+        return mExcludeLocalRoutes;
+    }
 
     /**
-     * Returns if the local traffic is exempted from the VPN.
+     * Returns whether this VPN should undergo Internet validation.
      *
-     * @hide TODO(184750836): unhide once the implementation is completed
+     * If this is true, the platform will perform basic validation checks for Internet
+     * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+     * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+     * capability.
+     *
+     * If this is false, the platform assumes the VPN either is always capable of reaching the
+     * Internet or intends not to. In this case, the VPN network capabilities will
+     * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+     * immediately after it connects, whether it can reach public Internet destinations or not.
      */
-    public final boolean getExcludeLocalRoutes() {
-        return mExcludeLocalRoutes;
+    public final boolean getRequiresInternetValidation() {
+        return mRequiresInternetValidation;
     }
 
     /** Returns a type string describing the VPN profile type */
diff --git a/core/java/android/net/PrivateDnsConnectivityChecker.java b/core/java/android/net/PrivateDnsConnectivityChecker.java
index cfd458c..ac97b36 100644
--- a/core/java/android/net/PrivateDnsConnectivityChecker.java
+++ b/core/java/android/net/PrivateDnsConnectivityChecker.java
@@ -44,7 +44,7 @@
      */
     public static boolean canConnectToPrivateDnsServer(@NonNull String hostname) {
         final SocketFactory factory = SSLSocketFactory.getDefault();
-        TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_APP);
+        TrafficStats.setThreadStatsTagApp();
 
         try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
             socket.setSoTimeout(CONNECTION_TIMEOUT_MS);
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index 5c28553..779d931 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -24,6 +24,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
@@ -52,7 +53,7 @@
  * app (unlike VpnService).
  *
  * <p>VPN apps using supported protocols should preferentially use this API over the {@link
- * VpnService} API for ease-of-development and reduced maintainance burden. This also give the user
+ * VpnService} API for ease-of-development and reduced maintenance burden. This also give the user
  * the guarantee that VPN network traffic is not subjected to on-device packet interception.
  *
  * @see Ikev2VpnProfile
@@ -96,6 +97,177 @@
      */
     public static final String NOTIFICATION_CHANNEL_VPN = "VPN";
 
+    /**
+     * Action sent in {@link android.content.Intent}s to VpnManager clients when an event occurred.
+     *
+     * This action will have a category of either {@link #CATEGORY_EVENT_IKE_ERROR},
+     * {@link #CATEGORY_EVENT_NETWORK_ERROR}, or {@link #CATEGORY_EVENT_DEACTIVATED_BY_USER},
+     * that the app can use to filter events it's interested in reacting to.
+     *
+     * It will also contain the following extras :
+     * <ul>
+     *   <li>{@link #EXTRA_SESSION_KEY}, a {@code String} for the session key, as returned by
+     *       {@link #startProvisionedVpnProfileSession}.
+     *   <li>{@link #EXTRA_TIMESTAMP}, a long for the timestamp at which the error occurred,
+     *       in milliseconds since the epoch, as returned by
+     *       {@link java.lang.System#currentTimeMillis}.
+     *   <li>{@link #EXTRA_UNDERLYING_NETWORK}, a {@link Network} containing the underlying
+     *       network at the time the error occurred, or null if none. Note that this network
+     *       may have disconnected already.
+     *   <li>{@link #EXTRA_UNDERLYING_NETWORK_CAPABILITIES}, a {@link NetworkCapabilities} for
+     *       the underlying network at the time the error occurred.
+     *   <li>{@link #EXTRA_UNDERLYING_LINK_PROPERTIES}, a {@link LinkProperties} for the underlying
+     *       network at the time the error occurred.
+     * </ul>
+     * When this event is an error, either {@link #CATEGORY_EVENT_IKE_ERROR} or
+     * {@link #CATEGORY_EVENT_NETWORK_ERROR}, the following extras will be populated :
+     * <ul>
+     *   <li>{@link #EXTRA_ERROR_CLASS}, an {@code int} for the class of error, either
+     *       {@link #ERROR_CLASS_RECOVERABLE} or {@link #ERROR_CLASS_NOT_RECOVERABLE}.
+     *   <li>{@link #EXTRA_ERROR_CODE}, an {@code int} error code specific to the error. See
+     *       {@link #EXTRA_ERROR_CODE} for details.
+     * </ul>
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
+
+    /**
+     * An IKE protocol error occurred.
+     *
+     * Codes (in {@link #EXTRA_ERROR_CODE}) are the codes from
+     * {@link android.net.ipsec.ike.exceptions.IkeProtocolException}, as defined by IANA in
+     * "IKEv2 Notify Message Types - Error Types".
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
+
+    /**
+     * A network error occurred.
+     *
+     * Error codes (in {@link #EXTRA_ERROR_CODE}) are ERROR_CODE_NETWORK_*.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_EVENT_NETWORK_ERROR =
+            "android.net.category.EVENT_NETWORK_ERROR";
+
+    /**
+     * The user deactivated the VPN.
+     *
+     * This can happen either when the user turns the VPN off explicitly, or when they select
+     * a different VPN provider.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER =
+            "android.net.category.EVENT_DEACTIVATED_BY_USER";
+
+    /**
+     * The key of the session that experienced this event, as a {@code String}.
+     *
+     * This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
+     */
+    public static final String EXTRA_SESSION_KEY = "android.net.extra.SESSION_KEY";
+
+    /**
+     * The network that was underlying the VPN when the event occurred, as a {@link Network}.
+     *
+     * This extra will be null if there was no underlying network at the time of the event.
+     */
+    public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
+
+    /**
+     * The {@link NetworkCapabilities} of the underlying network when the event occurred.
+     *
+     * This extra will be null if there was no underlying network at the time of the event.
+     */
+    public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES =
+            "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
+
+    /**
+     * The {@link LinkProperties} of the underlying network when the event occurred.
+     *
+     * This extra will be null if there was no underlying network at the time of the event.
+     */
+    public static final String EXTRA_UNDERLYING_LINK_PROPERTIES =
+            "android.net.extra.UNDERLYING_LINK_PROPERTIES";
+
+    /**
+     * A {@code long} timestamp containing the time at which the event occurred.
+     *
+     * This is a number of milliseconds since the epoch, suitable to be compared with
+     * {@link java.lang.System#currentTimeMillis}.
+     */
+    public static final String EXTRA_TIMESTAMP = "android.net.extra.TIMESTAMP";
+
+    /**
+     * Extra for the error class, as an {@code int}.
+     *
+     * This is always either {@link #ERROR_CLASS_NOT_RECOVERABLE} or
+     * {@link #ERROR_CLASS_RECOVERABLE}. This extra is only populated for error categories.
+     */
+    public static final String EXTRA_ERROR_CLASS = "android.net.extra.ERROR_CLASS";
+
+    /**
+     * Extra for an error code, as an {@code int}.
+     *
+     * <ul>
+     *   <li>For {@link #CATEGORY_EVENT_NETWORK_ERROR}, this is one of the
+     *       {@code ERROR_CODE_NETWORK_*} constants.
+     *   <li>For {@link #CATEGORY_EVENT_IKE_ERROR}, this is one of values defined in
+     *       {@link android.net.ipsec.ike.exceptions.IkeProtocolException}.ERROR_TYPE_*.
+     * </ul>
+     * For non-error categories, this extra is not populated.
+     */
+    public static final String EXTRA_ERROR_CODE = "android.net.extra.ERROR_CODE";
+
+    /**
+     * {@link #EXTRA_ERROR_CLASS} coding for a non-recoverable error.
+     *
+     * This error is fatal, e.g. configuration error. The stack will not retry connection.
+     */
+    public static final int ERROR_CLASS_NOT_RECOVERABLE = 1;
+
+    /**
+     * {@link #EXTRA_ERROR_CLASS} coding for a recoverable error.
+     *
+     * The stack experienced an error but will retry with exponential backoff, e.g. network timeout.
+     */
+    public static final int ERROR_CLASS_RECOVERABLE = 2;
+
+    /**
+     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} to indicate that the
+     * network host isn't known.
+     *
+     * This happens when domain name resolution could not resolve an IP address for the
+     * specified host. {@see java.net.UnknownHostException}
+     */
+    public static final int ERROR_CODE_NETWORK_UNKNOWN_HOST = 0;
+
+    /**
+     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating a timeout.
+     *
+     * For Ikev2 VPNs, this happens typically after a retransmission failure.
+     * {@see android.net.ipsec.ike.exceptions.IkeTimeoutException}
+     */
+    public static final int ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT = 1;
+
+    /**
+     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating that
+     * network connectivity was lost.
+     *
+     * The most common reason for this error is that the underlying network was disconnected,
+     * {@see android.net.ipsec.ike.exceptions.IkeNetworkLostException}.
+     */
+    public static final int ERROR_CODE_NETWORK_LOST = 2;
+
+    /**
+     * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating an
+     * input/output error.
+     *
+     * This code happens when reading or writing to sockets on the underlying networks was
+     * terminated by an I/O error. {@see IOException}.
+     */
+    public static final int ERROR_CODE_NETWORK_IO = 3;
+
     /** @hide */
     @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY,
             TYPE_VPN_OEM})
@@ -182,17 +354,32 @@
     /**
      * Request the startup of a previously provisioned VPN.
      *
+     * @return A unique key corresponding to this session.
      * @throws SecurityException exception if user or device settings prevent this VPN from being
-     *     setup, or if user consent has not been granted
+     *         setup, or if user consent has not been granted
      */
-    public void startProvisionedVpnProfile() {
+    @NonNull
+    public String startProvisionedVpnProfileSession() {
         try {
-            mService.startVpnProfile(mContext.getOpPackageName());
+            return mService.startVpnProfile(mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /**
+     * Request the startup of a previously provisioned VPN.
+     *
+     * @throws SecurityException exception if user or device settings prevent this VPN from being
+     *         setup, or if user consent has not been granted
+     * @deprecated This method is replaced by startProvisionedVpnProfileSession which returns a
+     *             session key for the caller to diagnose the errors.
+     */
+    @Deprecated
+    public void startProvisionedVpnProfile() {
+        startProvisionedVpnProfileSession();
+    }
+
     /** Tear down the VPN provided by the calling app (if any) */
     public void stopProvisionedVpnProfile() {
         try {
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 2ced056..1ae1b05 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -41,6 +41,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.net.NetworkUtilsInternal;
 import com.android.internal.net.VpnConfig;
 
@@ -50,6 +51,7 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -471,6 +473,13 @@
         }
     }
 
+    private static void checkNonPrefixBytes(@NonNull InetAddress address, int prefixLength) {
+        final IpPrefix prefix = new IpPrefix(address, prefixLength);
+        if (!prefix.getAddress().equals(address)) {
+            throw new IllegalArgumentException("Bad address");
+        }
+    }
+
     /**
      * Helper class to create a VPN interface. This class should be always
      * used within the scope of the outer {@link VpnService}.
@@ -481,9 +490,9 @@
 
         private final VpnConfig mConfig = new VpnConfig();
         @UnsupportedAppUsage
-        private final List<LinkAddress> mAddresses = new ArrayList<LinkAddress>();
+        private final List<LinkAddress> mAddresses = new ArrayList<>();
         @UnsupportedAppUsage
-        private final List<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
+        private final List<RouteInfo> mRoutes = new ArrayList<>();
 
         public Builder() {
             mConfig.user = VpnService.this.getClass().getName();
@@ -555,7 +564,6 @@
                 throw new IllegalArgumentException("Bad address");
             }
             mAddresses.add(new LinkAddress(address, prefixLength));
-            mConfig.updateAllowedFamilies(address);
             return this;
         }
 
@@ -579,28 +587,68 @@
          * Add a network route to the VPN interface. Both IPv4 and IPv6
          * routes are supported.
          *
+         * If a route with the same destination is already present, its type will be updated.
+         *
+         * @throws IllegalArgumentException if the route is invalid.
+         */
+        @NonNull
+        private Builder addRoute(@NonNull IpPrefix prefix, int type) {
+            check(prefix.getAddress(), prefix.getPrefixLength());
+
+            final RouteInfo newRoute = new RouteInfo(prefix, /* gateway */
+                    null, /* interface */ null, type);
+
+            final int index = findRouteIndexByDestination(newRoute);
+
+            if (index == -1) {
+                mRoutes.add(newRoute);
+            } else {
+                mRoutes.set(index, newRoute);
+            }
+
+            return this;
+        }
+
+        /**
+         * Add a network route to the VPN interface. Both IPv4 and IPv6
+         * routes are supported.
+         *
          * Adding a route implicitly allows traffic from that address family
          * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
          *
+         * Calling this method overrides previous calls to {@link #excludeRoute} for the same
+         * destination.
+         *
+         * If multiple routes match the packet destination, route with the longest prefix takes
+         * precedence.
+         *
          * @throws IllegalArgumentException if the route is invalid.
          */
         @NonNull
         public Builder addRoute(@NonNull InetAddress address, int prefixLength) {
-            check(address, prefixLength);
+            checkNonPrefixBytes(address, prefixLength);
 
-            int offset = prefixLength / 8;
-            byte[] bytes = address.getAddress();
-            if (offset < bytes.length) {
-                for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) {
-                    if (bytes[offset] != 0) {
-                        throw new IllegalArgumentException("Bad address");
-                    }
-                }
-            }
-            mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null, null,
-                RouteInfo.RTN_UNICAST));
-            mConfig.updateAllowedFamilies(address);
-            return this;
+            return addRoute(new IpPrefix(address, prefixLength), RouteInfo.RTN_UNICAST);
+        }
+
+        /**
+         * Add a network route to the VPN interface. Both IPv4 and IPv6
+         * routes are supported.
+         *
+         * Adding a route implicitly allows traffic from that address family
+         * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
+         *
+         * Calling this method overrides previous calls to {@link #excludeRoute} for the same
+         * destination.
+         *
+         * If multiple routes match the packet destination, route with the longest prefix takes
+         * precedence.
+         *
+         * @throws IllegalArgumentException if the route is invalid.
+         */
+        @NonNull
+        public Builder addRoute(@NonNull IpPrefix prefix) {
+            return addRoute(prefix, RouteInfo.RTN_UNICAST);
         }
 
         /**
@@ -611,6 +659,12 @@
          * Adding a route implicitly allows traffic from that address family
          * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
          *
+         * Calling this method overrides previous calls to {@link #excludeRoute} for the same
+         * destination.
+         *
+         * If multiple routes match the packet destination, route with the longest prefix takes
+         * precedence.
+         *
          * @throws IllegalArgumentException if the route is invalid.
          * @see #addRoute(InetAddress, int)
          */
@@ -620,6 +674,23 @@
         }
 
         /**
+         * Exclude a network route from the VPN interface. Both IPv4 and IPv6
+         * routes are supported.
+         *
+         * Calling this method overrides previous calls to {@link #addRoute} for the same
+         * destination.
+         *
+         * If multiple routes match the packet destination, route with the longest prefix takes
+         * precedence.
+         *
+         * @throws IllegalArgumentException if the route is invalid.
+         */
+        @NonNull
+        public Builder excludeRoute(@NonNull IpPrefix prefix) {
+            return addRoute(prefix, RouteInfo.RTN_THROW);
+        }
+
+        /**
          * Add a DNS server to the VPN connection. Both IPv4 and IPv6
          * addresses are supported. If none is set, the DNS servers of
          * the default network will be used.
@@ -900,5 +971,23 @@
                 throw new IllegalStateException(e);
             }
         }
+
+        private int findRouteIndexByDestination(RouteInfo route) {
+            for (int i = 0; i < mRoutes.size(); i++) {
+                if (mRoutes.get(i).getDestination().equals(route.getDestination())) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /**
+         * Method for testing, to observe mRoutes while builder is being used.
+         * @hide
+         */
+        @VisibleForTesting
+        public List<RouteInfo> routes() {
+            return Collections.unmodifiableList(mRoutes);
+        }
     }
 }
diff --git a/core/java/android/net/annotations/PolicyDirection.java b/core/java/android/net/annotations/PolicyDirection.java
index febd9b4..3f7521a 100644
--- a/core/java/android/net/annotations/PolicyDirection.java
+++ b/core/java/android/net/annotations/PolicyDirection.java
@@ -24,10 +24,6 @@
 
 /**
  * IPsec traffic direction.
- *
- * <p>Mainline modules cannot reference hidden @IntDef. Moving this annotation to a separate class
- * to allow others to statically include it.
- *
  * @hide
  */
 @IntDef(value = {IpSecManager.DIRECTION_IN, IpSecManager.DIRECTION_OUT})
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
new file mode 100644
index 0000000..9772bde
--- /dev/null
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.netstats;
+
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
+import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.TAG_NONE;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.NetworkIdentity;
+import android.net.NetworkStatsCollection;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.Environment;
+import android.util.AtomicFile;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastDataInput;
+
+import libcore.io.IoUtils;
+
+import java.io.BufferedInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Helper class to read old version of persistent network statistics.
+ *
+ * The implementation is intended to be modified by OEM partners to
+ * accommodate their custom changes.
+ *
+ * @hide
+ */
+@SystemApi(client = MODULE_LIBRARIES)
+public class NetworkStatsDataMigrationUtils {
+    /**
+     * Prefix of the files which are used to store per network interface statistics.
+     */
+    public static final String PREFIX_XT = "xt";
+    /**
+     * Prefix of the files which are used to store per uid statistics.
+     */
+    public static final String PREFIX_UID = "uid";
+    /**
+     * Prefix of the files which are used to store per uid tagged traffic statistics.
+     */
+    public static final String PREFIX_UID_TAG = "uid_tag";
+
+    private static final HashMap<String, String> sPrefixLegacyFileNameMap =
+            new HashMap<String, String>() {{
+                put(PREFIX_XT, "netstats_xt.bin");
+                put(PREFIX_UID, "netstats_uid.bin");
+                put(PREFIX_UID_TAG, "netstats_uid.bin");
+            }};
+
+    // These version constants are copied from NetworkStatsCollection/History, which is okay for
+    // OEMs to modify to adapt their own logic.
+    private static class CollectionVersion {
+        static final int VERSION_NETWORK_INIT = 1;
+
+        static final int VERSION_UID_INIT = 1;
+        static final int VERSION_UID_WITH_IDENT = 2;
+        static final int VERSION_UID_WITH_TAG = 3;
+        static final int VERSION_UID_WITH_SET = 4;
+
+        static final int VERSION_UNIFIED_INIT = 16;
+    }
+
+    private static class HistoryVersion {
+        static final int VERSION_INIT = 1;
+        static final int VERSION_ADD_PACKETS = 2;
+        static final int VERSION_ADD_ACTIVE = 3;
+    }
+
+    private static class IdentitySetVersion {
+        static final int VERSION_INIT = 1;
+        static final int VERSION_ADD_ROAMING = 2;
+        static final int VERSION_ADD_NETWORK_ID = 3;
+        static final int VERSION_ADD_METERED = 4;
+        static final int VERSION_ADD_DEFAULT_NETWORK = 5;
+        static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+    }
+
+    /**
+     * File header magic number: "ANET". The definition is copied from NetworkStatsCollection,
+     * but it is fine for OEM to re-define to their own value to adapt the legacy file reading
+     * logic.
+     */
+    private static final int FILE_MAGIC = 0x414E4554;
+    /** Default buffer size from BufferedInputStream */
+    private static final int BUFFER_SIZE = 8192;
+
+    // Constructing this object is not allowed.
+    private NetworkStatsDataMigrationUtils() {
+    }
+
+    // Used to read files at /data/system/netstats_*.bin.
+    @NonNull
+    private static File getPlatformSystemDir() {
+        return new File(Environment.getDataDirectory(), "system");
+    }
+
+    // Used to read files at /data/system/netstats/<tag>.<start>-<end>.
+    @NonNull
+    private static File getPlatformBaseDir() {
+        File baseDir = new File(getPlatformSystemDir(), "netstats");
+        baseDir.mkdirs();
+        return baseDir;
+    }
+
+    // Get /data/system/netstats_*.bin legacy files. Does not check for existence.
+    @NonNull
+    private static File getLegacyBinFileForPrefix(@NonNull String prefix) {
+        return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix));
+    }
+
+    // List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files.
+    @NonNull
+    private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) {
+        final ArrayList<File> list = new ArrayList<>();
+        final File platformFiles = new File(getPlatformBaseDir(), "netstats");
+        if (platformFiles.exists()) {
+            for (String name : platformFiles.list()) {
+                // Skip when prefix doesn't match.
+                if (!name.startsWith(prefix + ".")) continue;
+
+                list.add(new File(platformFiles, name));
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Read legacy persisted network stats from disk.
+     *
+     * This function provides the implementation to read legacy network stats
+     * from disk. It is used for migration of legacy network stats into the
+     * stats provided by the Connectivity module.
+     * This function needs to know about the previous format(s) of the network
+     * stats data that might be stored on this device so it can be read and
+     * conserved upon upgrade to Android 13 or above.
+     *
+     * This function will be called multiple times sequentially, all on the
+     * same thread, and will not be called multiple times concurrently. This
+     * function is expected to do a substantial amount of disk access, and
+     * doesn't need to return particularly fast, but the first boot after
+     * an upgrade to Android 13+ will be held until migration is done. As
+     * migration is only necessary once, after the first boot following the
+     * upgrade, this delay is not incurred.
+     *
+     * If this function fails in any way, it should throw an exception. If this
+     * happens, the system can't know about the data that was stored in the
+     * legacy files, but it will still count data usage happening on this
+     * session. On the next boot, the system will try migration again, and
+     * merge the returned data with the data used with the previous session.
+     * The system will only try the migration up to three (3) times. The remaining
+     * count is stored in the netstats_import_legacy_file_needed device config. The
+     * legacy data is never deleted by the mainline module to avoid any possible
+     * data loss.
+     *
+     * It is possible to set the netstats_import_legacy_file_needed device config
+     * to any positive integer to force the module to perform the migration. This
+     * can be achieved by calling the following command before rebooting :
+     *     adb shell device_config put connectivity netstats_import_legacy_file_needed 1
+     *
+     * The AOSP implementation provides code to read persisted network stats as
+     * they were written by AOSP prior to Android 13.
+     * OEMs who have used the AOSP implementation of persisting network stats
+     * to disk don't need to change anything.
+     * OEM that had modifications to this format should modify this function
+     * to read from their custom file format or locations if necessary.
+     *
+     * @param prefix         Type of data which is being read by the service.
+     * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+     * @return {@link NetworkStatsCollection} instance.
+     */
+    @NonNull
+    public static NetworkStatsCollection readPlatformCollection(
+            @NonNull String prefix, long bucketDuration) throws IOException {
+        final NetworkStatsCollection.Builder builder =
+                new NetworkStatsCollection.Builder(bucketDuration);
+
+        // Import /data/system/netstats_uid.bin legacy files if exists.
+        switch (prefix) {
+            case PREFIX_UID:
+            case PREFIX_UID_TAG:
+                final File uidFile = getLegacyBinFileForPrefix(prefix);
+                if (uidFile.exists()) {
+                    readLegacyUid(builder, uidFile, PREFIX_UID_TAG.equals(prefix) ? true : false);
+                }
+                break;
+            default:
+                // Ignore other types.
+        }
+
+        // Import /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files if exists.
+        final ArrayList<File> platformFiles = getPlatformFileListForPrefix(prefix);
+        for (final File platformFile : platformFiles) {
+            if (platformFile.exists()) {
+                readPlatformCollection(builder, platformFile);
+            }
+        }
+
+        return builder.build();
+    }
+
+    private static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder,
+            @NonNull File file) throws IOException {
+        final FileInputStream is = new FileInputStream(file);
+        final FastDataInput dataIn = new FastDataInput(is, BUFFER_SIZE);
+        try {
+            readPlatformCollection(builder, dataIn);
+        } finally {
+            IoUtils.closeQuietly(dataIn);
+        }
+    }
+
+    /**
+     * Helper function to read old version of NetworkStatsCollections that resided in the platform.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder,
+            @NonNull DataInput in) throws IOException {
+        // verify file magic header intact
+        final int magic = in.readInt();
+        if (magic != FILE_MAGIC) {
+            throw new ProtocolException("unexpected magic: " + magic);
+        }
+
+        final int version = in.readInt();
+        switch (version) {
+            case CollectionVersion.VERSION_UNIFIED_INIT: {
+                // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
+                final int identSize = in.readInt();
+                for (int i = 0; i < identSize; i++) {
+                    final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in);
+
+                    final int size = in.readInt();
+                    for (int j = 0; j < size; j++) {
+                        final int uid = in.readInt();
+                        final int set = in.readInt();
+                        final int tag = in.readInt();
+
+                        final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key(
+                                ident, uid, set, tag);
+                        final NetworkStatsHistory history = readPlatformHistory(in);
+                        builder.addEntry(key, history);
+                    }
+                }
+                break;
+            }
+            default: {
+                throw new ProtocolException("unexpected version: " + version);
+            }
+        }
+    }
+
+    // Copied from NetworkStatsHistory#DataStreamUtils.
+    private static long[] readFullLongArray(DataInput in) throws IOException {
+        final int size = in.readInt();
+        if (size < 0) throw new ProtocolException("negative array size");
+        final long[] values = new long[size];
+        for (int i = 0; i < values.length; i++) {
+            values[i] = in.readLong();
+        }
+        return values;
+    }
+
+    // Copied from NetworkStatsHistory#DataStreamUtils.
+    private static long[] readVarLongArray(@NonNull DataInput in) throws IOException {
+        final int size = in.readInt();
+        if (size == -1) return null;
+        if (size < 0) throw new ProtocolException("negative array size");
+        final long[] values = new long[size];
+        for (int i = 0; i < values.length; i++) {
+            values[i] = readVarLong(in);
+        }
+        return values;
+    }
+
+    /**
+     * Read variable-length {@link Long} using protobuf-style approach.
+     */
+    // Copied from NetworkStatsHistory#DataStreamUtils.
+    private static long readVarLong(DataInput in) throws IOException {
+        int shift = 0;
+        long result = 0;
+        while (shift < 64) {
+            byte b = in.readByte();
+            result |= (long) (b & 0x7F) << shift;
+            if ((b & 0x80) == 0) {
+                return result;
+            }
+            shift += 7;
+        }
+        throw new ProtocolException("malformed var long");
+    }
+
+    // Copied from NetworkIdentitySet.
+    private static String readOptionalString(DataInput in) throws IOException {
+        if (in.readByte() != 0) {
+            return in.readUTF();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * This is copied from NetworkStatsHistory#NetworkStatsHistory(DataInput in). But it is fine
+     * for OEM to re-write the logic to adapt the legacy file reading.
+     */
+    @NonNull
+    private static NetworkStatsHistory readPlatformHistory(@NonNull DataInput in)
+            throws IOException {
+        final long bucketDuration;
+        final long[] bucketStart;
+        final long[] rxBytes;
+        final long[] rxPackets;
+        final long[] txBytes;
+        final long[] txPackets;
+        final long[] operations;
+        final int bucketCount;
+        long[] activeTime = new long[0];
+
+        final int version = in.readInt();
+        switch (version) {
+            case HistoryVersion.VERSION_INIT: {
+                bucketDuration = in.readLong();
+                bucketStart = readFullLongArray(in);
+                rxBytes = readFullLongArray(in);
+                rxPackets = new long[bucketStart.length];
+                txBytes = readFullLongArray(in);
+                txPackets = new long[bucketStart.length];
+                operations = new long[bucketStart.length];
+                bucketCount = bucketStart.length;
+                break;
+            }
+            case HistoryVersion.VERSION_ADD_PACKETS:
+            case HistoryVersion.VERSION_ADD_ACTIVE: {
+                bucketDuration = in.readLong();
+                bucketStart = readVarLongArray(in);
+                activeTime = (version >= HistoryVersion.VERSION_ADD_ACTIVE)
+                        ? readVarLongArray(in)
+                        : new long[bucketStart.length];
+                rxBytes = readVarLongArray(in);
+                rxPackets = readVarLongArray(in);
+                txBytes = readVarLongArray(in);
+                txPackets = readVarLongArray(in);
+                operations = readVarLongArray(in);
+                bucketCount = bucketStart.length;
+                break;
+            }
+            default: {
+                throw new ProtocolException("unexpected version: " + version);
+            }
+        }
+
+        final NetworkStatsHistory.Builder historyBuilder =
+                new NetworkStatsHistory.Builder(bucketDuration, bucketCount);
+        for (int i = 0; i < bucketCount; i++) {
+            final NetworkStatsHistory.Entry entry = new NetworkStatsHistory.Entry(
+                    bucketStart[i], activeTime[i],
+                    rxBytes[i], rxPackets[i], txBytes[i], txPackets[i], operations[i]);
+            historyBuilder.addEntry(entry);
+        }
+
+        return historyBuilder.build();
+    }
+
+    @NonNull
+    private static Set<NetworkIdentity> readPlatformNetworkIdentitySet(@NonNull DataInput in)
+            throws IOException {
+        final int version = in.readInt();
+        final int size = in.readInt();
+        final Set<NetworkIdentity> set = new HashSet<>();
+        for (int i = 0; i < size; i++) {
+            if (version <= IdentitySetVersion.VERSION_INIT) {
+                final int ignored = in.readInt();
+            }
+            final int type = in.readInt();
+            final int ratType = in.readInt();
+            final String subscriberId = readOptionalString(in);
+            final String networkId;
+            if (version >= IdentitySetVersion.VERSION_ADD_NETWORK_ID) {
+                networkId = readOptionalString(in);
+            } else {
+                networkId = null;
+            }
+            final boolean roaming;
+            if (version >= IdentitySetVersion.VERSION_ADD_ROAMING) {
+                roaming = in.readBoolean();
+            } else {
+                roaming = false;
+            }
+
+            final boolean metered;
+            if (version >= IdentitySetVersion.VERSION_ADD_METERED) {
+                metered = in.readBoolean();
+            } else {
+                // If this is the old data and the type is mobile, treat it as metered. (Note that
+                // if this is a mobile network, TYPE_MOBILE is the only possible type that could be
+                // used.)
+                metered = (type == TYPE_MOBILE);
+            }
+
+            final boolean defaultNetwork;
+            if (version >= IdentitySetVersion.VERSION_ADD_DEFAULT_NETWORK) {
+                defaultNetwork = in.readBoolean();
+            } else {
+                defaultNetwork = true;
+            }
+
+            final int oemNetCapabilities;
+            if (version >= IdentitySetVersion.VERSION_ADD_OEM_MANAGED_NETWORK) {
+                oemNetCapabilities = in.readInt();
+            } else {
+                oemNetCapabilities = NetworkTemplate.OEM_MANAGED_NO;
+            }
+
+            // Legacy files might contain TYPE_MOBILE_* types which were deprecated in later
+            // releases. For backward compatibility, record them as TYPE_MOBILE instead.
+            final int collapsedLegacyType = getCollapsedLegacyType(type);
+            final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
+                    .setType(collapsedLegacyType)
+                    .setSubscriberId(subscriberId)
+                    .setWifiNetworkKey(networkId)
+                    .setRoaming(roaming).setMetered(metered)
+                    .setDefaultNetwork(defaultNetwork)
+                    .setOemManaged(oemNetCapabilities);
+            if (type == TYPE_MOBILE && ratType != NetworkTemplate.NETWORK_TYPE_ALL) {
+                builder.setRatType(ratType);
+            }
+            set.add(builder.build());
+        }
+        return set;
+    }
+
+    private static int getCollapsedLegacyType(int networkType) {
+        // The constants are referenced from ConnectivityManager#TYPE_MOBILE_*.
+        switch (networkType) {
+            case TYPE_MOBILE:
+            case TYPE_MOBILE_SUPL:
+            case TYPE_MOBILE_MMS:
+            case TYPE_MOBILE_DUN:
+            case TYPE_MOBILE_HIPRI:
+            case 10 /* TYPE_MOBILE_FOTA */:
+            case 11 /* TYPE_MOBILE_IMS */:
+            case 12 /* TYPE_MOBILE_CBS */:
+            case 14 /* TYPE_MOBILE_IA */:
+            case 15 /* TYPE_MOBILE_EMERGENCY */:
+                return TYPE_MOBILE;
+        }
+        return networkType;
+    }
+
+    private static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder,
+            @NonNull File uidFile, boolean onlyTaggedData) throws IOException {
+        final AtomicFile inputFile = new AtomicFile(uidFile);
+        DataInputStream in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
+        try {
+            readLegacyUid(builder, in, onlyTaggedData);
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
+    /**
+     * Read legacy Uid statistics file format into the collection.
+     *
+     * This is copied from {@code NetworkStatsCollection#readLegacyUid}.
+     * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
+     *
+     * @param taggedData whether to read tagged data. For legacy uid files, the tagged
+     *                   data was stored in the same binary file with non-tagged data.
+     *                   But in later releases, these data should be kept in different
+     *                   recorders.
+     * @hide
+     */
+    @VisibleForTesting
+    public static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder,
+            @NonNull DataInput in, boolean taggedData) throws IOException {
+        try {
+            // verify file magic header intact
+            final int magic = in.readInt();
+            if (magic != FILE_MAGIC) {
+                throw new ProtocolException("unexpected magic: " + magic);
+            }
+
+            final int version = in.readInt();
+            switch (version) {
+                case CollectionVersion.VERSION_UID_INIT: {
+                    // uid := size *(UID NetworkStatsHistory)
+                    // drop this data version, since we don't have a good
+                    // mapping into NetworkIdentitySet.
+                    break;
+                }
+                case CollectionVersion.VERSION_UID_WITH_IDENT: {
+                    // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
+                    // drop this data version, since this version only existed
+                    // for a short time.
+                    break;
+                }
+                case CollectionVersion.VERSION_UID_WITH_TAG:
+                case CollectionVersion.VERSION_UID_WITH_SET: {
+                    // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
+                    final int identSize = in.readInt();
+                    for (int i = 0; i < identSize; i++) {
+                        final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in);
+
+                        final int size = in.readInt();
+                        for (int j = 0; j < size; j++) {
+                            final int uid = in.readInt();
+                            final int set = (version >= CollectionVersion.VERSION_UID_WITH_SET)
+                                    ? in.readInt()
+                                    : SET_DEFAULT;
+                            final int tag = in.readInt();
+
+                            final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key(
+                                    ident, uid, set, tag);
+                            final NetworkStatsHistory history = readPlatformHistory(in);
+
+                            if ((tag == TAG_NONE) != taggedData) {
+                                builder.addEntry(key, history);
+                            }
+                        }
+                    }
+                    break;
+                }
+                default: {
+                    throw new ProtocolException("unknown version: " + version);
+                }
+            }
+        } catch (FileNotFoundException | ProtocolException e) {
+            // missing stats is okay, probably first boot
+        }
+    }
+}
diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
index 125b573..69e6313 100644
--- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
@@ -63,13 +63,22 @@
     private final int mOpportunisticMatchCriteria;
 
     private VcnCellUnderlyingNetworkTemplate(
-            int networkQuality,
             int meteredMatchCriteria,
+            int minEntryUpstreamBandwidthKbps,
+            int minExitUpstreamBandwidthKbps,
+            int minEntryDownstreamBandwidthKbps,
+            int minExitDownstreamBandwidthKbps,
             Set<String> allowedNetworkPlmnIds,
             Set<Integer> allowedSpecificCarrierIds,
             int roamingMatchCriteria,
             int opportunisticMatchCriteria) {
-        super(NETWORK_PRIORITY_TYPE_CELL, networkQuality, meteredMatchCriteria);
+        super(
+                NETWORK_PRIORITY_TYPE_CELL,
+                meteredMatchCriteria,
+                minEntryUpstreamBandwidthKbps,
+                minExitUpstreamBandwidthKbps,
+                minEntryDownstreamBandwidthKbps,
+                minExitDownstreamBandwidthKbps);
         mAllowedNetworkPlmnIds = new ArraySet<>(allowedNetworkPlmnIds);
         mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
         mRoamingMatchCriteria = roamingMatchCriteria;
@@ -109,9 +118,17 @@
             @NonNull PersistableBundle in) {
         Objects.requireNonNull(in, "PersistableBundle is null");
 
-        final int networkQuality = in.getInt(NETWORK_QUALITY_KEY);
         final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY);
 
+        final int minEntryUpstreamBandwidthKbps =
+                in.getInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+        final int minExitUpstreamBandwidthKbps =
+                in.getInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+        final int minEntryDownstreamBandwidthKbps =
+                in.getInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+        final int minExitDownstreamBandwidthKbps =
+                in.getInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+
         final PersistableBundle plmnIdsBundle =
                 in.getPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY);
         Objects.requireNonNull(plmnIdsBundle, "plmnIdsBundle is null");
@@ -131,8 +148,11 @@
         final int opportunisticMatchCriteria = in.getInt(OPPORTUNISTIC_MATCH_KEY);
 
         return new VcnCellUnderlyingNetworkTemplate(
-                networkQuality,
                 meteredMatchCriteria,
+                minEntryUpstreamBandwidthKbps,
+                minExitUpstreamBandwidthKbps,
+                minEntryDownstreamBandwidthKbps,
+                minExitDownstreamBandwidthKbps,
                 allowedNetworkPlmnIds,
                 allowedSpecificCarrierIds,
                 roamingMatchCriteria,
@@ -243,7 +263,6 @@
 
     /** This class is used to incrementally build VcnCellUnderlyingNetworkTemplate objects. */
     public static final class Builder {
-        private int mNetworkQuality = NETWORK_QUALITY_ANY;
         private int mMeteredMatchCriteria = MATCH_ANY;
 
         @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
@@ -252,29 +271,15 @@
         private int mRoamingMatchCriteria = MATCH_ANY;
         private int mOpportunisticMatchCriteria = MATCH_ANY;
 
+        private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+        private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+        private int mMinEntryDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+        private int mMinExitDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+
         /** Construct a Builder object. */
         public Builder() {}
 
         /**
-         * Set the required network quality to match this template.
-         *
-         * <p>Network quality is a aggregation of multiple signals that reflect the network link
-         * metrics. For example, the network validation bit (see {@link
-         * NetworkCapabilities#NET_CAPABILITY_VALIDATED}), estimated first hop transport bandwidth
-         * and signal strength.
-         *
-         * @param networkQuality the required network quality. Defaults to NETWORK_QUALITY_ANY
-         * @hide
-         */
-        @NonNull
-        public Builder setNetworkQuality(@NetworkQuality int networkQuality) {
-            validateNetworkQuality(networkQuality);
-
-            mNetworkQuality = networkQuality;
-            return this;
-        }
-
-        /**
          * Set the matching criteria for metered networks.
          *
          * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one
@@ -369,12 +374,92 @@
             return this;
         }
 
+        /**
+         * Set the minimum upstream bandwidths that this template will match.
+         *
+         * <p>This template will not match a network that does not provide at least the bandwidth
+         * passed as the entry bandwidth, except in the case that the network is selected as the VCN
+         * Gateway Connection's underlying network, where it will continue to match until the
+         * bandwidth drops under the exit bandwidth.
+         *
+         * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
+         * invalid case where a network fulfills the entry criteria, but at the same time fails the
+         * exit criteria.
+         *
+         * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
+         * {@link NetworkCapabilities}. The provided estimates will be used without modification.
+         *
+         * @param minEntryUpstreamBandwidthKbps the minimum accepted upstream bandwidth for networks
+         *     that ARE NOT the already-selected underlying network, or {@code 0} to disable this
+         *     requirement. Disabled by default.
+         * @param minExitUpstreamBandwidthKbps the minimum accepted upstream bandwidth for a network
+         *     that IS the already-selected underlying network, or {@code 0} to disable this
+         *     requirement. Disabled by default.
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        // The getter for the two integers are separated, and in the superclass. Please see {@link
+        // VcnUnderlyingNetworkTemplate#getMinEntryUpstreamBandwidthKbps()} and {@link
+        // VcnUnderlyingNetworkTemplate#getMinExitUpstreamBandwidthKbps()}
+        @SuppressLint("MissingGetterMatchingBuilder")
+        public Builder setMinUpstreamBandwidthKbps(
+                int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps) {
+            validateMinBandwidthKbps(minEntryUpstreamBandwidthKbps, minExitUpstreamBandwidthKbps);
+
+            mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps;
+            mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps;
+
+            return this;
+        }
+
+        /**
+         * Set the minimum upstream bandwidths that this template will match.
+         *
+         * <p>This template will not match a network that does not provide at least the bandwidth
+         * passed as the entry bandwidth, except in the case that the network is selected as the VCN
+         * Gateway Connection's underlying network, where it will continue to match until the
+         * bandwidth drops under the exit bandwidth.
+         *
+         * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
+         * invalid case where a network fulfills the entry criteria, but at the same time fails the
+         * exit criteria.
+         *
+         * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
+         * {@link NetworkCapabilities}. The provided estimates will be used without modification.
+         *
+         * @param minEntryDownstreamBandwidthKbps the minimum accepted downstream bandwidth for
+         *     networks that ARE NOT the already-selected underlying network, or {@code 0} to
+         *     disable this requirement. Disabled by default.
+         * @param minExitDownstreamBandwidthKbps the minimum accepted downstream bandwidth for a
+         *     network that IS the already-selected underlying network, or {@code 0} to disable this
+         *     requirement. Disabled by default.
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        // The getter for the two integers are separated, and in the superclass. Please see {@link
+        // VcnUnderlyingNetworkTemplate#getMinEntryDownstreamBandwidthKbps()} and {@link
+        // VcnUnderlyingNetworkTemplate#getMinExitDownstreamBandwidthKbps()}
+        @SuppressLint("MissingGetterMatchingBuilder")
+        public Builder setMinDownstreamBandwidthKbps(
+                int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps) {
+            validateMinBandwidthKbps(
+                    minEntryDownstreamBandwidthKbps, minExitDownstreamBandwidthKbps);
+
+            mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps;
+            mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps;
+
+            return this;
+        }
+
         /** Build the VcnCellUnderlyingNetworkTemplate. */
         @NonNull
         public VcnCellUnderlyingNetworkTemplate build() {
             return new VcnCellUnderlyingNetworkTemplate(
-                    mNetworkQuality,
                     mMeteredMatchCriteria,
+                    mMinEntryUpstreamBandwidthKbps,
+                    mMinExitUpstreamBandwidthKbps,
+                    mMinEntryDownstreamBandwidthKbps,
+                    mMinExitDownstreamBandwidthKbps,
                     mAllowedNetworkPlmnIds,
                     mAllowedSpecificCarrierIds,
                     mRoamingMatchCriteria,
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 92956e8..2339656 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -17,7 +17,6 @@
 
 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility;
 
@@ -169,18 +168,15 @@
     static {
         DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
                 new VcnCellUnderlyingNetworkTemplate.Builder()
-                        .setNetworkQuality(NETWORK_QUALITY_OK)
                         .setOpportunistic(MATCH_REQUIRED)
                         .build());
 
         DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
                 new VcnWifiUnderlyingNetworkTemplate.Builder()
-                        .setNetworkQuality(NETWORK_QUALITY_OK)
                         .build());
 
         DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
                 new VcnCellUnderlyingNetworkTemplate.Builder()
-                        .setNetworkQuality(NETWORK_QUALITY_OK)
                         .build());
     }
 
@@ -553,8 +549,8 @@
          * networks, a network will be chosen arbitrarily amongst the networks matching the highest
          * priority rule.
          *
-         * <p>If all networks fail to match the rules provided, an underlying network will still be
-         * selected (at random if necessary).
+         * <p>If all networks fail to match the rules provided, a carrier-owned underlying network
+         * will still be selected (if available, at random if necessary).
          *
          * @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are
          *     ordered from most to least preferred, or an empty list to use the default
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
index 60fc936..3a9ca3e 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
@@ -48,23 +48,6 @@
     /** @hide */
     static final int NETWORK_PRIORITY_TYPE_CELL = 2;
 
-    /** Denotes that any network quality is acceptable. @hide */
-    public static final int NETWORK_QUALITY_ANY = 0;
-    /** Denotes that network quality needs to be OK. @hide */
-    public static final int NETWORK_QUALITY_OK = 100000;
-
-    private static final SparseArray<String> NETWORK_QUALITY_TO_STRING_MAP = new SparseArray<>();
-
-    static {
-        NETWORK_QUALITY_TO_STRING_MAP.put(NETWORK_QUALITY_ANY, "NETWORK_QUALITY_ANY");
-        NETWORK_QUALITY_TO_STRING_MAP.put(NETWORK_QUALITY_OK, "NETWORK_QUALITY_OK");
-    }
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({NETWORK_QUALITY_OK, NETWORK_QUALITY_ANY})
-    public @interface NetworkQuality {}
-
     /**
      * Used to configure the matching criteria of a network characteristic. This may include network
      * capabilities, or cellular subscription information. Denotes that networks with or without the
@@ -103,44 +86,73 @@
     private final int mNetworkPriorityType;
 
     /** @hide */
-    static final String NETWORK_QUALITY_KEY = "mNetworkQuality";
-
-    private final int mNetworkQuality;
-
-    /** @hide */
     static final String METERED_MATCH_KEY = "mMeteredMatchCriteria";
 
     private final int mMeteredMatchCriteria;
 
     /** @hide */
+    public static final int DEFAULT_MIN_BANDWIDTH_KBPS = 0;
+
+    /** @hide */
+    static final String MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY = "mMinEntryUpstreamBandwidthKbps";
+
+    private final int mMinEntryUpstreamBandwidthKbps;
+
+    /** @hide */
+    static final String MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY = "mMinExitUpstreamBandwidthKbps";
+
+    private final int mMinExitUpstreamBandwidthKbps;
+
+    /** @hide */
+    static final String MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY =
+            "mMinEntryDownstreamBandwidthKbps";
+
+    private final int mMinEntryDownstreamBandwidthKbps;
+
+    /** @hide */
+    static final String MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY = "mMinExitDownstreamBandwidthKbps";
+
+    private final int mMinExitDownstreamBandwidthKbps;
+
+    /** @hide */
     VcnUnderlyingNetworkTemplate(
-            int networkPriorityType, int networkQuality, int meteredMatchCriteria) {
+            int networkPriorityType,
+            int meteredMatchCriteria,
+            int minEntryUpstreamBandwidthKbps,
+            int minExitUpstreamBandwidthKbps,
+            int minEntryDownstreamBandwidthKbps,
+            int minExitDownstreamBandwidthKbps) {
         mNetworkPriorityType = networkPriorityType;
-        mNetworkQuality = networkQuality;
         mMeteredMatchCriteria = meteredMatchCriteria;
+        mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps;
+        mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps;
+        mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps;
+        mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps;
     }
 
     /** @hide */
-    static void validateNetworkQuality(int networkQuality) {
+    static void validateMatchCriteria(int matchCriteria, String matchingCapability) {
         Preconditions.checkArgument(
-                networkQuality == NETWORK_QUALITY_ANY || networkQuality == NETWORK_QUALITY_OK,
-                "Invalid networkQuality:" + networkQuality);
+                MATCH_CRITERIA_TO_STRING_MAP.contains(matchCriteria),
+                "Invalid matching criteria: " + matchCriteria + " for " + matchingCapability);
     }
 
     /** @hide */
-    static void validateMatchCriteria(int meteredMatchCriteria, String matchingCapability) {
+    static void validateMinBandwidthKbps(int minEntryBandwidth, int minExitBandwidth) {
         Preconditions.checkArgument(
-                MATCH_CRITERIA_TO_STRING_MAP.contains(meteredMatchCriteria),
-                "Invalid matching criteria: "
-                        + meteredMatchCriteria
-                        + " for "
-                        + matchingCapability);
+                minEntryBandwidth >= 0, "Invalid minEntryBandwidth, must be >= 0");
+        Preconditions.checkArgument(
+                minExitBandwidth >= 0, "Invalid minExitBandwidth, must be >= 0");
+        Preconditions.checkArgument(
+                minEntryBandwidth >= minExitBandwidth,
+                "Minimum entry bandwidth must be >= exit bandwidth");
     }
 
     /** @hide */
     protected void validate() {
-        validateNetworkQuality(mNetworkQuality);
         validateMatchCriteria(mMeteredMatchCriteria, "mMeteredMatchCriteria");
+        validateMinBandwidthKbps(mMinEntryUpstreamBandwidthKbps, mMinExitUpstreamBandwidthKbps);
+        validateMinBandwidthKbps(mMinEntryDownstreamBandwidthKbps, mMinExitDownstreamBandwidthKbps);
     }
 
     /** @hide */
@@ -168,15 +180,24 @@
         final PersistableBundle result = new PersistableBundle();
 
         result.putInt(NETWORK_PRIORITY_TYPE_KEY, mNetworkPriorityType);
-        result.putInt(NETWORK_QUALITY_KEY, mNetworkQuality);
         result.putInt(METERED_MATCH_KEY, mMeteredMatchCriteria);
+        result.putInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, mMinEntryUpstreamBandwidthKbps);
+        result.putInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, mMinExitUpstreamBandwidthKbps);
+        result.putInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, mMinEntryDownstreamBandwidthKbps);
+        result.putInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, mMinExitDownstreamBandwidthKbps);
 
         return result;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mNetworkPriorityType, mNetworkQuality, mMeteredMatchCriteria);
+        return Objects.hash(
+                mNetworkPriorityType,
+                mMeteredMatchCriteria,
+                mMinEntryUpstreamBandwidthKbps,
+                mMinExitUpstreamBandwidthKbps,
+                mMinEntryDownstreamBandwidthKbps,
+                mMinExitDownstreamBandwidthKbps);
     }
 
     @Override
@@ -187,8 +208,11 @@
 
         final VcnUnderlyingNetworkTemplate rhs = (VcnUnderlyingNetworkTemplate) other;
         return mNetworkPriorityType == rhs.mNetworkPriorityType
-                && mNetworkQuality == rhs.mNetworkQuality
-                && mMeteredMatchCriteria == rhs.mMeteredMatchCriteria;
+                && mMeteredMatchCriteria == rhs.mMeteredMatchCriteria
+                && mMinEntryUpstreamBandwidthKbps == rhs.mMinEntryUpstreamBandwidthKbps
+                && mMinExitUpstreamBandwidthKbps == rhs.mMinExitUpstreamBandwidthKbps
+                && mMinEntryDownstreamBandwidthKbps == rhs.mMinEntryDownstreamBandwidthKbps
+                && mMinExitDownstreamBandwidthKbps == rhs.mMinExitDownstreamBandwidthKbps;
     }
 
     /** @hide */
@@ -197,8 +221,8 @@
     }
 
     /** @hide */
-    static String getMatchCriteriaString(int meteredMatchCriteria) {
-        return getNameString(MATCH_CRITERIA_TO_STRING_MAP, meteredMatchCriteria);
+    static String getMatchCriteriaString(int matchCriteria) {
+        return getNameString(MATCH_CRITERIA_TO_STRING_MAP, matchCriteria);
     }
 
     /** @hide */
@@ -213,34 +237,63 @@
         pw.println(this.getClass().getSimpleName() + ":");
         pw.increaseIndent();
 
-        pw.println(
-                "mNetworkQuality: "
-                        + getNameString(NETWORK_QUALITY_TO_STRING_MAP, mNetworkQuality));
         pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria));
+        pw.println("mMinEntryUpstreamBandwidthKbps: " + mMinEntryUpstreamBandwidthKbps);
+        pw.println("mMinExitUpstreamBandwidthKbps: " + mMinExitUpstreamBandwidthKbps);
+        pw.println("mMinEntryDownstreamBandwidthKbps: " + mMinEntryDownstreamBandwidthKbps);
+        pw.println("mMinExitDownstreamBandwidthKbps: " + mMinExitDownstreamBandwidthKbps);
         dumpTransportSpecificFields(pw);
 
         pw.decreaseIndent();
     }
 
     /**
-     * Retrieve the required network quality to match this template.
-     *
-     * @see Builder#setNetworkQuality(int)
-     * @hide
-     */
-    @NetworkQuality
-    public int getNetworkQuality() {
-        return mNetworkQuality;
-    }
-
-    /**
      * Return the matching criteria for metered networks.
      *
      * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMetered(int)
      * @see VcnCellUnderlyingNetworkTemplate.Builder#setMetered(int)
      */
-    @MatchCriteria
     public int getMetered() {
         return mMeteredMatchCriteria;
     }
+
+    /**
+     * Returns the minimum entry upstream bandwidth allowed by this template.
+     *
+     * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
+     * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
+     */
+    public int getMinEntryUpstreamBandwidthKbps() {
+        return mMinEntryUpstreamBandwidthKbps;
+    }
+
+    /**
+     * Returns the minimum exit upstream bandwidth allowed by this template.
+     *
+     * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
+     * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinUpstreamBandwidthKbps(int, int)
+     */
+    public int getMinExitUpstreamBandwidthKbps() {
+        return mMinExitUpstreamBandwidthKbps;
+    }
+
+    /**
+     * Returns the minimum entry downstream bandwidth allowed by this template.
+     *
+     * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
+     * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
+     */
+    public int getMinEntryDownstreamBandwidthKbps() {
+        return mMinEntryDownstreamBandwidthKbps;
+    }
+
+    /**
+     * Returns the minimum exit downstream bandwidth allowed by this template.
+     *
+     * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
+     * @see VcnCellUnderlyingNetworkTemplate.Builder#setMinDownstreamBandwidthKbps(int, int)
+     */
+    public int getMinExitDownstreamBandwidthKbps() {
+        return mMinExitDownstreamBandwidthKbps;
+    }
 }
diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
index 272ca9d..23a07ab 100644
--- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
@@ -46,8 +46,19 @@
     @Nullable private final Set<String> mSsids;
 
     private VcnWifiUnderlyingNetworkTemplate(
-            int networkQuality, int meteredMatchCriteria, Set<String> ssids) {
-        super(NETWORK_PRIORITY_TYPE_WIFI, networkQuality, meteredMatchCriteria);
+            int meteredMatchCriteria,
+            int minEntryUpstreamBandwidthKbps,
+            int minExitUpstreamBandwidthKbps,
+            int minEntryDownstreamBandwidthKbps,
+            int minExitDownstreamBandwidthKbps,
+            Set<String> ssids) {
+        super(
+                NETWORK_PRIORITY_TYPE_WIFI,
+                meteredMatchCriteria,
+                minEntryUpstreamBandwidthKbps,
+                minExitUpstreamBandwidthKbps,
+                minEntryDownstreamBandwidthKbps,
+                minExitDownstreamBandwidthKbps);
         mSsids = new ArraySet<>(ssids);
 
         validate();
@@ -75,15 +86,29 @@
             @NonNull PersistableBundle in) {
         Objects.requireNonNull(in, "PersistableBundle is null");
 
-        final int networkQuality = in.getInt(NETWORK_QUALITY_KEY);
         final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY);
 
+        final int minEntryUpstreamBandwidthKbps =
+                in.getInt(MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+        final int minExitUpstreamBandwidthKbps =
+                in.getInt(MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+        final int minEntryDownstreamBandwidthKbps =
+                in.getInt(MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+        final int minExitDownstreamBandwidthKbps =
+                in.getInt(MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS_KEY, DEFAULT_MIN_BANDWIDTH_KBPS);
+
         final PersistableBundle ssidsBundle = in.getPersistableBundle(SSIDS_KEY);
         Objects.requireNonNull(ssidsBundle, "ssidsBundle is null");
         final Set<String> ssids =
                 new ArraySet<String>(
                         PersistableBundleUtils.toList(ssidsBundle, STRING_DESERIALIZER));
-        return new VcnWifiUnderlyingNetworkTemplate(networkQuality, meteredMatchCriteria, ssids);
+        return new VcnWifiUnderlyingNetworkTemplate(
+                meteredMatchCriteria,
+                minEntryUpstreamBandwidthKbps,
+                minExitUpstreamBandwidthKbps,
+                minEntryDownstreamBandwidthKbps,
+                minExitDownstreamBandwidthKbps,
+                ssids);
     }
 
     /** @hide */
@@ -137,33 +162,18 @@
 
     /** This class is used to incrementally build VcnWifiUnderlyingNetworkTemplate objects. */
     public static final class Builder {
-        private int mNetworkQuality = NETWORK_QUALITY_ANY;
         private int mMeteredMatchCriteria = MATCH_ANY;
         @NonNull private final Set<String> mSsids = new ArraySet<>();
 
+        private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+        private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+        private int mMinEntryDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+        private int mMinExitDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;
+
         /** Construct a Builder object. */
         public Builder() {}
 
         /**
-         * Set the required network quality to match this template.
-         *
-         * <p>Network quality is a aggregation of multiple signals that reflect the network link
-         * metrics. For example, the network validation bit (see {@link
-         * NetworkCapabilities#NET_CAPABILITY_VALIDATED}), estimated first hop transport bandwidth
-         * and signal strength.
-         *
-         * @param networkQuality the required network quality. Defaults to NETWORK_QUALITY_ANY
-         * @hide
-         */
-        @NonNull
-        public Builder setNetworkQuality(@NetworkQuality int networkQuality) {
-            validateNetworkQuality(networkQuality);
-
-            mNetworkQuality = networkQuality;
-            return this;
-        }
-
-        /**
          * Set the matching criteria for metered networks.
          *
          * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one
@@ -200,11 +210,93 @@
             return this;
         }
 
+        /**
+         * Set the minimum upstream bandwidths that this template will match.
+         *
+         * <p>This template will not match a network that does not provide at least the bandwidth
+         * passed as the entry bandwidth, except in the case that the network is selected as the VCN
+         * Gateway Connection's underlying network, where it will continue to match until the
+         * bandwidth drops under the exit bandwidth.
+         *
+         * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
+         * invalid case where a network fulfills the entry criteria, but at the same time fails the
+         * exit criteria.
+         *
+         * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
+         * {@link NetworkCapabilities}. The provided estimates will be used without modification.
+         *
+         * @param minEntryUpstreamBandwidthKbps the minimum accepted upstream bandwidth for networks
+         *     that ARE NOT the already-selected underlying network, or {@code 0} to disable this
+         *     requirement. Disabled by default.
+         * @param minExitUpstreamBandwidthKbps the minimum accepted upstream bandwidth for a network
+         *     that IS the already-selected underlying network, or {@code 0} to disable this
+         *     requirement. Disabled by default.
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        // The getter for the two integers are separated, and in the superclass. Please see {@link
+        // VcnUnderlyingNetworkTemplate#getMinEntryUpstreamBandwidthKbps()} and {@link
+        // VcnUnderlyingNetworkTemplate#getMinExitUpstreamBandwidthKbps()}
+        @SuppressLint("MissingGetterMatchingBuilder")
+        public Builder setMinUpstreamBandwidthKbps(
+                int minEntryUpstreamBandwidthKbps, int minExitUpstreamBandwidthKbps) {
+            validateMinBandwidthKbps(minEntryUpstreamBandwidthKbps, minExitUpstreamBandwidthKbps);
+
+            mMinEntryUpstreamBandwidthKbps = minEntryUpstreamBandwidthKbps;
+            mMinExitUpstreamBandwidthKbps = minExitUpstreamBandwidthKbps;
+
+            return this;
+        }
+
+        /**
+         * Set the minimum upstream bandwidths that this template will match.
+         *
+         * <p>This template will not match a network that does not provide at least the bandwidth
+         * passed as the entry bandwidth, except in the case that the network is selected as the VCN
+         * Gateway Connection's underlying network, where it will continue to match until the
+         * bandwidth drops under the exit bandwidth.
+         *
+         * <p>The entry criteria MUST be greater than, or equal to the exit criteria to avoid the
+         * invalid case where a network fulfills the entry criteria, but at the same time fails the
+         * exit criteria.
+         *
+         * <p>Estimated bandwidth of a network is provided by the transport layer, and reported in
+         * {@link NetworkCapabilities}. The provided estimates will be used without modification.
+         *
+         * @param minEntryDownstreamBandwidthKbps the minimum accepted downstream bandwidth for
+         *     networks that ARE NOT the already-selected underlying network, or {@code 0} to
+         *     disable this requirement. Disabled by default.
+         * @param minExitDownstreamBandwidthKbps the minimum accepted downstream bandwidth for a
+         *     network that IS the already-selected underlying network, or {@code 0} to disable this
+         *     requirement. Disabled by default.
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        // The getter for the two integers are separated, and in the superclass. Please see {@link
+        // VcnUnderlyingNetworkTemplate#getMinEntryDownstreamBandwidthKbps()} and {@link
+        // VcnUnderlyingNetworkTemplate#getMinExitDownstreamBandwidthKbps()}
+        @SuppressLint("MissingGetterMatchingBuilder")
+        public Builder setMinDownstreamBandwidthKbps(
+                int minEntryDownstreamBandwidthKbps, int minExitDownstreamBandwidthKbps) {
+            validateMinBandwidthKbps(
+                    minEntryDownstreamBandwidthKbps, minExitDownstreamBandwidthKbps);
+
+            mMinEntryDownstreamBandwidthKbps = minEntryDownstreamBandwidthKbps;
+            mMinExitDownstreamBandwidthKbps = minExitDownstreamBandwidthKbps;
+
+            return this;
+        }
+
         /** Build the VcnWifiUnderlyingNetworkTemplate. */
         @NonNull
         public VcnWifiUnderlyingNetworkTemplate build() {
             return new VcnWifiUnderlyingNetworkTemplate(
-                    mNetworkQuality, mMeteredMatchCriteria, mSsids);
+                    mMeteredMatchCriteria,
+                    mMinEntryUpstreamBandwidthKbps,
+                    mMinExitUpstreamBandwidthKbps,
+                    mMinEntryDownstreamBandwidthKbps,
+                    mMinExitDownstreamBandwidthKbps,
+                    mSsids);
         }
     }
 }
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 0a9fe90..9a780c8 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -84,13 +84,6 @@
     public static final String EXTRA_SERVICE_COMPONENT = "component";
 
     /**
-     * The caller userId extra for {@link #ACTION_CHANGE_DEFAULT}.
-     *
-     * @see #ACTION_CHANGE_DEFAULT
-     */
-    public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
-
-    /**
      * Category used for NFC payment services.
      */
     public static final String CATEGORY_PAYMENT = "payment";
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index ad3de25..244335d 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -31,7 +31,7 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Set;
-import java.util.function.Supplier;
+import java.util.function.Function;
 
 /**
  * A mapping from String keys to values of various types. In most cases, you
@@ -252,11 +252,10 @@
         if (size == 0) {
             return null;
         }
-        Object o = getValueAt(0);
         try {
-            return (String) o;
-        } catch (ClassCastException e) {
-            typeWarning("getPairValue()", o, "String", e);
+            return getValueAt(0, String.class);
+        } catch (ClassCastException | BadParcelableException e) {
+            typeWarning("getPairValue()", /* value */ null, "String", e);
             return null;
         }
     }
@@ -309,7 +308,7 @@
                 }
                 for (int i = 0, n = mMap.size(); i < n; i++) {
                     // Triggers deserialization of i-th item, if needed
-                    getValueAt(i);
+                    getValueAt(i, /* clazz */ null);
                 }
             }
         }
@@ -324,8 +323,21 @@
      * @hide
      */
     final Object getValue(String key) {
+        return getValue(key, /* clazz */ null);
+    }
+
+    /**
+     * Returns the value for key {@code key} for expected return type {@param clazz} (or {@code
+     * null} for no type check).
+     *
+     * This call should always be made after {@link #unparcel()} or inside a lock after making sure
+     * {@code mMap} is not null.
+     *
+     * @hide
+     */
+    final <T> T getValue(String key, @Nullable Class<T> clazz) {
         int i = mMap.indexOfKey(key);
-        return (i >= 0) ? getValueAt(i) : null;
+        return (i >= 0) ? getValueAt(i, clazz) : null;
     }
 
     /**
@@ -336,11 +348,12 @@
      *
      * @hide
      */
-    final Object getValueAt(int i) {
+    @SuppressWarnings("unchecked")
+    final <T> T getValueAt(int i, @Nullable Class<T> clazz) {
         Object object = mMap.valueAt(i);
-        if (object instanceof Supplier<?>) {
+        if (object instanceof Function<?, ?>) {
             try {
-                object = ((Supplier<?>) object).get();
+                object = ((Function<Class<?>, ?>) object).apply(clazz);
             } catch (BadParcelableException e) {
                 if (sShouldDefuse) {
                     Log.w(TAG, "Failed to parse item " + mMap.keyAt(i) + ", returning null.", e);
@@ -351,7 +364,7 @@
             }
             mMap.setValueAt(i, object);
         }
-        return object;
+        return (clazz != null) ? clazz.cast(object) : (T) object;
     }
 
     private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel,
@@ -528,7 +541,7 @@
         } 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
+            // deserialized yet, it's a function object (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).
@@ -982,15 +995,19 @@
     }
 
     // Log a message if the value was non-null but not of the expected type
-    void typeWarning(String key, Object value, String className,
-            Object defaultValue, ClassCastException e) {
+    void typeWarning(String key, @Nullable Object value, String className,
+            Object defaultValue, RuntimeException e) {
         StringBuilder sb = new StringBuilder();
         sb.append("Key ");
         sb.append(key);
         sb.append(" expected ");
         sb.append(className);
-        sb.append(" but value was a ");
-        sb.append(value.getClass().getName());
+        if (value != null) {
+            sb.append(" but value was a ");
+            sb.append(value.getClass().getName());
+        } else {
+            sb.append(" but value was of a different type ");
+        }
         sb.append(".  The default value ");
         sb.append(defaultValue);
         sb.append(" was returned.");
@@ -998,8 +1015,7 @@
         Log.w(TAG, "Attempt to cast generated internal exception:", e);
     }
 
-    void typeWarning(String key, Object value, String className,
-            ClassCastException e) {
+    void typeWarning(String key, @Nullable Object value, String className, RuntimeException e) {
         typeWarning(key, value, className, "<null>", e);
     }
 
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 0f94cbe..86e6db1 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -127,6 +127,7 @@
     private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
     private final Parcel mHistoryBuffer;
     private final List<BatteryStats.HistoryTag> mHistoryTagPool;
+    private final BatteryStatsHistory mBatteryStatsHistory;
 
     private BatteryUsageStats(@NonNull Builder builder) {
         mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
@@ -138,6 +139,7 @@
         mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
         mHistoryBuffer = builder.mHistoryBuffer;
         mHistoryTagPool = builder.mHistoryTagPool;
+        mBatteryStatsHistory = builder.mBatteryStatsHistory;
         mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
         mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
         mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
@@ -289,8 +291,8 @@
             throw new IllegalStateException(
                     "Battery history was not requested in the BatteryUsageStatsQuery");
         }
-        return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer),
-                mHistoryTagPool);
+
+        return new BatteryStatsHistoryIterator(mBatteryStatsHistory, mHistoryTagPool);
     }
 
     @Override
@@ -356,7 +358,10 @@
                 tag.poolIdx = source.readInt();
                 mHistoryTagPool.add(tag);
             }
+            mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+            mBatteryStatsHistory.readFromBatteryUsageStatsParcel(source);
         } else {
+            mBatteryStatsHistory = null;
             mHistoryBuffer = null;
             mHistoryTagPool = null;
         }
@@ -404,6 +409,7 @@
                 dest.writeInt(tag.uid);
                 dest.writeInt(tag.poolIdx);
             }
+            mBatteryStatsHistory.writeToBatteryUsageStatsParcel(dest);
         } else {
             dest.writeBoolean(false);
         }
@@ -757,6 +763,7 @@
                 new SparseArray<>();
         private Parcel mHistoryBuffer;
         private List<BatteryStats.HistoryTag> mHistoryTagPool;
+        private BatteryStatsHistory mBatteryStatsHistory;
 
         public Builder(@NonNull String[] customPowerComponentNames) {
             this(customPowerComponentNames, false);
@@ -865,10 +872,12 @@
          * Sets the parceled recent history.
          */
         @NonNull
-        public Builder setBatteryHistory(Parcel historyBuffer,
-                List<BatteryStats.HistoryTag> historyTagPool) {
+        public Builder setBatteryHistory(@NonNull Parcel historyBuffer,
+                @NonNull List<BatteryStats.HistoryTag> historyTagPool,
+                @NonNull BatteryStatsHistory batteryStatsHistory) {
             mHistoryBuffer = historyBuffer;
             mHistoryTagPool = historyTagPool;
+            mBatteryStatsHistory = batteryStatsHistory;
             return this;
         }
 
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index c646623..71c63ff 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -116,7 +116,7 @@
             for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
                 if (a != null) {
                     for (WeakReference<BinderProxy> ref : a) {
-                        if (ref.get() != null) {
+                        if (!ref.refersTo(null)) {
                             ++size;
                         }
                     }
@@ -187,7 +187,7 @@
             // This ensures that ArrayList size is bounded by the maximum occupancy of
             // that bucket.
             for (int i = 0; i < size; ++i) {
-                if (valueArray.get(i).get() == null) {
+                if (valueArray.get(i).refersTo(null)) {
                     valueArray.set(i, newWr);
                     Long[] keyArray = mMainIndexKeys[myHash];
                     keyArray[i] = key;
@@ -195,7 +195,7 @@
                         // "Randomly" check one of the remaining entries in [i+1, size), so that
                         // needlessly long buckets are eventually pruned.
                         int rnd = Math.floorMod(++mRandom, size - (i + 1));
-                        if (valueArray.get(i + 1 + rnd).get() == null) {
+                        if (valueArray.get(i + 1 + rnd).refersTo(null)) {
                             remove(myHash, i + 1 + rnd);
                         }
                     }
@@ -516,12 +516,15 @@
     public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
         Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
 
-        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
+        boolean warnOnBlocking = mWarnOnBlocking; // Cache it to reduce volatile access.
+
+        if (warnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
                 && Binder.sWarnOnBlockingOnCurrentThread.get()) {
 
             // For now, avoid spamming the log by disabling after we've logged
             // about this interface at least once
             mWarnOnBlocking = false;
+            warnOnBlocking = false;
 
             if (Build.IS_USERDEBUG) {
                 // Log this as a WTF on userdebug builds.
@@ -568,7 +571,13 @@
         }
 
         try {
-            return transactNative(code, data, reply, flags);
+            final boolean result = transactNative(code, data, reply, flags);
+
+            if (reply != null && !warnOnBlocking) {
+                reply.addFlags(Parcel.FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT);
+            }
+
+            return result;
         } finally {
             AppOpsManager.resumeNotedAppOpsCollection(prevCollection);
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index e519ff3..545ae38 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -31,6 +31,7 @@
 import android.sysprop.SocProperties;
 import android.sysprop.TelephonyProperties;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.view.View;
 
@@ -39,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -396,6 +398,22 @@
          */
         public static final String CODENAME = getString("ro.build.version.codename");
 
+        /**
+         * All known codenames starting from {@link VERSION_CODES.Q}.
+         *
+         * <p>This includes in development codenames as well, i.e. if {@link #CODENAME} is not "REL"
+         * then the value of that is present in this set.
+         *
+         * <p>If a particular string is not present in this set, then it is either not a codename
+         * or a codename for a future release. For example, during Android R development, "Tiramisu"
+         * was not a known codename.
+         *
+         * @hide
+         */
+        @SystemApi
+        @NonNull public static final Set<String> KNOWN_CODENAMES =
+                new ArraySet<>(getStringList("ro.build.version.known_codenames", ","));
+
         private static final String[] ALL_CODENAMES
                 = getStringList("ro.build.version.all_codenames", ",");
 
@@ -1024,7 +1042,7 @@
          * will also enable {@link StrictMode.ThreadPolicy.Builder#detectUnbufferedIo}.</li>
          * <li>{@link android.provider.DocumentsContract}'s various methods will throw failure
          * exceptions back to the caller instead of returning null.
-         * <li>{@link View#hasFocusable View.hasFocusable} now includes auto-focusable views.</li>
+         * <li>{@link View#hasFocusable() View.hasFocusable} now includes auto-focusable views.</li>
          * <li>{@link android.view.SurfaceView} will no longer always change the underlying
          * Surface object when something about it changes; apps need to look at the current
          * state of the object to determine which things they are interested in have changed.</li>
@@ -1132,6 +1150,14 @@
         public static final int S = 31;
 
         /**
+         * S V2.
+         *
+         * Once more unto the breach, dear friends, once more.
+         *
+         */
+        public static final int S_V2 = 32;
+
+        /**
          * Tiramisu.
          */
         public static final int TIRAMISU = CUR_DEVELOPMENT;
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index b2bbfd6..2b13f20 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
@@ -914,6 +917,33 @@
 
     /**
      * Returns the value associated with the given key, or {@code null} if
+     * no mapping of the desired type exists for the given key or a {@code null}
+     * value is explicitly associated with the key.
+     *
+     * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+     * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+     * Otherwise, this method might throw an exception or return {@code null}.
+     *
+     * @param key a String, or {@code null}
+     * @param clazz The type of the object expected or {@code null} for performing no checks.
+     * @return a Parcelable value, or {@code null}
+     *
+     * @hide
+     */
+    @SuppressWarnings("unchecked")
+    @Nullable
+    public <T> T getParcelable(@Nullable String key, @NonNull Class<T> clazz) {
+        unparcel();
+        try {
+            return getValue(key, requireNonNull(clazz));
+        } catch (ClassCastException | BadParcelableException e) {
+            typeWarning(key, /* value */ null, "Parcelable", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or {@code null} if
      * no mapping of the desired type exists for the given key or a null
      * value is explicitly associated with the key.
      *
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 09eac79..32cee94 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -18,6 +18,7 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -53,6 +54,8 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamClass;
 import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -229,6 +232,25 @@
 
     private RuntimeException mStack;
 
+    /** @hide */
+    @TestApi
+    public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1 << 0;
+
+    /** @hide */
+    @TestApi
+    public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 1 << 1;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT,
+            FLAG_PROPAGATE_ALLOW_BLOCKING,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ParcelFlags {}
+
+    @ParcelFlags
+    private int mFlags;
+
     /**
      * Whether or not to parcel the stack trace of an exception. This has a performance
      * impact, so should only be included in specific processes and only on debug builds.
@@ -585,6 +607,40 @@
         nativeMarkForBinder(mNativePtr, binder);
     }
 
+    /** @hide */
+    @ParcelFlags
+    @TestApi
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /** @hide */
+    public void setFlags(@ParcelFlags int flags) {
+        mFlags = flags;
+    }
+
+    /** @hide */
+    public void addFlags(@ParcelFlags int flags) {
+        mFlags |= flags;
+    }
+
+    /** @hide */
+    private boolean hasFlags(@ParcelFlags int flags) {
+        return (mFlags & flags) == flags;
+    }
+
+    /**
+     * This method is used by the AIDL compiler for system components. Not intended to be
+     * used by non-system apps.
+     */
+    // Note: Ideally this method should be @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES),
+    // but we need to make this method public due to the way the aidl compiler is compiled.
+    // We don't really need to protect it; even if 3p / non-system apps, nothing would happen.
+    // This would only work when used on a reply parcel by a binder object that's allowed-blocking.
+    public void setPropagateAllowBlocking() {
+        addFlags(FLAG_PROPAGATE_ALLOW_BLOCKING);
+    }
+
     /**
      * Returns the total amount of data contained in the parcel.
      */
@@ -2079,6 +2135,102 @@
     }
 
     /**
+     * Flatten a homogeneous multi-dimensional array with fixed-size.  This delegates to other
+     * APIs to write a one-dimensional array.  Use {@link #readFixedArray(Object)} or
+     * {@link #createFixedArray(Class, int[])} with the same dimensions to unmarshal.
+     *
+     * @param val The array to be written.
+     * @param parcelableFlags Contextual flags as per
+     *   {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}.
+     *   Used only if val is an array of Parcelable objects.
+     * @param dimensions an array of int representing length of each dimension. The array should be
+     *   sized with the exact size of dimensions.
+     *
+     * @see #readFixedArray
+     * @see #createFixedArray
+     * @see #writeBooleanArray
+     * @see #writeByteArray
+     * @see #writeCharArray
+     * @see #writeIntArray
+     * @see #writeLongArray
+     * @see #writeFloatArray
+     * @see #writeDoubleArray
+     * @see #writeBinderArray
+     * @see #writeInterfaceArray
+     * @see #writeTypedArray
+     * @throws BadParcelableException If the array's component type is not supported or if its
+     *   size doesn't match with the given dimensions.
+     */
+    public <T> void writeFixedArray(@Nullable T val, int parcelableFlags,
+            @NonNull int... dimensions) {
+        if (val == null) {
+            writeInt(-1);
+            return;
+        }
+        writeFixedArrayInternal(val, parcelableFlags, /*index=*/0, dimensions);
+    }
+
+    private <T> void writeFixedArrayInternal(T val, int parcelableFlags, int index,
+            int[] dimensions) {
+        if (index >= dimensions.length) {
+            throw new BadParcelableException("Array has more dimensions than expected: "
+                + dimensions.length);
+        }
+
+        int length = dimensions[index];
+
+        // val should be an array of length N
+        if (val == null) {
+            throw new BadParcelableException("Non-null array shouldn't have a null array.");
+        }
+        if (!val.getClass().isArray()) {
+            throw new BadParcelableException("Not an array: " + val);
+        }
+        if (Array.getLength(val) != length) {
+            throw new BadParcelableException("bad length: expected " + length + ", but got "
+                + Array.getLength(val));
+        }
+
+        // Delegates to other writers if this is a one-dimensional array.
+        // Otherwise, write component arrays with recursive calls.
+
+        final Class<?> componentType = val.getClass().getComponentType();
+        if (!componentType.isArray() && index + 1 != dimensions.length) {
+            throw new BadParcelableException("Array has fewer dimensions than expected: "
+                + dimensions.length);
+        }
+        if (componentType == boolean.class) {
+            writeBooleanArray((boolean[]) val);
+        } else if (componentType == byte.class) {
+            writeByteArray((byte[]) val);
+        } else if (componentType == char.class) {
+            writeCharArray((char[]) val);
+        } else if (componentType == int.class) {
+            writeIntArray((int[]) val);
+        } else if (componentType == long.class) {
+            writeLongArray((long[]) val);
+        } else if (componentType == float.class) {
+            writeFloatArray((float[]) val);
+        } else if (componentType == double.class) {
+            writeDoubleArray((double[]) val);
+        } else if (componentType == IBinder.class) {
+            writeBinderArray((IBinder[]) val);
+        } else if (IInterface.class.isAssignableFrom(componentType)) {
+            writeInterfaceArray((IInterface[]) val);
+        } else if (Parcelable.class.isAssignableFrom(componentType)) {
+            writeTypedArray((Parcelable[]) val, parcelableFlags);
+        } else if (componentType.isArray()) {
+            writeInt(length);
+            for (int i = 0; i < length; i++) {
+                writeFixedArrayInternal(Array.get(val, i), parcelableFlags, index + 1,
+                        dimensions);
+            }
+        } else {
+            throw new BadParcelableException("unknown type for fixed-size array: " + componentType);
+        }
+    }
+
+    /**
      * Flatten a generic object in to a parcel.  The given Object value may
      * currently be one of the following types:
      *
@@ -2940,7 +3092,15 @@
      * Read an object from the parcel at the current dataPosition().
      */
     public final IBinder readStrongBinder() {
-        return nativeReadStrongBinder(mNativePtr);
+        final IBinder result = nativeReadStrongBinder(mNativePtr);
+
+        // If it's a reply from a method with @PropagateAllowBlocking, then inherit allow-blocking
+        // from the object that returned it.
+        if (result != null && hasFlags(
+                FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT | FLAG_PROPAGATE_ALLOW_BLOCKING)) {
+            Binder.allowBlocking(result);
+        }
+        return result;
     }
 
     /**
@@ -3781,6 +3941,317 @@
     }
 
     /**
+     * Read a new multi-dimensional array from a parcel.  If you want to read Parcelable or
+     * IInterface values, use {@link #readFixedArray(Object, Parcelable.Creator)} or
+     * {@link #readFixedArray(Object, Function)}.
+     * @param val the destination array to hold the read values.
+     *
+     * @see #writeTypedArray
+     * @see #readBooleanArray
+     * @see #readByteArray
+     * @see #readCharArray
+     * @see #readIntArray
+     * @see #readLongArray
+     * @see #readFloatArray
+     * @see #readDoubleArray
+     * @see #readBinderArray
+     * @see #readInterfaceArray
+     * @see #readTypedArray
+     */
+    public <T> void readFixedArray(@NonNull T val) {
+        Class<?> componentType = val.getClass().getComponentType();
+        if (componentType == boolean.class) {
+            readBooleanArray((boolean[]) val);
+        } else if (componentType == byte.class) {
+            readByteArray((byte[]) val);
+        } else if (componentType == char.class) {
+            readCharArray((char[]) val);
+        } else if (componentType == int.class) {
+            readIntArray((int[]) val);
+        } else if (componentType == long.class) {
+            readLongArray((long[]) val);
+        } else if (componentType == float.class) {
+            readFloatArray((float[]) val);
+        } else if (componentType == double.class) {
+            readDoubleArray((double[]) val);
+        } else if (componentType == IBinder.class) {
+            readBinderArray((IBinder[]) val);
+        } else if (componentType.isArray()) {
+            int length = readInt();
+            if (length != Array.getLength(val)) {
+                throw new BadParcelableException("Bad length: expected " + Array.getLength(val)
+                    + ", but got " + length);
+            }
+            for (int i = 0; i < length; i++) {
+                readFixedArray(Array.get(val, i));
+            }
+        } else {
+            throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+        }
+    }
+
+    /**
+     * Read a new multi-dimensional array of typed interfaces from a parcel.
+     * If you want to read Parcelable values, use
+     * {@link #readFixedArray(Object, Parcelable.Creator)}. For values of other types, use
+     * {@link #readFixedArray(Object)}.
+     * @param val the destination array to hold the read values.
+     */
+    public <T, S extends IInterface> void readFixedArray(@NonNull T val,
+            @NonNull Function<IBinder, S> asInterface) {
+        Class<?> componentType = val.getClass().getComponentType();
+        if (IInterface.class.isAssignableFrom(componentType)) {
+            readInterfaceArray((S[]) val, asInterface);
+        } else if (componentType.isArray()) {
+            int length = readInt();
+            if (length != Array.getLength(val)) {
+                throw new BadParcelableException("Bad length: expected " + Array.getLength(val)
+                    + ", but got " + length);
+            }
+            for (int i = 0; i < length; i++) {
+                readFixedArray(Array.get(val, i), asInterface);
+            }
+        } else {
+            throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+        }
+    }
+
+    /**
+     * Read a new multi-dimensional array of typed parcelables from a parcel.
+     * If you want to read IInterface values, use
+     * {@link #readFixedArray(Object, Function)}. For values of other types, use
+     * {@link #readFixedArray(Object)}.
+     * @param val the destination array to hold the read values.
+     */
+    public <T, S extends Parcelable> void readFixedArray(@NonNull T val,
+            @NonNull Parcelable.Creator<S> c) {
+        Class<?> componentType = val.getClass().getComponentType();
+        if (Parcelable.class.isAssignableFrom(componentType)) {
+            readTypedArray((S[]) val, c);
+        } else if (componentType.isArray()) {
+            int length = readInt();
+            if (length != Array.getLength(val)) {
+                throw new BadParcelableException("Bad length: expected " + Array.getLength(val)
+                    + ", but got " + length);
+            }
+            for (int i = 0; i < length; i++) {
+                readFixedArray(Array.get(val, i), c);
+            }
+        } else {
+            throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+        }
+    }
+
+    private void ensureClassHasExpectedDimensions(@NonNull Class<?> cls, int numDimension) {
+        if (numDimension <= 0) {
+            throw new BadParcelableException("Fixed-size array should have dimensions.");
+        }
+
+        for (int i = 0; i < numDimension; i++) {
+            if (!cls.isArray()) {
+                throw new BadParcelableException("Array has fewer dimensions than expected: "
+                    + numDimension);
+            }
+            cls = cls.getComponentType();
+        }
+        if (cls.isArray()) {
+            throw new BadParcelableException("Array has more dimensions than expected: "
+                + numDimension);
+        }
+    }
+
+    /**
+     * Read and return a new multi-dimensional array from a parcel.  Returns null if the
+     * previously written array object is null.  If you want to read Parcelable or
+     * IInterface values, use {@link #createFixedArray(Class, Parcelable.Creator, int[])} or
+     * {@link #createFixedArray(Class, Function, int[])}.
+     * @param cls  the Class object for the target array type. (e.g. int[][].class)
+     * @param dimensions an array of int representing length of each dimension.
+     *
+     * @see #writeTypedArray
+     * @see #createBooleanArray
+     * @see #createByteArray
+     * @see #createCharArray
+     * @see #createIntArray
+     * @see #createLongArray
+     * @see #createFloatArray
+     * @see #createDoubleArray
+     * @see #createBinderArray
+     * @see #createInterfaceArray
+     * @see #createTypedArray
+     */
+    @Nullable
+    public <T> T createFixedArray(@NonNull Class<T> cls, @NonNull int... dimensions) {
+        // Check if type matches with dimensions
+        // If type is one-dimensional array, delegate to other creators
+        // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray
+
+        ensureClassHasExpectedDimensions(cls, dimensions.length);
+
+        T val = null;
+        final Class<?> componentType = cls.getComponentType();
+        if (componentType == boolean.class) {
+            val = (T) createBooleanArray();
+        } else if (componentType == byte.class) {
+            val = (T) createByteArray();
+        } else if (componentType == char.class) {
+            val = (T) createCharArray();
+        } else if (componentType == int.class) {
+            val = (T) createIntArray();
+        } else if (componentType == long.class) {
+            val = (T) createLongArray();
+        } else if (componentType == float.class) {
+            val = (T) createFloatArray();
+        } else if (componentType == double.class) {
+            val = (T) createDoubleArray();
+        } else if (componentType == IBinder.class) {
+            val = (T) createBinderArray();
+        } else if (componentType.isArray()) {
+            int length = readInt();
+            if (length < 0) {
+                return null;
+            }
+            if (length != dimensions[0]) {
+                throw new BadParcelableException("Bad length: expected " + dimensions[0]
+                    + ", but got " + length);
+            }
+
+            // Create a multi-dimensional array with an innermost component type and dimensions
+            Class<?> innermost = componentType.getComponentType();
+            while (innermost.isArray()) {
+                innermost = innermost.getComponentType();
+            }
+            val = (T) Array.newInstance(innermost, dimensions);
+            for (int i = 0; i < length; i++) {
+                readFixedArray(Array.get(val, i));
+            }
+            return val;
+        } else {
+            throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+        }
+
+        // Check if val is null (which is OK) or has the expected size.
+        // This check doesn't have to be multi-dimensional because multi-dimensional arrays
+        // are created with expected dimensions.
+        if (val != null && Array.getLength(val) != dimensions[0]) {
+            throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got "
+                + Array.getLength(val));
+        }
+        return val;
+    }
+
+    /**
+     * Read and return a new multi-dimensional array of typed interfaces from a parcel.
+     * Returns null if the previously written array object is null.  If you want to read
+     * Parcelable values, use {@link #createFixedArray(Class, Parcelable.Creator, int[])}.
+     * For values of other types use {@link #createFixedArray(Class, int[])}.
+     * @param cls  the Class object for the target array type. (e.g. IFoo[][].class)
+     * @param dimensions an array of int representing length of each dimension.
+     */
+    @Nullable
+    public <T, S extends IInterface> T createFixedArray(@NonNull Class<T> cls,
+            @NonNull Function<IBinder, S> asInterface, @NonNull int... dimensions) {
+        // Check if type matches with dimensions
+        // If type is one-dimensional array, delegate to other creators
+        // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray
+
+        ensureClassHasExpectedDimensions(cls, dimensions.length);
+
+        T val = null;
+        final Class<?> componentType = cls.getComponentType();
+        if (IInterface.class.isAssignableFrom(componentType)) {
+            val = (T) createInterfaceArray(n -> (S[]) Array.newInstance(componentType, n),
+                    asInterface);
+        } else if (componentType.isArray()) {
+            int length = readInt();
+            if (length < 0) {
+                return null;
+            }
+            if (length != dimensions[0]) {
+                throw new BadParcelableException("Bad length: expected " + dimensions[0]
+                    + ", but got " + length);
+            }
+
+            // Create a multi-dimensional array with an innermost component type and dimensions
+            Class<?> innermost = componentType.getComponentType();
+            while (innermost.isArray()) {
+                innermost = innermost.getComponentType();
+            }
+            val = (T) Array.newInstance(innermost, dimensions);
+            for (int i = 0; i < length; i++) {
+                readFixedArray(Array.get(val, i), asInterface);
+            }
+            return val;
+        } else {
+            throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+        }
+
+        // Check if val is null (which is OK) or has the expected size.
+        // This check doesn't have to be multi-dimensional because multi-dimensional arrays
+        // are created with expected dimensions.
+        if (val != null && Array.getLength(val) != dimensions[0]) {
+            throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got "
+                + Array.getLength(val));
+        }
+        return val;
+    }
+
+    /**
+     * Read and return a new multi-dimensional array of typed parcelables from a parcel.
+     * Returns null if the previously written array object is null.  If you want to read
+     * IInterface values, use {@link #createFixedArray(Class, Function, int[])}.
+     * For values of other types use {@link #createFixedArray(Class, int[])}.
+     * @param cls  the Class object for the target array type. (e.g. Foo[][].class)
+     * @param dimensions an array of int representing length of each dimension.
+     */
+    @Nullable
+    public <T, S extends Parcelable> T createFixedArray(@NonNull Class<T> cls,
+            @NonNull Parcelable.Creator<S> c, @NonNull int... dimensions) {
+        // Check if type matches with dimensions
+        // If type is one-dimensional array, delegate to other creators
+        // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray
+
+        ensureClassHasExpectedDimensions(cls, dimensions.length);
+
+        T val = null;
+        final Class<?> componentType = cls.getComponentType();
+        if (Parcelable.class.isAssignableFrom(componentType)) {
+            val = (T) createTypedArray(c);
+        } else if (componentType.isArray()) {
+            int length = readInt();
+            if (length < 0) {
+                return null;
+            }
+            if (length != dimensions[0]) {
+                throw new BadParcelableException("Bad length: expected " + dimensions[0]
+                    + ", but got " + length);
+            }
+
+            // Create a multi-dimensional array with an innermost component type and dimensions
+            Class<?> innermost = componentType.getComponentType();
+            while (innermost.isArray()) {
+                innermost = innermost.getComponentType();
+            }
+            val = (T) Array.newInstance(innermost, dimensions);
+            for (int i = 0; i < length; i++) {
+                readFixedArray(Array.get(val, i), c);
+            }
+            return val;
+        } else {
+            throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+        }
+
+        // Check if val is null (which is OK) or has the expected size.
+        // This check doesn't have to be multi-dimensional because multi-dimensional arrays
+        // are created with expected dimensions.
+        if (val != null && Array.getLength(val) != dimensions[0]) {
+            throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got "
+                + Array.getLength(val));
+        }
+        return val;
+    }
+
+    /**
      * Write a heterogeneous array of Parcelable objects into the Parcel.
      * Each object in the array is written along with its class name, so
      * that the correct class can later be instantiated.  As a result, this
@@ -3841,18 +4312,19 @@
     }
 
     /**
-     * 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.
+     * This will return a {@link Function} for length-prefixed types that deserializes the object
+     * when {@link Function#apply} is called with the expected class of the return object (or {@code
+     * null} for no type check), 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
+     * <p>After calling {@link Function#apply(Object)} 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:
+     * </p>The function returned implements {@link #equals(Object)} and {@link #hashCode()}. Two
+     * function objects 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:
+     *   <li>{@link Function#apply} has been called on both and both objects returned are equal.
+     *   <li>{@link Function#apply} 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.
@@ -3879,7 +4351,7 @@
     }
 
 
-    private static final class LazyValue implements Supplier<Object> {
+    private static final class LazyValue implements Function<Class<?>, Object> {
         /**
          *                      |   4B   |   4B   |
          * mSource = Parcel{... |  type  | length | object | ...}
@@ -3911,7 +4383,7 @@
         }
 
         @Override
-        public Object get() {
+        public Object apply(@Nullable Class<?> clazz) {
             Parcel source = mSource;
             if (source != null) {
                 synchronized (source) {
@@ -3920,7 +4392,7 @@
                         int restore = source.dataPosition();
                         try {
                             source.setDataPosition(mPosition);
-                            mObject = source.readValue(mLoader);
+                            mObject = source.readValue(mLoader, clazz);
                         } finally {
                             source.setDataPosition(restore);
                         }
@@ -4581,6 +5053,7 @@
     }
 
     private void freeBuffer() {
+        mFlags = 0;
         resetSqaushingState();
         if (mOwnsNativeParcelObject) {
             nativeFreeBuffer(mNativePtr);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9f37c48..2030571 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -129,6 +129,7 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     @TestApi
+    @SystemApi(client = MODULE_LIBRARIES)
     public static final int NFC_UID = 1027;
 
     /**
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index d974e0c..6b869f1 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -16,7 +16,10 @@
 
 package android.os;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -90,6 +93,7 @@
     /** @hide */
     public static final long TRACE_TAG_DATABASE = 1L << 20;
     /** @hide */
+    @SystemApi(client = MODULE_LIBRARIES)
     public static final long TRACE_TAG_NETWORK = 1L << 21;
     /** @hide */
     public static final long TRACE_TAG_ADB = 1L << 22;
@@ -148,6 +152,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @SystemApi(client = MODULE_LIBRARIES)
     public static boolean isTagEnabled(long traceTag) {
         long tags = nativeGetEnabledTags();
         return (tags & traceTag) != 0;
@@ -163,7 +168,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public static void traceCounter(long traceTag, String counterName, int counterValue) {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static void traceCounter(long traceTag, @NonNull String counterName, int counterValue) {
         if (isTagEnabled(traceTag)) {
             nativeTraceCounter(traceTag, counterName, counterValue);
         }
@@ -202,7 +208,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public static void traceBegin(long traceTag, String methodName) {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static void traceBegin(long traceTag, @NonNull String methodName) {
         if (isTagEnabled(traceTag)) {
             nativeTraceBegin(traceTag, methodName);
         }
@@ -217,6 +224,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @SystemApi(client = MODULE_LIBRARIES)
     public static void traceEnd(long traceTag) {
         if (isTagEnabled(traceTag)) {
             nativeTraceEnd(traceTag);
@@ -237,7 +245,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public static void asyncTraceBegin(long traceTag, String methodName, int cookie) {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static void asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie) {
         if (isTagEnabled(traceTag)) {
             nativeAsyncTraceBegin(traceTag, methodName, cookie);
         }
@@ -255,7 +264,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public static void asyncTraceEnd(long traceTag, String methodName, int cookie) {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static void asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie) {
         if (isTagEnabled(traceTag)) {
             nativeAsyncTraceEnd(traceTag, methodName, cookie);
         }
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a5a40ad..4e69952 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -26,6 +26,7 @@
      * @param dsuSlot Name used to identify this installation
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean startInstallation(@utf8InCpp String dsuSlot);
 
     /**
@@ -36,6 +37,7 @@
      * @param readOnly True if this partition is readOnly
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean createPartition(@utf8InCpp String name, long size, boolean readOnly);
 
     /**
@@ -43,12 +45,14 @@
      *
      * @return true if the partition installation completes without error.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean closePartition();
 
     /**
      * Finish a previously started installation. Installations without
      * a cooresponding finishInstallation() will be cleaned up during device boot.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean finishInstallation();
 
     /**
@@ -57,6 +61,7 @@
      *
      * @return GsiProgress
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     GsiProgress getInstallationProgress();
 
     /**
@@ -66,21 +71,25 @@
      *
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean abort();
 
     /**
      * @return true if the device is running an DynamicAnroid image
      */
+    @RequiresNoPermission
     boolean isInUse();
 
     /**
      * @return true if the device has an DynamicSystem image installed
      */
+    @RequiresNoPermission
     boolean isInstalled();
 
     /**
      * @return true if the device has an DynamicSystem image enabled
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean isEnabled();
 
     /**
@@ -88,6 +97,7 @@
      *
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean remove();
 
     /**
@@ -97,6 +107,7 @@
      *
      * @return true if the call succeeds
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean setEnable(boolean enable, boolean oneShot);
 
     /**
@@ -106,6 +117,7 @@
      * @param fd            fd that points to a ashmem
      * @param size          size of the ashmem file
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean setAshmem(in ParcelFileDescriptor fd, long size);
 
     /**
@@ -115,6 +127,7 @@
      * @param bytes         number of bytes that can be read from stream.
      * @return              true on success, false otherwise.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean submitFromAshmem(long bytes);
 
     /**
@@ -124,10 +137,12 @@
      * @return              true on success, false if partition doesn't have a
      *                      valid VBMeta block to retrieve the AVB key from.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     boolean getAvbPublicKey(out AvbPublicKey dst);
 
     /**
      * Returns the suggested scratch partition size for overlayFS.
      */
+    @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
     long suggestScratchSize();
 }
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3b4f7e2..f900558 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -317,16 +317,35 @@
             ErrorCode.MISSING_MIN_MAC_LENGTH; // -58;
     public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH =
             ErrorCode.UNSUPPORTED_MIN_MAC_LENGTH; // -59;
+    public static final int KM_ERROR_UNSUPPORTED_KDF = ErrorCode.UNSUPPORTED_KDF; // -60
+    public static final int KM_ERROR_UNSUPPORTED_EC_CURVE = ErrorCode.UNSUPPORTED_EC_CURVE; // -61
+    // -62 is KEY_REQUIRES_UPGRADE and is handled by Keystore.
+    public static final int KM_ERROR_ATTESTATION_CHALLENGE_MISSING =
+            ErrorCode.ATTESTATION_CHALLENGE_MISSING; // -63
+    public static final int KM_ERROR_KEYMINT_NOT_CONFIGURED =
+            ErrorCode.KEYMINT_NOT_CONFIGURED; // -64
+    public static final int KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING =
+            ErrorCode.ATTESTATION_APPLICATION_ID_MISSING; // -65;
     public static final int KM_ERROR_CANNOT_ATTEST_IDS =
             ErrorCode.CANNOT_ATTEST_IDS; // -66;
+    public static final int KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE =
+            ErrorCode.ROLLBACK_RESISTANCE_UNAVAILABLE; // -67;
     public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE =
             ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68;
     public static final int KM_ERROR_DEVICE_LOCKED =
             ErrorCode.DEVICE_LOCKED; // -72;
+    public static final int KM_ERROR_STORAGE_KEY_UNSUPPORTED =
+            ErrorCode.STORAGE_KEY_UNSUPPORTED; // -77,
+    public static final int KM_ERROR_INCOMPATIBLE_MGF_DIGEST =
+            ErrorCode.INCOMPATIBLE_MGF_DIGEST; // -78,
+    public static final int KM_ERROR_UNSUPPORTED_MGF_DIGEST =
+            ErrorCode.UNSUPPORTED_MGF_DIGEST; // -79,
     public static final int KM_ERROR_MISSING_NOT_BEFORE =
             ErrorCode.MISSING_NOT_BEFORE; // -80;
     public static final int KM_ERROR_MISSING_NOT_AFTER =
             ErrorCode.MISSING_NOT_AFTER; // -80;
+    public static final int KM_ERROR_HARDWARE_NOT_YET_AVAILABLE =
+            ErrorCode.HARDWARE_NOT_YET_AVAILABLE; // -85
     public static final int KM_ERROR_UNIMPLEMENTED =
             ErrorCode.UNIMPLEMENTED; // -100;
     public static final int KM_ERROR_VERSION_MISMATCH =
diff --git a/core/java/android/service/autofill/OWNERS b/core/java/android/service/autofill/OWNERS
index a088632..9a30e82 100644
--- a/core/java/android/service/autofill/OWNERS
+++ b/core/java/android/service/autofill/OWNERS
@@ -1,9 +1,3 @@
 # Bug component: 351486
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/java/android/service/contentcapture/OWNERS b/core/java/android/service/contentcapture/OWNERS
index 6337327..24561c5 100644
--- a/core/java/android/service/contentcapture/OWNERS
+++ b/core/java/android/service/contentcapture/OWNERS
@@ -1,9 +1,3 @@
 # Bug component: 544200
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/contentcapture/OWNERS
diff --git a/core/java/android/service/contentsuggestions/OWNERS b/core/java/android/service/contentsuggestions/OWNERS
index 46b5ea0..72fe0b1 100644
--- a/core/java/android/service/contentsuggestions/OWNERS
+++ b/core/java/android/service/contentsuggestions/OWNERS
@@ -1,7 +1,2 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+
+include /core/java/android/app/contentsuggestions/OWNERS
diff --git a/core/java/android/service/resumeonreboot/OWNERS b/core/java/android/service/resumeonreboot/OWNERS
index 3a127d5..721fbaf 100644
--- a/core/java/android/service/resumeonreboot/OWNERS
+++ b/core/java/android/service/resumeonreboot/OWNERS
@@ -1,2 +1 @@
-xunchang@google.com
-zhaojiac@google.com
+ejyzhang@google.com
\ No newline at end of file
diff --git a/core/java/android/service/security/attestationverification/OWNERS b/core/java/android/service/security/attestationverification/OWNERS
new file mode 100644
index 0000000..12c9978
--- /dev/null
+++ b/core/java/android/service/security/attestationverification/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/security/attestationverification/OWNERS
diff --git a/core/java/android/service/textclassifier/OWNERS b/core/java/android/service/textclassifier/OWNERS
index a535f52..c85c69e 100644
--- a/core/java/android/service/textclassifier/OWNERS
+++ b/core/java/android/service/textclassifier/OWNERS
@@ -1,9 +1,3 @@
 # Bug component: 709498
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/textclassifier/OWNERS
diff --git a/core/java/android/service/tracing/TraceReportService.java b/core/java/android/service/tracing/TraceReportService.java
new file mode 100644
index 0000000..6fdc8e8
--- /dev/null
+++ b/core/java/android/service/tracing/TraceReportService.java
@@ -0,0 +1,161 @@
+/*
+ * 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.service.tracing;
+
+import static android.annotation.SystemApi.Client.PRIVILEGED_APPS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.tracing.TraceReportParams;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * Service to be sub-classed and exposed by (privileged) apps which want to report
+ * system traces.
+ * <p>
+ * Subclasses should implement the onReportTrace method to handle traces reported
+ * to them.
+ * </p>
+ * <pre>
+ *    public class SampleReportService extends TraceReportService {
+ *        public void onReportTrace(TraceParams args) {
+ *            // --- Implementation goes here ---
+ *        }
+ *    }
+ * </pre>
+ * <p>
+ * The service declaration in the application manifest must specify
+ * BIND_TRACE_REPORT_SERVICE in the permission attribute.
+ * </p>
+ * <pre>
+ *   &lt;application>
+ *        &lt;service android:name=".SampleReportService"
+ *               android:permission="android.permission.BIND_TRACE_REPORT_SERVICE">
+ *       &lt;/service>
+ *   &lt;/application>
+ * </pre>
+ *
+ * Moreover, the package containing this service must hold the DUMP and PACKAGE_USAGE_STATS
+ * permissions.
+ *
+ * @hide
+ */
+@SystemApi(client = PRIVILEGED_APPS)
+public class TraceReportService extends Service {
+    private static final String TAG = "TraceReportService";
+    private Messenger mMessenger = null;
+
+    /**
+     * Public to allow this to be used by TracingServiceProxy in system_server.
+     *
+     * @hide
+     */
+    public static final int MSG_REPORT_TRACE = 1;
+
+    /**
+     * Contains information about the trace which is being reported.
+     *
+     * @hide
+     */
+    @SystemApi(client = PRIVILEGED_APPS)
+    public static final class TraceParams {
+        private final ParcelFileDescriptor mFd;
+        private final UUID mUuid;
+
+        private TraceParams(TraceReportParams params) {
+            mFd = params.fd;
+            mUuid = new UUID(params.uuidMsb, params.uuidLsb);
+        }
+
+        /**
+         * Returns the ParcelFileDescriptor for the collected trace.
+         */
+        @NonNull
+        public ParcelFileDescriptor getFd() {
+            return mFd;
+        }
+
+        /**
+         * Returns the UUID of the trace; this is exactly the UUID created by the tracing system
+         * (i.e. Perfetto) and is also present inside the trace file.
+         */
+        @NonNull
+        public UUID getUuid() {
+            return mUuid;
+        }
+    }
+
+    /**
+     * Called when a trace is reported and sent to this class.
+     *
+     * Note: the trace file descriptor should not be persisted beyond the lifetime of this
+     * function as it is owned by the framework and will be closed immediately after this function
+     * returns: if future use of the fd is needed, it should be duped.
+     */
+    public void onReportTrace(@NonNull TraceParams args) {
+    }
+
+    /**
+     * Handles binder calls from system_server.
+     */
+    private boolean onMessage(@NonNull Message msg) {
+        if (msg.what == MSG_REPORT_TRACE) {
+            if (!(msg.obj instanceof TraceReportParams)) {
+                Log.e(TAG, "Received invalid type for report trace message.");
+                return false;
+            }
+            TraceParams params = new TraceParams((TraceReportParams) msg.obj);
+            try {
+                onReportTrace(params);
+            } finally {
+                try {
+                    params.getFd().close();
+                } catch (IOException ignored) {
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns an IBinder for handling binder calls from system_server.
+     *
+     * @hide
+     */
+    @Nullable
+    @Override
+    public final IBinder onBind(@NonNull Intent intent) {
+        if (mMessenger == null) {
+            mMessenger = new Messenger(new Handler(Looper.getMainLooper(), this::onMessage));
+        }
+        return mMessenger.getBinder();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/service/translation/OWNERS b/core/java/android/service/translation/OWNERS
index a1e663a..440f9a8 100644
--- a/core/java/android/service/translation/OWNERS
+++ b/core/java/android/service/translation/OWNERS
@@ -1,8 +1,3 @@
 # Bug component: 994311
 
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include /core/java/android/view/translation/OWNERS
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
index 46b5ea0..59a0c2e 100644
--- a/core/java/android/service/voice/OWNERS
+++ b/core/java/android/service/voice/OWNERS
@@ -1,7 +1,3 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+# Bug component: 533220
+
+include /core/java/android/app/assist/OWNERS
diff --git a/core/java/android/service/wallpapereffectsgeneration/OWNERS b/core/java/android/service/wallpapereffectsgeneration/OWNERS
new file mode 100644
index 0000000..d2d3e2c0
--- /dev/null
+++ b/core/java/android/service/wallpapereffectsgeneration/OWNERS
@@ -0,0 +1,4 @@
+susharon@google.com
+shanh@google.com
+huiwu@google.com
+srazdan@google.com
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 9eaaa91..542de3f 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -131,6 +131,7 @@
                     mContext.getAttributionTag(), callback);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -152,6 +153,7 @@
             mSubscriptionChangedListenerMap.remove(listener);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -194,6 +196,7 @@
                     mContext.getAttributionTag(), callback);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -216,6 +219,7 @@
             mOpportunisticSubscriptionChangedListenerMap.remove(listener);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -304,6 +308,7 @@
             sRegistry.notifyCarrierNetworkChange(active);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -329,6 +334,7 @@
             sRegistry.notifyCarrierNetworkChangeWithSubId(subscriptionId, active);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -347,6 +353,7 @@
             sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -364,6 +371,7 @@
             sRegistry.notifyCallStateForAllSubs(state, incomingNumber);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -376,6 +384,7 @@
             sRegistry.notifySubscriptionInfoChanged();
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -388,6 +397,7 @@
             sRegistry.notifyOpportunisticSubscriptionInfoChanged();
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -404,6 +414,7 @@
             sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -421,6 +432,7 @@
             sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -439,6 +451,7 @@
             sRegistry.notifyMessageWaitingChangedForPhoneId(slotIndex, subId, msgWaitingInd);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -454,6 +467,7 @@
             sRegistry.notifyCallForwardingChangedForSubscriber(subId, callForwardInd);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -469,6 +483,7 @@
             sRegistry.notifyDataActivityForSubscriber(subId, dataActivityType);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -490,6 +505,7 @@
                     slotIndex, subId, preciseState);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -508,6 +524,7 @@
             sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -523,6 +540,7 @@
             sRegistry.notifyEmergencyNumberList(slotIndex, subId);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -538,6 +556,7 @@
             sRegistry.notifyOutgoingEmergencyCall(phoneId, subId, emergencyNumber);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -553,6 +572,7 @@
             sRegistry.notifyOutgoingEmergencySms(phoneId, subId, emergencyNumber);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -570,6 +590,7 @@
             sRegistry.notifyRadioPowerStateChanged(slotIndex, subId, radioPowerState);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -583,6 +604,7 @@
             sRegistry.notifyPhoneCapabilityChanged(phoneCapability);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -615,6 +637,7 @@
                     SIM_ACTIVATION_TYPE_DATA, activationState);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -634,6 +657,7 @@
                     SIM_ACTIVATION_TYPE_VOICE, activationState);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -651,6 +675,7 @@
             sRegistry.notifyUserMobileDataStateChangedForPhoneId(slotIndex, subId, state);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -669,6 +694,7 @@
             sRegistry.notifyDisplayInfoChanged(slotIndex, subscriptionId, telephonyDisplayInfo);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -683,6 +709,7 @@
             sRegistry.notifyImsDisconnectCause(subId, imsReasonInfo);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -698,6 +725,7 @@
             sRegistry.notifySrvccStateChanged(subId, state);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -721,6 +749,7 @@
                 foregroundCallPreciseState, backgroundCallPreciseState);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -741,6 +770,7 @@
             sRegistry.notifyDisconnectCause(slotIndex, subId, cause, preciseCause);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -755,6 +785,7 @@
             sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -769,7 +800,7 @@
         try {
             sRegistry.notifyCellInfoForSubscriber(subId, cellInfo);
         } catch (RemoteException ex) {
-
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -781,7 +812,7 @@
         try {
             sRegistry.notifyActiveDataSubIdChanged(activeDataSubId);
         } catch (RemoteException ex) {
-
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -814,6 +845,7 @@
             sRegistry.notifyRegistrationFailed(slotIndex, subId, cellIdentity,
                     chosenPlmn, domain, causeCode, additionalCauseCode);
         } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -830,6 +862,7 @@
             sRegistry.notifyBarringInfoChanged(slotIndex, subId, barringInfo);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -846,6 +879,7 @@
             sRegistry.notifyPhysicalChannelConfigForSubscriber(slotIndex, subId, configs);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -862,6 +896,7 @@
             sRegistry.notifyDataEnabled(slotIndex, subId, enabled, reason);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -880,6 +915,7 @@
                     allowedNetworkType);
         } catch (RemoteException ex) {
             // system process is dead
+            throw ex.rethrowFromSystemServer();
         }
     }
 
@@ -895,6 +931,7 @@
             sRegistry.notifyLinkCapacityEstimateChanged(slotIndex, subId, linkCapacityEstimateList);
         } catch (RemoteException ex) {
             // system server crash
+            throw ex.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
index 9cbda9c..2eb917b 100644
--- a/core/java/android/text/method/TextKeyListener.java
+++ b/core/java/android/text/method/TextKeyListener.java
@@ -306,7 +306,7 @@
 
     /* package */ int getPrefs(Context context) {
         synchronized (this) {
-            if (!mPrefsInited || mResolver.get() == null) {
+            if (!mPrefsInited || mResolver.refersTo(null)) {
                 initPrefs(context);
             }
         }
diff --git a/core/java/android/tracing/ITracingServiceProxy.aidl b/core/java/android/tracing/ITracingServiceProxy.aidl
index 4520db3..8029b88 100644
--- a/core/java/android/tracing/ITracingServiceProxy.aidl
+++ b/core/java/android/tracing/ITracingServiceProxy.aidl
@@ -16,17 +16,25 @@
 
 package android.tracing;
 
+import android.tracing.TraceReportParams;
+
 /**
  * Binder interface for the TracingServiceProxy running in system_server.
  *
  * {@hide}
  */
-interface ITracingServiceProxy
-{
+interface ITracingServiceProxy {
     /**
      * Notifies system tracing app that a tracing session has ended. If a session is repurposed
      * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
      * there is no buffer available to dump.
      */
     oneway void notifyTraceSessionEnded(boolean sessionStolen);
+
+    /**
+     * Notifies the specified service that a trace has been captured. The contents of |params|
+     * contains the intended recipient (package and class) of this trace as well as a file
+     * descriptor to an unlinked trace |fd| (i.e. an fd opened using O_TMPFILE).
+     */
+    oneway void reportTrace(in TraceReportParams params);
 }
diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS
index f5de4eb..7d1b48b 100644
--- a/core/java/android/tracing/OWNERS
+++ b/core/java/android/tracing/OWNERS
@@ -1,2 +1,2 @@
-cfijalkovich@google.com
 carmenjackson@google.com
+include platform/external/perfetto:/OWNERS
diff --git a/core/java/android/tracing/TraceReportParams.aidl b/core/java/android/tracing/TraceReportParams.aidl
new file mode 100644
index 0000000..f57386c
--- /dev/null
+++ b/core/java/android/tracing/TraceReportParams.aidl
@@ -0,0 +1,59 @@
+/**
+ * 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.tracing;
+
+import android.os.ParcelFileDescriptor;
+
+/*
+ * Parameters for a trace report.
+ *
+ * See ITracingServiceProxy::reportTrace for more details.
+ *
+ * @hide
+ */
+parcelable TraceReportParams {
+  // The package name containing the reporter service (see |reporterClassName|).
+  String reporterPackageName;
+
+  // The class name of the reporter service. The framework will bind to this service and pass the
+  // trace fd and metadata to this class.
+  // This class should be "trusted" (in practice this means being a priv_app + having DUMP and
+  // USAGE_STATS permissions).
+  String reporterClassName;
+
+  // The file descriptor for the trace file. This will be an unlinked file fd (i.e. created
+  // with O_TMPFILE); the intention is that reporter classes link this fd into a app-private
+  // folder for reporting when conditions are right (e.g. charging, on unmetered networks etc).
+  ParcelFileDescriptor fd;
+
+  // The least-significant-bytes of the UUID of this trace.
+  long uuidLsb;
+
+  // The most-significant-bytes of the UUID of this trace.
+  long uuidMsb;
+
+  // Flag indicating whether, instead of passing the fd from the trace collector, to pass a
+  // pipe fd from system_server and send the file over it.
+  //
+  // This flag is necessary because there is no good way to write a CTS test where a helper
+  // priv_app (in terms of SELinux) is needed (this is because priv_apps are supposed to be
+  // preinstalled on the system partition). By creating a pipe in system_server we work around
+  // this restriction. Note that there is a maximum allowed file size if this flag is set
+  // (see TracingServiceProxy). Further note that, even though SELinux may be worked around,
+  // manifest (i.e. framework) permissions are still checked even if this flag is set.
+  boolean usePipeForTesting;
+}
\ No newline at end of file
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index 5425c21..d4cf6e6 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,8 +1,12 @@
+per-file Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
 per-file FeatureFlagUtils.java = sbasi@google.com
 per-file FeatureFlagUtils.java = tmfang@google.com
-per-file FeatureFlagUtils.java = asapperstein@google.com
 
 per-file AttributeSet.java = file:/core/java/android/content/res/OWNERS
 per-file TypedValue.java = file:/core/java/android/content/res/OWNERS
 
 per-file PackageUtils.java = file:/core/java/android/content/pm/OWNERS
+
+per-file NtpTrustedTime.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
+per-file TimeUtils.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
+per-file TrustedTime.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index c7d9b9c..c8c1fd4 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -407,20 +407,6 @@
         }
     }
 
-    static byte[] generateApkVerityRootHash(String apkPath)
-            throws IOException, SignatureNotFoundException, DigestException,
-                   NoSuchAlgorithmException {
-        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
-            SignatureInfo signatureInfo = findSignature(apk);
-            VerifiedSigner vSigner = verify(apk, false);
-            if (vSigner.verityRootHash == null) {
-                return null;
-            }
-            return VerityBuilder.generateApkVerityRootHash(
-                    apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
-        }
-    }
-
     /**
      * Verified APK Signature Scheme v2 signer.
      *
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index b07b522..15215c6 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -444,20 +444,6 @@
         }
     }
 
-    static byte[] generateApkVerityRootHash(String apkPath)
-            throws NoSuchAlgorithmException, DigestException, IOException,
-            SignatureNotFoundException {
-        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
-            SignatureInfo signatureInfo = findSignature(apk);
-            VerifiedSigner vSigner = verify(apk, false);
-            if (vSigner.verityRootHash == null) {
-                return null;
-            }
-            return VerityBuilder.generateApkVerityRootHash(
-                    apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
-        }
-    }
-
     /**
      * Verified APK Signature Scheme v3 signer, including the proof of rotation structure.
      *
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index 73f7543..f6b85fd 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -551,27 +551,6 @@
     }
 
     /**
-     * Generates the FSVerity root hash from FSVerity header, extensions and Merkle tree root hash
-     * in Signing Block.
-     *
-     * @return FSverity root hash
-     */
-    public static byte[] generateApkVerityRootHash(String apkPath)
-            throws NoSuchAlgorithmException, DigestException, IOException {
-        // first try v3
-        try {
-            return ApkSignatureSchemeV3Verifier.generateApkVerityRootHash(apkPath);
-        } catch (SignatureNotFoundException e) {
-            // try older version
-        }
-        try {
-            return ApkSignatureSchemeV2Verifier.generateApkVerityRootHash(apkPath);
-        } catch (SignatureNotFoundException e) {
-            return null;
-        }
-    }
-
-    /**
      * Extended signing details.
      * @hide for internal use only.
      */
diff --git a/core/java/android/util/apk/VerityBuilder.java b/core/java/android/util/apk/VerityBuilder.java
index c7c465d..adf53c2 100644
--- a/core/java/android/util/apk/VerityBuilder.java
+++ b/core/java/android/util/apk/VerityBuilder.java
@@ -143,25 +143,6 @@
             return generateFsVerityTreeInternal(apk, salt, levelOffset, tree);
         }
     }
-    /**
-     * Calculates the apk-verity root hash for integrity measurement.  This needs to be consistent
-     * to what kernel returns.
-     */
-    @NonNull
-    static byte[] generateApkVerityRootHash(@NonNull RandomAccessFile apk,
-            @NonNull ByteBuffer apkDigest, @NonNull SignatureInfo signatureInfo)
-            throws NoSuchAlgorithmException, DigestException, IOException {
-        assertSigningBlockAlignedAndHasFullPages(signatureInfo);
-
-        ByteBuffer footer = ByteBuffer.allocate(CHUNK_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN);
-        generateApkVerityFooter(apk, signatureInfo, footer);
-        footer.flip();
-
-        MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM);
-        md.update(footer);
-        md.update(apkDigest);
-        return md.digest();
-    }
 
     /**
      * Generates the apk-verity header and hash tree to be used by kernel for the given apk. This
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index c74e428..b166fa6 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -11,6 +11,9 @@
 roosa@google.com
 jreck@google.com
 
+# Autofill
+per-file ViewStructure.java = file:/core/java/android/service/autofill/OWNERS
+
 # Display
 per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS
 per-file Display*.aidl = file:/services/core/java/com/android/server/display/OWNERS
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 00f4eb8..5b0bc4a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3128,7 +3128,8 @@
 
         /**
          * The window is allowed to extend into the {@link DisplayCutout} area, only if the
-         * {@link DisplayCutout} is fully contained within a system bar. Otherwise, the window is
+         * {@link DisplayCutout} is fully contained within a system bar or the {@link DisplayCutout}
+         * is not deeper than 16 dp, but this depends on the OEM choice. Otherwise, the window is
          * laid out such that it does not overlap with the {@link DisplayCutout} area.
          *
          * <p>
@@ -3143,6 +3144,13 @@
          * The usual precautions for not overlapping with the status and navigation bar are
          * sufficient for ensuring that no important content overlaps with the DisplayCutout.
          *
+         * <p>
+         * Note: OEMs can have an option to allow the window to always extend into the
+         * {@link DisplayCutout} area, no matter the cutout flag set, when the {@link DisplayCutout}
+         * is on the different side from system bars, only if the {@link DisplayCutout} overlaps at
+         * most 16dp with the windows.
+         * In such case, OEMs must provide an opt-in/out affordance for users.
+         *
          * @see DisplayCutout
          * @see WindowInsets
          * @see #layoutInDisplayCutoutMode
@@ -3155,8 +3163,16 @@
          * The window is always allowed to extend into the {@link DisplayCutout} areas on the short
          * edges of the screen.
          *
+         * <p>
          * The window will never extend into a {@link DisplayCutout} area on the long edges of the
-         * screen.
+         * screen, unless the {@link DisplayCutout} is not deeper than 16 dp, but this depends on
+         * the OEM choice.
+         *
+         * <p>
+         * Note: OEMs can have an option to allow the window to extend into the
+         * {@link DisplayCutout} area on the long edge side, only if the cutout overlaps at most
+         * 16dp with the windows. In such case, OEMs must provide an opt-in/out affordance for
+         * users.
          *
          * <p>
          * The window must make sure that no important content overlaps with the
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index a088632..108c42c 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 351486
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 6337327..1a5cb1e4 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -1,9 +1,7 @@
 # Bug component: 544200
 
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
 augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/view/inputmethod/OWNERS b/core/java/android/view/inputmethod/OWNERS
index d7db7c7..9fa7e8f 100644
--- a/core/java/android/view/inputmethod/OWNERS
+++ b/core/java/android/view/inputmethod/OWNERS
@@ -3,4 +3,4 @@
 
 include /services/core/java/com/android/server/inputmethod/OWNERS
 
-per-file *InlineSuggestion* = file:/core/java/android/service/autofill/OWNERS
+per-file *InlineSuggestion* = file:/core/java/android/view/autofill/OWNERS
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index 4bcdeea..a205be2 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -2,8 +2,6 @@
 
 mns@google.com
 toki@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
 augale@google.com
 joannechung@google.com
 tonymak@google.com
diff --git a/core/java/android/view/textclassifier/logging/OWNERS b/core/java/android/view/textclassifier/logging/OWNERS
deleted file mode 100644
index ac80d9f..0000000
--- a/core/java/android/view/textclassifier/logging/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Bug component: 709498
-
-mns@google.com
-toki@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
-augale@google.com
-joannechung@google.com
diff --git a/core/java/android/view/translation/OWNERS b/core/java/android/view/translation/OWNERS
index a1e663a..b772ad3 100644
--- a/core/java/android/view/translation/OWNERS
+++ b/core/java/android/view/translation/OWNERS
@@ -1,8 +1,7 @@
 # Bug component: 994311
 
-adamhe@google.com
 augale@google.com
 joannechung@google.com
+markpun@google.com
 lpeter@google.com
-svetoslavganov@google.com
 tymtsai@google.com
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 2d1f17a..a0ec48b 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -297,12 +297,12 @@
         } else {
             mTextClassification = null;
         }
-        final SelectionModifierCursorController controller = mEditor.getSelectionController();
-        if (controller != null
-                && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
-            controller.show();
-        }
         if (mEditor.startActionModeInternal(actionMode)) {
+            final SelectionModifierCursorController controller = mEditor.getSelectionController();
+            if (controller != null
+                    && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
+                controller.show();
+            }
             if (result != null) {
                 switch (actionMode) {
                     case Editor.TextActionMode.SELECTION:
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f5c1bcf..452dad3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4347,7 +4347,7 @@
      * pixel" units.  This size is adjusted based on the current density and
      * user font size preference.
      *
-     * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op.
+     * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op.
      *
      * @param size The scaled pixel size.
      *
@@ -4362,7 +4362,7 @@
      * Set the default text size to a given unit and value. See {@link
      * TypedValue} for the possible dimension units.
      *
-     * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op.
+     * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op.
      *
      * @param unit The desired dimension unit.
      * @param size The desired size in the given units.
diff --git a/core/java/android/widget/inline/OWNERS b/core/java/android/widget/inline/OWNERS
new file mode 100644
index 0000000..9a30e82
--- /dev/null
+++ b/core/java/android/widget/inline/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/java/com/android/internal/midi/OWNERS b/core/java/com/android/internal/midi/OWNERS
new file mode 100644
index 0000000..af273a6
--- /dev/null
+++ b/core/java/com/android/internal/midi/OWNERS
@@ -0,0 +1 @@
+include /services/midi/OWNERS
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 2e7629a..f174498 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -34,8 +34,6 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 
-import java.net.Inet4Address;
-import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -93,8 +91,8 @@
     public String interfaze;
     public String session;
     public int mtu = -1;
-    public List<LinkAddress> addresses = new ArrayList<LinkAddress>();
-    public List<RouteInfo> routes = new ArrayList<RouteInfo>();
+    public List<LinkAddress> addresses = new ArrayList<>();
+    public List<RouteInfo> routes = new ArrayList<>();
     public List<String> dnsServers;
     public List<String> searchDomains;
     public List<String> allowedApplications;
@@ -107,6 +105,7 @@
     public boolean allowIPv4;
     public boolean allowIPv6;
     public boolean isMetered = true;
+    public boolean requiresInternetValidation = false;
     public Network[] underlyingNetworks;
     public ProxyInfo proxyInfo;
 
@@ -114,12 +113,33 @@
     public VpnConfig() {
     }
 
-    public void updateAllowedFamilies(InetAddress address) {
-        if (address instanceof Inet4Address) {
-            allowIPv4 = true;
-        } else {
-            allowIPv6 = true;
-        }
+    public VpnConfig(VpnConfig other) {
+        user = other.user;
+        interfaze = other.interfaze;
+        session = other.session;
+        mtu = other.mtu;
+        addresses = copyOf(other.addresses);
+        routes = copyOf(other.routes);
+        dnsServers = copyOf(other.dnsServers);
+        searchDomains = copyOf(other.searchDomains);
+        allowedApplications = copyOf(other.allowedApplications);
+        disallowedApplications = copyOf(other.disallowedApplications);
+        configureIntent = other.configureIntent;
+        startTime = other.startTime;
+        legacy = other.legacy;
+        blocking = other.blocking;
+        allowBypass = other.allowBypass;
+        allowIPv4 = other.allowIPv4;
+        allowIPv6 = other.allowIPv6;
+        isMetered = other.isMetered;
+        requiresInternetValidation = other.requiresInternetValidation;
+        underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
+                other.underlyingNetworks, other.underlyingNetworks.length) : null;
+        proxyInfo = other.proxyInfo;
+    }
+
+    private static <T> List<T> copyOf(List<T> list) {
+        return list != null ? new ArrayList<>(list) : null;
     }
 
     public void addLegacyRoutes(String routesStr) {
@@ -131,7 +151,6 @@
             //each route is ip/prefix
             RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
             this.routes.add(info);
-            updateAllowedFamilies(info.getDestination().getAddress());
         }
     }
 
@@ -144,7 +163,6 @@
             //each address is ip/prefix
             LinkAddress addr = new LinkAddress(address);
             this.addresses.add(addr);
-            updateAllowedFamilies(addr.getAddress());
         }
     }
 
@@ -173,6 +191,7 @@
         out.writeInt(allowIPv4 ? 1 : 0);
         out.writeInt(allowIPv6 ? 1 : 0);
         out.writeInt(isMetered ? 1 : 0);
+        out.writeInt(requiresInternetValidation ? 1 : 0);
         out.writeTypedArray(underlyingNetworks, flags);
         out.writeParcelable(proxyInfo, flags);
     }
@@ -200,6 +219,7 @@
             config.allowIPv4 = in.readInt() != 0;
             config.allowIPv6 = in.readInt() != 0;
             config.isMetered = in.readInt() != 0;
+            config.requiresInternetValidation = in.readInt() != 0;
             config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
             config.proxyInfo = in.readParcelable(null);
             return config;
@@ -232,6 +252,8 @@
                 .append(", allowBypass=").append(allowBypass)
                 .append(", allowIPv4=").append(allowIPv4)
                 .append(", allowIPv6=").append(allowIPv6)
+                .append(", isMetered=").append(isMetered)
+                .append(", requiresInternetValidation").append(requiresInternetValidation)
                 .append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
                 .append(", proxyInfo=").append(proxyInfo)
                 .append("}")
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index d8dc143..bd3e898 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -144,23 +144,26 @@
     public final boolean isRestrictedToTestNetworks;             // 24
 
     public final boolean excludeLocalRoutes;                     // 25
+    public final boolean requiresInternetValidation;             // 26
 
     // Helper fields.
     @UnsupportedAppUsage
     public transient boolean saveLogin = false;
 
     public VpnProfile(String key) {
-        this(key, false, false);
+        this(key, false, false, false);
     }
 
     public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
-        this(key, isRestrictedToTestNetworks, false);
+        this(key, isRestrictedToTestNetworks, false, false);
     }
 
-    public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes) {
+    public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes,
+            boolean requiresInternetValidation) {
         this.key = key;
         this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
         this.excludeLocalRoutes = excludeLocalRoutes;
+        this.requiresInternetValidation = requiresInternetValidation;
     }
 
     @UnsupportedAppUsage
@@ -191,6 +194,7 @@
         areAuthParamsInline = in.readBoolean();
         isRestrictedToTestNetworks = in.readBoolean();
         excludeLocalRoutes = in.readBoolean();
+        requiresInternetValidation = in.readBoolean();
     }
 
     /**
@@ -239,6 +243,7 @@
         out.writeBoolean(areAuthParamsInline);
         out.writeBoolean(isRestrictedToTestNetworks);
         out.writeBoolean(excludeLocalRoutes);
+        out.writeBoolean(requiresInternetValidation);
     }
 
     /**
@@ -258,9 +263,11 @@
             // 14-19: Standard profile, with option for serverCert, proxy
             // 24: Standard profile with serverCert, proxy and platform-VPN parameters
             // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
-            // 26: Standard profile with platform-VPN parameters and excludeLocalRoutes
-            if ((values.length < 14 || values.length > 19)
-                    && values.length != 24 && values.length != 25 && values.length != 26) {
+            // 26:                                            ...and excludeLocalRoutes
+            //     (26 can only be found on dogfood devices)
+            // 27:                                            ...and requiresInternetValidation
+            if ((values.length < 14 || (values.length > 19 && values.length < 24)
+                    || values.length > 27)) {
                 return null;
             }
 
@@ -278,8 +285,15 @@
                 excludeLocalRoutes = false;
             }
 
+            final boolean requiresInternetValidation;
+            if (values.length >= 27) {
+                requiresInternetValidation = Boolean.parseBoolean(values[26]);
+            } else {
+                requiresInternetValidation = false;
+            }
+
             VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks,
-                    excludeLocalRoutes);
+                    excludeLocalRoutes, requiresInternetValidation);
             profile.name = values[0];
             profile.type = Integer.parseInt(values[1]);
             if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -390,6 +404,7 @@
         builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks);
 
         builder.append(VALUE_DELIMITER).append(excludeLocalRoutes);
+        builder.append(VALUE_DELIMITER).append(requiresInternetValidation);
 
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
@@ -471,7 +486,7 @@
             key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
             l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
             proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
-            isRestrictedToTestNetworks, excludeLocalRoutes);
+            isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation);
     }
 
     /** Checks VPN profiles for interior equality. */
@@ -505,11 +520,12 @@
                 && maxMtu == other.maxMtu
                 && areAuthParamsInline == other.areAuthParamsInline
                 && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks
-                && excludeLocalRoutes == other.excludeLocalRoutes;
+                && excludeLocalRoutes == other.excludeLocalRoutes
+                && requiresInternetValidation == other.requiresInternetValidation;
     }
 
     @NonNull
-    public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
+    public static final Creator<VpnProfile> CREATOR = new Creator<>() {
         @Override
         public VpnProfile createFromParcel(Parcel in) {
             return new VpnProfile(in);
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 879e0a8..8ebb11d 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -160,6 +160,11 @@
         mHistoryDir = null;
         mHistoryBuffer = historyBuffer;
     }
+
+    public File getHistoryDirectory() {
+        return mHistoryDir;
+    }
+
     /**
      * Set the active file that mHistoryBuffer is backed up into.
      *
@@ -375,12 +380,24 @@
     }
 
     /**
-     * Read all history files and serialize into a big Parcel. This is to send history files to
-     * Settings app since Settings app can not access /data/system directory.
-     * Checkin file also call this method.
+     * Read all history files and serialize into a big Parcel.
+     * Checkin file calls this method.
      * @param out the output parcel
      */
     public void writeToParcel(Parcel out) {
+        writeToParcel(out, false /* useBlobs */);
+    }
+
+    /**
+     * Read all history files and serialize into a big Parcel. This is to send history files to
+     * Settings app since Settings app can not access /data/system directory.
+     * @param out the output parcel
+     */
+    public void writeToBatteryUsageStatsParcel(Parcel out) {
+        writeToParcel(out, true /* useBlobs */);
+    }
+
+    private void writeToParcel(Parcel out, boolean useBlobs) {
         final long start = SystemClock.uptimeMillis();
         out.writeInt(mFileNumbers.size() - 1);
         for(int i = 0;  i < mFileNumbers.size() - 1; i++) {
@@ -391,7 +408,12 @@
             } catch(Exception e) {
                 Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
             }
-            out.writeByteArray(raw);
+            if (useBlobs) {
+                out.writeBlob(raw);
+            } else {
+                // Avoiding blobs in the check-in file for compatibility
+                out.writeByteArray(raw);
+            }
         }
         if (DEBUG) {
             Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start));
@@ -399,18 +421,29 @@
     }
 
     /**
-     * This is for Settings app, when Settings app receives big history parcel, it call
-     * this method to parse it into list of parcels.
-     * Checkin file also call this method.
+     * This is for the check-in file, which has all history files embedded.
      * @param in the input parcel.
      */
     public void readFromParcel(Parcel in) {
+        readFromParcel(in, false /* useBlobs */);
+    }
+
+    /**
+     * This is for Settings app, when Settings app receives big history parcel, it calls
+     * this method to parse it into list of parcels.
+     * @param in the input parcel.
+     */
+    public void readFromBatteryUsageStatsParcel(Parcel in) {
+        readFromParcel(in, true /* useBlobs */);
+    }
+
+    private void readFromParcel(Parcel in, boolean useBlobs) {
         final long start = SystemClock.uptimeMillis();
         mHistoryParcels = new ArrayList<>();
         final int count = in.readInt();
         for(int i = 0; i < count; i++) {
-            byte[] temp = in.createByteArray();
-            if (temp.length == 0) {
+            byte[] temp = useBlobs ? in.readBlob() : in.createByteArray();
+            if (temp == null || temp.length == 0) {
                 continue;
             }
             Parcel p = Parcel.obtain();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0f1c6f3..a234743 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.UidTraffic;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -36,7 +37,6 @@
 import android.database.ContentObserver;
 import android.hardware.usb.UsbManager;
 import android.location.GnssSignalQuality;
-import android.net.INetworkStatsService;
 import android.net.NetworkStats;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
@@ -83,7 +83,6 @@
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.MutableInt;
-import android.util.Pools;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.Slog;
@@ -1201,12 +1200,21 @@
     }
 
     public BatteryStatsImpl(Clocks clocks) {
+        this(clocks, (File) null);
+    }
+
+    public BatteryStatsImpl(Clocks clocks, File historyDirectory) {
         init(clocks);
         mStartClockTimeMs = clocks.currentTimeMillis();
-        mStatsFile = null;
         mCheckinFile = null;
         mDailyFile = null;
-        mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+        if (historyDirectory == null) {
+            mStatsFile = null;
+            mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+        } else {
+            mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
+            mBatteryStatsHistory = new BatteryStatsHistory(this, historyDirectory, mHistoryBuffer);
+        }
         mHandler = null;
         mPlatformIdleStateCallback = null;
         mMeasuredEnergyRetriever = null;
@@ -11520,8 +11528,6 @@
         }
     }
 
-    private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
-
     private final Object mWifiNetworkLock = new Object();
 
     @GuardedBy("mWifiNetworkLock")
@@ -11539,21 +11545,15 @@
     private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
 
     @VisibleForTesting
-    protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
-        try {
-            if (!ArrayUtils.isEmpty(ifaces)) {
-                INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                        ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-                if (statsService != null) {
-                    return statsService.getDetailedUidStats(ifaces);
-                } else {
-                    Slog.e(TAG, "Failed to get networkStatsService ");
-                }
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
-        }
-        return null;
+    protected NetworkStats readMobileNetworkStatsLocked(
+            @NonNull NetworkStatsManager networkStatsManager) {
+        return networkStatsManager.getMobileUidStats();
+    }
+
+    @VisibleForTesting
+    protected NetworkStats readWifiNetworkStatsLocked(
+            @NonNull NetworkStatsManager networkStatsManager) {
+        return networkStatsManager.getWifiUidStats();
     }
 
     /**
@@ -11561,7 +11561,8 @@
      * @param info The energy information from the WiFi controller.
      */
     public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
-            final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
+            final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
+            @NonNull NetworkStatsManager networkStatsManager) {
         if (DEBUG_ENERGY) {
             Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
         }
@@ -11569,20 +11570,15 @@
         // Grab a separate lock to acquire the network stats, which may do I/O.
         NetworkStats delta = null;
         synchronized (mWifiNetworkLock) {
-            final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
+            final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
             if (latestStats != null) {
-                delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
-                        mNetworkStatsPool.acquire());
-                mNetworkStatsPool.release(mLastWifiNetworkStats);
+                delta = latestStats.subtract(mLastWifiNetworkStats);
                 mLastWifiNetworkStats = latestStats;
             }
         }
 
         synchronized (this) {
             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
-                if (delta != null) {
-                    mNetworkStatsPool.release(delta);
-                }
                 if (mIgnoreNextExternalStats) {
                     // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
                     //  global one) here like we do for display. But I'm not sure it's worth the
@@ -11603,61 +11599,60 @@
             long totalTxPackets = 0;
             long totalRxPackets = 0;
             if (delta != null) {
-                NetworkStats.Entry entry = new NetworkStats.Entry();
-                final int size = delta.size();
-                for (int i = 0; i < size; i++) {
-                    entry = delta.getValues(i, entry);
-
+                for (NetworkStats.Entry entry : delta) {
                     if (DEBUG_ENERGY) {
-                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
-                                + " txPackets=" + entry.txPackets);
+                        Slog.d(TAG, "Wifi uid " + entry.getUid()
+                                + ": delta rx=" + entry.getRxBytes()
+                                + " tx=" + entry.getTxBytes()
+                                + " rxPackets=" + entry.getRxPackets()
+                                + " txPackets=" + entry.getTxPackets());
                     }
 
-                    if (entry.rxBytes == 0 && entry.txBytes == 0) {
+                    if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
                         // Skip the lookup below since there is no work to do.
                         continue;
                     }
 
-                    final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
-                    if (entry.rxBytes != 0) {
-                        u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
-                                entry.rxPackets);
-                        if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
-                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
-                                    entry.rxPackets);
+                    final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
+                            elapsedRealtimeMs, uptimeMs);
+                    if (entry.getRxBytes() != 0) {
+                        u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
+                                entry.getRxPackets());
+                        if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
+                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
+                                    entry.getRxPackets());
                         }
                         mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                                entry.rxBytes);
+                                entry.getRxBytes());
                         mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                                entry.rxPackets);
+                                entry.getRxPackets());
 
                         // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
-                        rxPackets.put(u.getUid(), entry.rxPackets);
+                        rxPackets.put(u.getUid(), entry.getRxPackets());
 
                         // Sum the total number of packets so that the Rx Power can
                         // be evenly distributed amongst the apps.
-                        totalRxPackets += entry.rxPackets;
+                        totalRxPackets += entry.getRxPackets();
                     }
 
-                    if (entry.txBytes != 0) {
-                        u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
-                                entry.txPackets);
-                        if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
-                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
-                                    entry.txPackets);
+                    if (entry.getTxBytes() != 0) {
+                        u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
+                                entry.getTxPackets());
+                        if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
+                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
+                                    entry.getTxPackets());
                         }
                         mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                                entry.txBytes);
+                                entry.getTxBytes());
                         mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                                entry.txPackets);
+                                entry.getTxPackets());
 
                         // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
-                        txPackets.put(u.getUid(), entry.txPackets);
+                        txPackets.put(u.getUid(), entry.getTxPackets());
 
                         // Sum the total number of packets so that the Tx Power can
                         // be evenly distributed amongst the apps.
-                        totalTxPackets += entry.txPackets;
+                        totalTxPackets += entry.getTxPackets();
                     }
 
                     // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
@@ -11685,11 +11680,10 @@
 
                         uidEstimatedConsumptionMah.add(u.getUid(),
                                 mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
-                                        entry.rxPackets, entry.txPackets,
+                                        entry.getRxPackets(), entry.getTxPackets(),
                                         uidRunningMs, uidScanMs, uidBatchScanMs));
                     }
                 }
-                mNetworkStatsPool.release(delta);
                 delta = null;
             }
 
@@ -11921,7 +11915,8 @@
      * Distribute Cell radio energy info and network traffic to apps.
      */
     public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
-            final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
+            final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
+            @NonNull NetworkStatsManager networkStatsManager) {
         if (DEBUG_ENERGY) {
             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
         }
@@ -11935,20 +11930,15 @@
         // Grab a separate lock to acquire the network stats, which may do I/O.
         NetworkStats delta = null;
         synchronized (mModemNetworkLock) {
-            final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
+            final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
             if (latestStats != null) {
-                delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
-                        mNetworkStatsPool.acquire());
-                mNetworkStatsPool.release(mLastModemNetworkStats);
+                delta = latestStats.subtract(mLastModemNetworkStats);
                 mLastModemNetworkStats = latestStats;
             }
         }
 
         synchronized (this) {
             if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
-                if (delta != null) {
-                    mNetworkStatsPool.release(delta);
-                }
                 return;
             }
 
@@ -12013,59 +12003,57 @@
             long totalRxPackets = 0;
             long totalTxPackets = 0;
             if (delta != null) {
-                NetworkStats.Entry entry = new NetworkStats.Entry();
-                final int size = delta.size();
-                for (int i = 0; i < size; i++) {
-                    entry = delta.getValues(i, entry);
-                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
+                for (NetworkStats.Entry entry : delta) {
+                    if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
                         continue;
                     }
 
                     if (DEBUG_ENERGY) {
-                        Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
-                                + " txPackets=" + entry.txPackets);
+                        Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
+                                + entry.getRxBytes() + " tx=" + entry.getTxBytes()
+                                + " rxPackets=" + entry.getRxPackets()
+                                + " txPackets=" + entry.getTxPackets());
                     }
 
-                    totalRxPackets += entry.rxPackets;
-                    totalTxPackets += entry.txPackets;
+                    totalRxPackets += entry.getRxPackets();
+                    totalTxPackets += entry.getTxPackets();
 
-                    final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
-                            entry.rxPackets);
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
-                            entry.txPackets);
-                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                    final Uid u = getUidStatsLocked(
+                            mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
+                            entry.getRxPackets());
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
+                            entry.getTxPackets());
+                    if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
-                                entry.rxBytes, entry.rxPackets);
+                                entry.getRxBytes(), entry.getRxPackets());
                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
-                                entry.txBytes, entry.txPackets);
+                                entry.getTxBytes(), entry.getTxPackets());
                     }
 
                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                            entry.rxBytes);
+                            entry.getRxBytes());
                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                            entry.txBytes);
+                            entry.getTxBytes());
                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                            entry.rxPackets);
+                            entry.getRxPackets());
                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                            entry.txPackets);
+                            entry.getTxPackets());
                 }
 
                 // Now distribute proportional blame to the apps that did networking.
                 long totalPackets = totalRxPackets + totalTxPackets;
                 if (totalPackets > 0) {
-                    for (int i = 0; i < size; i++) {
-                        entry = delta.getValues(i, entry);
-                        if (entry.rxPackets == 0 && entry.txPackets == 0) {
+                    for (NetworkStats.Entry entry : delta) {
+                        if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
                             continue;
                         }
 
-                        final Uid u = getUidStatsLocked(mapUid(entry.uid),
+                        final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
                                 elapsedRealtimeMs, uptimeMs);
 
                         // Distribute total radio active time in to this app.
-                        final long appPackets = entry.rxPackets + entry.txPackets;
+                        final long appPackets = entry.getRxPackets() + entry.getTxPackets();
                         final long appRadioTimeUs =
                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs);
@@ -12086,16 +12074,16 @@
                         if (deltaInfo != null) {
                             ControllerActivityCounterImpl activityCounter =
                                     u.getOrCreateModemControllerActivityLocked();
-                            if (totalRxPackets > 0 && entry.rxPackets > 0) {
-                                final long rxMs = (entry.rxPackets
+                            if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
+                                final long rxMs = (entry.getRxPackets()
                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
                             }
 
-                            if (totalTxPackets > 0 && entry.txPackets > 0) {
+                            if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
                                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
                                         lvl++) {
-                                    long txMs = entry.txPackets
+                                    long txMs = entry.getTxPackets()
                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
                                     txMs /= totalTxPackets;
                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
@@ -12150,7 +12138,6 @@
                             totalEstimatedConsumptionMah);
                 }
 
-                mNetworkStatsPool.release(delta);
                 delta = null;
             }
         }
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 980aec1..7983286 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -21,6 +21,7 @@
 import android.os.BatteryStats;
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
+import android.os.Parcel;
 import android.os.SystemClock;
 import android.os.UidBatteryConsumer;
 import android.util.Log;
@@ -28,6 +29,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -186,16 +188,28 @@
             }
 
             BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;
+
+            // Make a copy of battery history to avoid concurrent modification.
+            Parcel historyBuffer = Parcel.obtain();
+            historyBuffer.appendFrom(batteryStatsImpl.mHistoryBuffer, 0,
+                    batteryStatsImpl.mHistoryBuffer.dataSize());
+
             ArrayList<BatteryStats.HistoryTag> tags = new ArrayList<>(
                     batteryStatsImpl.mHistoryTagPool.size());
             for (Map.Entry<BatteryStats.HistoryTag, Integer> entry :
                     batteryStatsImpl.mHistoryTagPool.entrySet()) {
-                final BatteryStats.HistoryTag tag = entry.getKey();
+                final BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
+                tag.setTo(entry.getKey());
                 tag.poolIdx = entry.getValue();
                 tags.add(tag);
             }
 
-            batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.mHistoryBuffer, tags);
+            final File systemDir =
+                    batteryStatsImpl.mBatteryStatsHistory.getHistoryDirectory().getParentFile();
+            final BatteryStatsHistory batteryStatsHistory =
+                    new BatteryStatsHistory(batteryStatsImpl, systemDir, historyBuffer);
+
+            batteryUsageStatsBuilder.setBatteryHistory(historyBuffer, tags, batteryStatsHistory);
         }
 
         return batteryUsageStatsBuilder.build();
diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java
index 20cf102..e9d55db 100644
--- a/core/java/com/android/internal/os/BinderLatencyObserver.java
+++ b/core/java/com/android/internal/os/BinderLatencyObserver.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.SystemClock;
 import android.util.ArrayMap;
 import android.util.Slog;
@@ -181,7 +180,7 @@
         }
 
         public Handler getHandler() {
-            return new Handler(Looper.getMainLooper());
+            return BackgroundThread.getHandler();
         }
     }
 
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 8d1f16b..44c7f54 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -22,6 +22,7 @@
 import android.app.IActivityManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.type.DefaultMimeMapFactory;
+import android.net.TrafficStats;
 import android.os.Build;
 import android.os.DeadObjectException;
 import android.os.IBinder;
@@ -32,7 +33,6 @@
 import android.util.Slog;
 
 import com.android.internal.logging.AndroidConfig;
-import com.android.server.NetworkManagementSocketTagger;
 
 import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
@@ -254,7 +254,7 @@
         /*
          * Wire socket tagging to traffic stats.
          */
-        NetworkManagementSocketTagger.install();
+        TrafficStats.attachSocketTagger();
 
         initialized = true;
     }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 611f644..f258f84 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -713,7 +713,7 @@
                 "--setuid=1000",
                 "--setgid=1000",
                 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
-                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012",
+                        + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
                 "--capabilities=" + capabilities + "," + capabilities,
                 "--nice-name=system_server",
                 "--runtime-args",
diff --git a/core/java/com/android/internal/security/VerityUtils.java b/core/java/com/android/internal/security/VerityUtils.java
index 8770267..76f7b21 100644
--- a/core/java/com/android/internal/security/VerityUtils.java
+++ b/core/java/com/android/internal/security/VerityUtils.java
@@ -18,28 +18,15 @@
 
 import android.annotation.NonNull;
 import android.os.Build;
-import android.os.SharedMemory;
 import android.os.SystemProperties;
-import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
-import android.util.Pair;
 import android.util.Slog;
-import android.util.apk.ApkSignatureVerifier;
-import android.util.apk.ByteBufferFactory;
-import android.util.apk.SignatureNotFoundException;
-
-import libcore.util.HexEncoding;
 
 import java.io.File;
-import java.io.FileDescriptor;
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.security.DigestException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
 
 /** Provides fsverity related operations. */
 public abstract class VerityUtils {
@@ -57,8 +44,6 @@
     /** SHA256 hash size. */
     private static final int HASH_SIZE_BYTES = 32;
 
-    private static final boolean DEBUG = false;
-
     public static boolean isFsVeritySupported() {
         return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R
                 || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
@@ -123,204 +108,4 @@
     private static native int measureFsverityNative(@NonNull String filePath,
             @NonNull byte[] digest);
     private static native int statxForFsverityNative(@NonNull String filePath);
-
-    /**
-     * Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped.
-     *
-     * @deprecated This is only used for previous fs-verity implementation, and should never be used
-     *             on new devices.
-     * @return {@code SetupResult} that contains the result code, and when success, the
-     *         {@code FileDescriptor} to read all the data from.
-     */
-    @Deprecated
-    public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) {
-        if (DEBUG) {
-            Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath);
-        }
-        SharedMemory shm = null;
-        try {
-            final byte[] signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath);
-            if (signedVerityHash == null) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Skip verity tree generation since there is no signed root hash");
-                }
-                return SetupResult.skipped();
-            }
-
-            Pair<SharedMemory, Integer> result =
-                    generateFsVerityIntoSharedMemory(apkPath, signedVerityHash);
-            shm = result.first;
-            int contentSize = result.second;
-            FileDescriptor rfd = shm.getFileDescriptor();
-            if (rfd == null || !rfd.valid()) {
-                return SetupResult.failed();
-            }
-            return SetupResult.ok(Os.dup(rfd), contentSize);
-        } catch (IOException | SecurityException | DigestException | NoSuchAlgorithmException
-                | SignatureNotFoundException | ErrnoException e) {
-            Slog.e(TAG, "Failed to set up apk verity: ", e);
-            return SetupResult.failed();
-        } finally {
-            if (shm != null) {
-                shm.close();
-            }
-        }
-    }
-
-    /**
-     * {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}.
-     * @deprecated This is only used for previous fs-verity implementation, and should never be used
-     *             on new devices.
-     */
-    @Deprecated
-    public static byte[] generateApkVerityRootHash(@NonNull String apkPath)
-            throws NoSuchAlgorithmException, DigestException, IOException {
-        return ApkSignatureVerifier.generateApkVerityRootHash(apkPath);
-    }
-
-    /**
-     * {@see ApkSignatureVerifier#getVerityRootHash(String)}.
-     * @deprecated This is only used for previous fs-verity implementation, and should never be used
-     *             on new devices.
-     */
-    @Deprecated
-    public static byte[] getVerityRootHash(@NonNull String apkPath)
-            throws IOException, SignatureNotFoundException {
-        return ApkSignatureVerifier.getVerityRootHash(apkPath);
-    }
-
-    /**
-     * Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains
-     * Merkle tree and fsverity headers for the given apk, in the form that can immediately be used
-     * for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has
-     * length equals to the returned {@code Integer}.
-     */
-    private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(String apkPath,
-            @NonNull byte[] expectedRootHash)
-            throws IOException, DigestException, NoSuchAlgorithmException,
-                   SignatureNotFoundException {
-        TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory();
-        byte[] generatedRootHash =
-                ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory);
-        // We only generate Merkle tree once here, so it's important to make sure the root hash
-        // matches the signed one in the apk.
-        if (!Arrays.equals(expectedRootHash, generatedRootHash)) {
-            throw new SecurityException("verity hash mismatch: "
-                    + bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash));
-        }
-
-        int contentSize = shmBufferFactory.getBufferLimit();
-        SharedMemory shm = shmBufferFactory.releaseSharedMemory();
-        if (shm == null) {
-            throw new IllegalStateException("Failed to generate verity tree into shared memory");
-        }
-        if (!shm.setProtect(OsConstants.PROT_READ)) {
-            throw new SecurityException("Failed to set up shared memory correctly");
-        }
-        return Pair.create(shm, contentSize);
-    }
-
-    private static String bytesToString(byte[] bytes) {
-        return HexEncoding.encodeToString(bytes);
-    }
-
-    /**
-     * @deprecated This is only used for previous fs-verity implementation, and should never be used
-     *             on new devices.
-     */
-    @Deprecated
-    public static class SetupResult {
-        /** Result code if verity is set up correctly. */
-        private static final int RESULT_OK = 1;
-
-        /** Result code if signature is not provided. */
-        private static final int RESULT_SKIPPED = 2;
-
-        /** Result code if the setup failed. */
-        private static final int RESULT_FAILED = 3;
-
-        private final int mCode;
-        private final FileDescriptor mFileDescriptor;
-        private final int mContentSize;
-
-        /** @deprecated */
-        @Deprecated
-        public static SetupResult ok(@NonNull FileDescriptor fileDescriptor, int contentSize) {
-            return new SetupResult(RESULT_OK, fileDescriptor, contentSize);
-        }
-
-        /** @deprecated */
-        @Deprecated
-        public static SetupResult skipped() {
-            return new SetupResult(RESULT_SKIPPED, null, -1);
-        }
-
-        /** @deprecated */
-        @Deprecated
-        public static SetupResult failed() {
-            return new SetupResult(RESULT_FAILED, null, -1);
-        }
-
-        private SetupResult(int code, FileDescriptor fileDescriptor, int contentSize) {
-            this.mCode = code;
-            this.mFileDescriptor = fileDescriptor;
-            this.mContentSize = contentSize;
-        }
-
-        public boolean isFailed() {
-            return mCode == RESULT_FAILED;
-        }
-
-        public boolean isOk() {
-            return mCode == RESULT_OK;
-        }
-
-        public @NonNull FileDescriptor getUnownedFileDescriptor() {
-            return mFileDescriptor;
-        }
-
-        public int getContentSize() {
-            return mContentSize;
-        }
-    }
-
-    /** A {@code ByteBufferFactory} that creates a shared memory backed {@code ByteBuffer}. */
-    private static class TrackedShmBufferFactory implements ByteBufferFactory {
-        private SharedMemory mShm;
-        private ByteBuffer mBuffer;
-
-        @Override
-        public ByteBuffer create(int capacity) {
-            try {
-                if (DEBUG) Slog.d(TAG, "Creating shared memory for apk verity");
-                // NB: This method is supposed to be called once according to the contract with
-                // ApkSignatureSchemeV2Verifier.
-                if (mBuffer != null) {
-                    throw new IllegalStateException("Multiple instantiation from this factory");
-                }
-                mShm = SharedMemory.create("apkverity", capacity);
-                if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) {
-                    throw new SecurityException("Failed to set protection");
-                }
-                mBuffer = mShm.mapReadWrite();
-                return mBuffer;
-            } catch (ErrnoException e) {
-                throw new SecurityException("Failed to set protection", e);
-            }
-        }
-
-        public SharedMemory releaseSharedMemory() {
-            if (mBuffer != null) {
-                SharedMemory.unmap(mBuffer);
-                mBuffer = null;
-            }
-            SharedMemory tmp = mShm;
-            mShm = null;
-            return tmp;
-        }
-
-        public int getBufferLimit() {
-            return mBuffer == null ? -1 : mBuffer.limit();
-        }
-    }
 }
diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java
index 3ca3320..4b3af15 100644
--- a/core/java/com/android/internal/util/FileRotator.java
+++ b/core/java/com/android/internal/util/FileRotator.java
@@ -17,7 +17,7 @@
 package com.android.internal.util;
 
 import android.os.FileUtils;
-import android.util.Slog;
+import android.util.Log;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -32,7 +32,6 @@
 import java.util.zip.ZipOutputStream;
 
 import libcore.io.IoUtils;
-import libcore.io.Streams;
 
 /**
  * Utility that rotates files over time, similar to {@code logrotate}. There is
@@ -47,6 +46,8 @@
  * <p>
  * Users must periodically call {@link #maybeRotate(long)} to perform actual
  * rotation. Not inherently thread safe.
+ *
+ * @hide
  */
 public class FileRotator {
     private static final String TAG = "FileRotator";
@@ -110,7 +111,7 @@
             if (!name.startsWith(mPrefix)) continue;
 
             if (name.endsWith(SUFFIX_BACKUP)) {
-                if (LOGD) Slog.d(TAG, "recovering " + name);
+                if (LOGD) Log.d(TAG, "recovering " + name);
 
                 final File backupFile = new File(mBasePath, name);
                 final File file = new File(
@@ -120,7 +121,7 @@
                 backupFile.renameTo(file);
 
             } else if (name.endsWith(SUFFIX_NO_BACKUP)) {
-                if (LOGD) Slog.d(TAG, "recovering " + name);
+                if (LOGD) Log.d(TAG, "recovering " + name);
 
                 final File noBackupFile = new File(mBasePath, name);
                 final File file = new File(
@@ -231,7 +232,7 @@
      * if the write fails.
      */
     private void rewriteSingle(Rewriter rewriter, String name) throws IOException {
-        if (LOGD) Slog.d(TAG, "rewriting " + name);
+        if (LOGD) Log.d(TAG, "rewriting " + name);
 
         final File file = new File(mBasePath, name);
         final File backupFile;
@@ -291,7 +292,7 @@
 
             // read file when it overlaps
             if (info.startMillis <= matchEndMillis && matchStartMillis <= info.endMillis) {
-                if (LOGD) Slog.d(TAG, "reading matching " + name);
+                if (LOGD) Log.d(TAG, "reading matching " + name);
 
                 final File file = new File(mBasePath, name);
                 readFile(file, reader);
@@ -348,7 +349,7 @@
             if (info.isActive()) {
                 if (info.startMillis <= rotateBefore) {
                     // found active file; rotate if old enough
-                    if (LOGD) Slog.d(TAG, "rotating " + name);
+                    if (LOGD) Log.d(TAG, "rotating " + name);
 
                     info.endMillis = currentTimeMillis;
 
@@ -358,7 +359,7 @@
                 }
             } else if (info.endMillis <= deleteBefore) {
                 // found rotated file; delete if old enough
-                if (LOGD) Slog.d(TAG, "deleting " + name);
+                if (LOGD) Log.d(TAG, "deleting " + name);
 
                 final File file = new File(mBasePath, name);
                 file.delete();
@@ -383,7 +384,10 @@
             writer.write(bos);
             bos.flush();
         } finally {
-            FileUtils.sync(fos);
+            try {
+                fos.getFD().sync();
+            } catch (IOException e) {
+            }
             IoUtils.closeQuietly(bos);
         }
     }
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 2b7f8b2..354dd9a 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -4,3 +4,4 @@
 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 *Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
diff --git a/core/java/com/android/internal/util/dump/OWNERS b/core/java/com/android/internal/util/dump/OWNERS
new file mode 100644
index 0000000..ce9302a
--- /dev/null
+++ b/core/java/com/android/internal/util/dump/OWNERS
@@ -0,0 +1,2 @@
+omakoto@google.com
+felipeal@google.com
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 2cfec4b..57a0b48 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -195,7 +195,6 @@
                 "android_util_FileObserver.cpp",
                 "android/opengl/poly_clip.cpp", // TODO: .arm
                 "android/opengl/util.cpp",
-                "android_server_NetworkManagementSocketTagger.cpp",
                 "android_ddm_DdmHandleNativeHeap.cpp",
                 "android_backup_BackupDataInput.cpp",
                 "android_backup_BackupDataOutput.cpp",
@@ -242,9 +241,8 @@
                 "audioflinger-aidl-cpp",
                 "av-types-aidl-cpp",
                 "android.hardware.camera.device@3.2",
+                "libandroid_net",
                 "libandroidicu",
-                "libbpf_android",
-                "libnetdbpf",
                 "libnetdutils",
                 "libmemtrack",
                 "libandroidfw",
@@ -299,6 +297,8 @@
                 "libdl_android",
                 "libtimeinstate",
                 "server_configurable_flags",
+                // TODO: delete when ConnectivityT moves to APEX.
+                "libframework-connectivity-tiramisu-jni",
             ],
             export_shared_lib_headers: [
                 // our headers include libnativewindow's public headers
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 0f98b74..1c4107a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -164,7 +164,6 @@
 extern int register_android_text_Hyphenator(JNIEnv *env);
 extern int register_android_opengl_classes(JNIEnv *env);
 extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
-extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
 extern int register_android_backup_BackupDataInput(JNIEnv *env);
 extern int register_android_backup_BackupDataOutput(JNIEnv *env);
 extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
@@ -1618,7 +1617,6 @@
         REG_JNI(register_android_media_midi),
 
         REG_JNI(register_android_opengl_classes),
-        REG_JNI(register_android_server_NetworkManagementSocketTagger),
         REG_JNI(register_android_ddm_DdmHandleNativeHeap),
         REG_JNI(register_android_backup_BackupDataInput),
         REG_JNI(register_android_backup_BackupDataOutput),
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 832c498..3a9957b 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -62,6 +62,8 @@
 
 ### Graphics ###
 per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
+per-file android_hardware_HardwareBuffer.cpp = file:/graphics/java/android/graphics/OWNERS
+per-file android_hardware_SyncFence.cpp = file:/graphics/java/android/graphics/OWNERS
 
 ### Text ###
 per-file android_text_* = file:/core/java/android/text/OWNERS
@@ -72,6 +74,9 @@
 per-file AndroidRuntime.cpp = calin@google.com, ngeoffray@google.com, oth@google.com
 # Although marked "view" this is mostly graphics stuff
 per-file android_view_* = file:/graphics/java/android/graphics/OWNERS
+# File used for Android Studio layoutlib
+per-file LayoutlibLoader.cpp = file:/graphics/java/android/graphics/OWNERS
+per-file LayoutlibLoader.cpp = diegoperez@google.com, jgaillard@google.com
 
 # Verity
 per-file com_android_internal_security_Verity* = ebiggers@google.com, victorhsieh@google.com
diff --git a/core/jni/android/opengl/OWNERS b/core/jni/android/opengl/OWNERS
new file mode 100644
index 0000000..ce4b907
--- /dev/null
+++ b/core/jni/android/opengl/OWNERS
@@ -0,0 +1 @@
+file:/graphics/java/android/graphics/OWNERS
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index 845d65c..a022842 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -16,20 +16,19 @@
 
 #define LOG_TAG "UsbDeviceConnectionJNI"
 
-#include "utils/Log.h"
-
-#include "jni.h"
+#include <fcntl.h>
 #include <nativehelper/JNIPlatformHelp.h>
-#include "core_jni_helpers.h"
-
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <usbhost/usbhost.h>
+#include <usbhost/usbhost_jni.h>
 
 #include <chrono>
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "utils/Log.h"
 
 using namespace android;
 using namespace std::chrono;
@@ -91,22 +90,8 @@
 static jbyteArray
 android_hardware_UsbDeviceConnection_get_desc(JNIEnv *env, jobject thiz)
 {
-    char buffer[16384];
     int fd = android_hardware_UsbDeviceConnection_get_fd(env, thiz);
-    if (fd < 0) return NULL;
-    lseek(fd, 0, SEEK_SET);
-    int length = read(fd, buffer, sizeof(buffer));
-    if (length < 0) return NULL;
-
-    jbyteArray ret = env->NewByteArray(length);
-    if (ret) {
-        jbyte* bytes = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
-        if (bytes) {
-            memcpy(bytes, buffer, length);
-            env->ReleasePrimitiveArrayCritical(ret, bytes, 0);
-        }
-    }
-    return ret;
+    return usb_jni_read_descriptors(env, fd);
 }
 
 static jboolean
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 3af55fe..d2d7213 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -81,27 +81,37 @@
 
     void binderDied(const wp<hardware::IBinder>& who)
     {
-        if (mObject != NULL) {
-            JNIEnv* env = javavm_to_jnienv(mVM);
+        JNIEnv* env = javavm_to_jnienv(mVM);
 
-            env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, mObject, mCookie);
+        // Serialize with our containing HwBinderDeathRecipientList so that we can't
+        // delete the global ref on object while the list is being iterated.
+        sp<HwBinderDeathRecipientList> list = mList.promote();
+        if (list == nullptr) return;
+
+        jobject object;
+        {
+            AutoMutex _l(list->lock());
+
+            // this function now owns the global ref - to the rest of the code, it looks like
+            // this binder already died, but we won't actually delete the reference until
+            // the Java code has processed the death
+            object = mObject;
+
+            // Demote from strong ref to weak for after binderDied() has been delivered,
+            // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
+            mObjectWeak = env->NewWeakGlobalRef(mObject);
+            mObject = nullptr;
+        }
+
+        if (object != nullptr) {
+            env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice,
+                                      object, mCookie);
             if (env->ExceptionCheck()) {
                 ALOGE("Uncaught exception returned from death notification.");
                 env->ExceptionClear();
             }
 
-            // Serialize with our containing HwBinderDeathRecipientList so that we can't
-            // delete the global ref on mObject while the list is being iterated.
-            sp<HwBinderDeathRecipientList> list = mList.promote();
-            if (list != NULL) {
-                AutoMutex _l(list->lock());
-
-                // Demote from strong ref to weak after binderDied() has been delivered,
-                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
-                mObjectWeak = env->NewWeakGlobalRef(mObject);
-                env->DeleteGlobalRef(mObject);
-                mObject = NULL;
-            }
+            env->DeleteGlobalRef(object);
         }
     }
 
@@ -115,7 +125,7 @@
         }
     }
 
-    bool matches(jobject obj) {
+    bool matchesLocked(jobject obj) {
         bool result;
         JNIEnv* env = javavm_to_jnienv(mVM);
 
@@ -129,7 +139,7 @@
         return result;
     }
 
-    void warnIfStillLive() {
+    void warnIfStillLiveLocked() {
         if (mObject != NULL) {
             // Okay, something is wrong -- we have a hard reference to a live death
             // recipient on the VM side, but the list is being torn down.
@@ -176,7 +186,7 @@
     AutoMutex _l(mLock);
 
     for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
-        deathRecipient->warnIfStillLive();
+        deathRecipient->warnIfStillLiveLocked();
     }
 }
 
@@ -201,7 +211,7 @@
     AutoMutex _l(mLock);
 
     for(auto iter = mList.rbegin(); iter != mList.rend(); iter++) {
-        if ((*iter)->matches(recipient)) {
+        if ((*iter)->matchesLocked(recipient)) {
             return (*iter);
         }
     }
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
deleted file mode 100644
index afad08a..0000000
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "NMST_QTagUidNative"
-#include <utils/Log.h>
-
-#include <nativehelper/JNIPlatformHelp.h>
-
-#include "jni.h"
-#include <utils/misc.h>
-#include <cutils/qtaguid.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-namespace android {
-
-static jint QTagUid_tagSocketFd(JNIEnv* env, jclass,
-                                jobject fileDescriptor,
-                                jint tagNum, jint uid) {
-  int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-  if (env->ExceptionCheck()) {
-    ALOGE("Can't get FileDescriptor num");
-    return (jint)-1;
-  }
-
-  int res = qtaguid_tagSocket(userFd, tagNum, uid);
-  if (res < 0) {
-    return (jint)-errno;
-  }
-  return (jint)res;
-}
-
-static jint QTagUid_untagSocketFd(JNIEnv* env, jclass,
-                                  jobject fileDescriptor) {
-  int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-  if (env->ExceptionCheck()) {
-    ALOGE("Can't get FileDescriptor num");
-    return (jint)-1;
-  }
-
-  int res = qtaguid_untagSocket(userFd);
-  if (res < 0) {
-    return (jint)-errno;
-  }
-  return (jint)res;
-}
-
-static jint QTagUid_setCounterSet(JNIEnv* env, jclass,
-                                  jint setNum, jint uid) {
-
-  int res = qtaguid_setCounterSet(setNum, uid);
-  if (res < 0) {
-    return (jint)-errno;
-  }
-  return (jint)res;
-}
-
-static jint QTagUid_deleteTagData(JNIEnv* env, jclass,
-                                  jint tagNum, jint uid) {
-
-  int res = qtaguid_deleteTagData(tagNum, uid);
-  if (res < 0) {
-    return (jint)-errno;
-  }
-  return (jint)res;
-}
-
-static const JNINativeMethod gQTagUidMethods[] = {
-  { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)QTagUid_tagSocketFd},
-  { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)QTagUid_untagSocketFd},
-  { "native_setCounterSet", "(II)I", (void*)QTagUid_setCounterSet},
-  { "native_deleteTagData", "(II)I", (void*)QTagUid_deleteTagData},
-};
-
-int register_android_server_NetworkManagementSocketTagger(JNIEnv* env) {
-  return jniRegisterNativeMethods(env, "com/android/server/NetworkManagementSocketTagger", gQTagUidMethods, NELEM(gQTagUidMethods));
-}
-
-};
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 61b91dd..13ca133 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -873,7 +873,7 @@
             const char* exceptionToThrow;
             char msg[128];
             // TransactionTooLargeException is a checked exception, only throw from certain methods.
-            // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
+            // TODO(b/28321379): Transaction size is the most common cause for FAILED_TRANSACTION
             //        but it is not the only one.  The Binder driver can return BR_FAILED_REPLY
             //        for other reasons also, such as if the transaction is malformed or
             //        refers to an FD that has been closed.  We should change the driver
@@ -890,8 +890,9 @@
                 exceptionToThrow = (canThrowRemoteException)
                         ? "android/os/DeadObjectException"
                         : "java/lang/RuntimeException";
-                snprintf(msg, sizeof(msg)-1,
-                        "Transaction failed on small parcel; remote process probably died");
+                snprintf(msg, sizeof(msg) - 1,
+                         "Transaction failed on small parcel; remote process probably died, but "
+                         "this could also be caused by running out of binder buffer space");
             }
             jniThrowException(env, exceptionToThrow, msg);
         } break;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aacf700..5971670 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -202,6 +202,8 @@
  */
 static constexpr int STORAGE_DIR_CHECK_TIMEOUT_US = 1000 * 1000 * 60 * 5;
 
+static void WaitUntilDirReady(const std::string& target, fail_fn_t fail_fn);
+
 /**
  * A helper class containing accounting information for USAPs.
  */
@@ -1249,7 +1251,11 @@
     auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
     auto cePath = StringPrintf("%s/user", volPath.c_str());
     auto dePath = StringPrintf("%s/user_de", volPath.c_str());
+    // Wait until dir user is created.
+    WaitUntilDirReady(cePath.c_str(), fail_fn);
     MountAppDataTmpFs(cePath.c_str(), fail_fn);
+    // Wait until dir user_de is created.
+    WaitUntilDirReady(dePath.c_str(), fail_fn);
     MountAppDataTmpFs(dePath.c_str(), fail_fn);
   }
   closedir(dir);
@@ -1620,7 +1626,7 @@
         }
         // Also prefetch standalone system server jars. The reason for doing this here is the same
         // as above.
-        env->CallStaticObjectMethod(gZygoteInitClass, gPrefetchStandaloneSystemServerJars);
+        env->CallStaticVoidMethod(gZygoteInitClass, gPrefetchStandaloneSystemServerJars);
         if (env->ExceptionCheck()) {
             env->ExceptionClear();
         }
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 931ef44..43d2439 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -17,7 +17,8 @@
 per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS
 
 # Biometrics
-kchyn@google.com
+jaggies@google.com
+jbolinger@google.com
 
 # Launcher
 hyunyoungs@google.com
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 998ec96..51e150e 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -249,7 +249,8 @@
 
     optional android.service.NetworkStatsServiceDumpProto netstats = 3001 [
         (section).type = SECTION_DUMPSYS,
-        (section).args = "netstats --proto"
+        (section).args = "netstats --proto",
+        (section).userdebug_and_eng_only = true
     ];
 
     optional android.providers.settings.SettingsServiceDumpProto settings = 3002 [
diff --git a/core/proto/android/service/netstats.proto b/core/proto/android/service/netstats.proto
index c8cdfdd..ba2b6d6b 100644
--- a/core/proto/android/service/netstats.proto
+++ b/core/proto/android/service/netstats.proto
@@ -17,15 +17,11 @@
 syntax = "proto2";
 package android.service;
 
-import "frameworks/base/core/proto/android/privacy.proto";
-
 option java_multiple_files = true;
 option java_outer_classname = "NetworkStatsServiceProto";
 
 // Represents dumpsys from NetworkStatsService (netstats).
 message NetworkStatsServiceDumpProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     repeated NetworkInterfaceProto active_interfaces = 1;
 
     repeated NetworkInterfaceProto active_uid_interfaces = 2;
@@ -45,8 +41,6 @@
 
 // Corresponds to NetworkStatsService.mActiveIfaces/mActiveUidIfaces.
 message NetworkInterfaceProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     // Name of the network interface (eg: wlan).
     optional string interface = 1;
 
@@ -55,26 +49,14 @@
 
 // Corresponds to NetworkIdentitySet.
 message NetworkIdentitySetProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     repeated NetworkIdentityProto identities = 1;
 }
 
 // Corresponds to NetworkIdentity.
 message NetworkIdentityProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     // Constants from ConnectivityManager.TYPE_*.
     optional int32 type = 1;
 
-    // Full subscriber ID on eng builds. The IMSI is scrubbed on user & userdebug
-    // builds to only include the info about the GSM network operator (the info
-    // that uniquely identifies the subscriber is removed).
-    optional string subscriber_id = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
-
-    // Name of the network (eg: MyWifi).
-    optional string network_id = 3 [ (android.privacy).dest = DEST_EXPLICIT ];
-
     optional bool roaming = 4;
 
     optional bool metered = 5;
@@ -86,8 +68,6 @@
 
 // Corresponds to NetworkStatsRecorder.
 message NetworkStatsRecorderProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     optional int64 pending_total_bytes = 1;
 
     optional NetworkStatsCollectionProto complete_history = 2;
@@ -95,15 +75,11 @@
 
 // Corresponds to NetworkStatsCollection.
 message NetworkStatsCollectionProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     repeated NetworkStatsCollectionStatsProto stats = 1;
 }
 
 // Corresponds to NetworkStatsCollection.mStats.
 message NetworkStatsCollectionStatsProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     optional NetworkStatsCollectionKeyProto key = 1;
 
     optional NetworkStatsHistoryProto history = 2;
@@ -111,8 +87,6 @@
 
 // Corresponds to NetworkStatsCollection.Key.
 message NetworkStatsCollectionKeyProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     optional NetworkIdentitySetProto identity = 1;
 
     optional int32 uid = 2;
@@ -124,8 +98,6 @@
 
 // Corresponds to NetworkStatsHistory.
 message NetworkStatsHistoryProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     // Duration for this bucket in milliseconds.
     optional int64 bucket_duration_ms = 1;
 
@@ -134,8 +106,6 @@
 
 // Corresponds to each bucket in NetworkStatsHistory.
 message NetworkStatsHistoryBucketProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
     // Bucket start time in milliseconds since epoch.
     optional int64 bucket_start_ms = 1;
 
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 6063062..c42517d 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -37,7 +37,6 @@
     visibility: [":__subpackages__"],
     license_kinds: [
         "SPDX-license-identifier-Apache-2.0",
-        "SPDX-license-identifier-GPL",
     ],
     license_text: [
         "NOTICE",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6ecfcec..111b694 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1945,6 +1945,11 @@
     <permission android:name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi @hide Allows an application to manage ethernet networks.
+         <p>Not for use by third-party or privileged applications. -->
+    <permission android:name="android.permission.MANAGE_ETHERNET_NETWORKS"
+        android:protectionLevel="signature" />
+
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
     <!-- ======================================= -->
@@ -2114,8 +2119,9 @@
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @hide Allows internal management of Bluetooth state when on wireless consent mode.
-         <p>Not for use by third-party applications. -->
+    <!-- @SystemApi Allows internal management of Bluetooth state when on wireless consent mode.
+         <p>Not for use by third-party applications.
+         @hide -->
     <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED"
         android:protectionLevel="signature" />
 
@@ -2723,6 +2729,10 @@
     <permission android:name="android.permission.INTERACT_ACROSS_PROFILES"
         android:protectionLevel="signature|appop" />
 
+    <!-- @SystemApi @hide Allows starting activities across profiles in the same profile group. -->
+    <permission android:name="android.permission.START_CROSS_PROFILE_ACTIVITIES"
+                android:protectionLevel="signature|role" />
+
     <!-- Allows configuring apps to have the INTERACT_ACROSS_PROFILES permission so that they can
          interact across profiles in the same profile group.
          @hide -->
@@ -3448,6 +3458,13 @@
     <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
         android:protectionLevel="signature|privileged|development" />
 
+    <!-- @hide @SystemApi Must be required by a
+         {@link com.android.service.tracing.TraceReportService}, to ensure that only the system
+         can bind to it.
+        <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.BIND_TRACE_REPORT_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- @hide @SystemApi @TestApi
          Allow an application to approve incident and bug reports to be
          shared off-device.  There can be only one application installed on the
@@ -6234,6 +6251,11 @@
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
+        <service android:name="com.android.server.SmartStorageMaintIdler"
+                android:exported="true"
+                android:permission="android.permission.BIND_JOB_SERVICE" >
+        </service>
+
         <service android:name="com.android.server.ZramWriteback"
                  android:exported="false"
                  android:permission="android.permission.BIND_JOB_SERVICE" >
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2f33498..ba647d7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -134,9 +134,6 @@
          be sent during a change to the audio output device. -->
     <bool name="config_sendAudioBecomingNoisy">true</bool>
 
-    <!-- Whether Hearing Aid profile is supported -->
-    <bool name="config_hearing_aid_profile_supported">false</bool>
-
     <!-- Flag to disable all transition animations -->
     <bool name="config_disableTransitionAnimation">false</bool>
 
@@ -404,10 +401,6 @@
     <string-array translatable="false" name="config_tether_bluetooth_regexs">
     </string-array>
 
-    <!-- Max number of Bluetooth tethering connections allowed. If this is
-         updated config_tether_dhcp_range has to be updated appropriately. -->
-    <integer translatable="false" name="config_max_pan_devices">5</integer>
-
     <!-- This setting is deprecated, please use
          com.android.networkstack.tethering.R.array.config_dhcp_range instead. -->
     <string-array translatable="false" name="config_tether_dhcp_range">
@@ -1820,53 +1813,38 @@
     <!-- Integer to set a max latency the accelerometer will batch sensor requests with. -->
     <integer name="config_flipToScreenOffMaxLatencyMicros">2000000</integer>
 
-    <!-- Boolean indicating if current platform supports bluetooth SCO for off call
-    use cases -->
+    <!-- Note: This config is deprecated
+          Boolean indicating if current platform supports bluetooth SCO for off call
+          use cases
+    -->
     <bool name="config_bluetooth_sco_off_call">true</bool>
 
-    <!-- Boolean indicating if current platform supports bluetooth wide band
-         speech -->
-    <bool name="config_bluetooth_wide_band_speech">true</bool>
-
-    <!-- Boolean indicating if current platform need do one-time bluetooth address
-         re-validation -->
+    <!-- Note: This config is deprecated
+          Boolean indicating if current platform need do one-time bluetooth address
+          re-validation
+    -->
     <bool name="config_bluetooth_address_validation">false</bool>
 
-    <!-- Boolean indicating if current platform supports BLE peripheral mode -->
-    <bool name="config_bluetooth_le_peripheral_mode_supported">false</bool>
-
-    <!-- Boolean indicating if current platform supports HFP inband ringing -->
-    <bool name="config_bluetooth_hfp_inband_ringing_support">false</bool>
-
-    <!-- Max number of scan filters supported by blutooth controller. 0 if the
-         device does not support hardware scan filters-->
-    <integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer>
-
-    <!-- Max number of advertisers supported by bluetooth controller. 0 if the
-         device does not support multiple advertisement-->
-    <integer translatable="false" name="config_bluetooth_max_advertisers">0</integer>
-
-    <!-- Idle current for bluetooth controller. 0 by default-->
+    <!-- Note: This config is deprecated, use BluetoothProperties instead.
+         Idle current for bluetooth controller. 0 by default
+    -->
     <integer translatable="false" name="config_bluetooth_idle_cur_ma">0</integer>
 
-    <!-- Rx current for bluetooth controller. 0 by default-->
+    <!-- Note: This config is deprecated, use BluetoothProperties instead.
+         Rx current for bluetooth controller. 0 by default
+    -->
     <integer translatable="false" name="config_bluetooth_rx_cur_ma">0</integer>
 
-    <!-- Tx current for bluetooth controller. 0 by default-->
+    <!-- Note: This config is deprecated, use BluetoothProperties instead.
+         Tx current for bluetooth controller. 0 by default
+    -->
     <integer translatable="false" name="config_bluetooth_tx_cur_ma">0</integer>
 
-    <!-- Operating volatage for bluetooth controller. 0 by default-->
+    <!-- Note: This config is deprecated, use BluetoothProperties instead.
+         Operating volatage for bluetooth controller. 0 by default
+    -->
     <integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer>
 
-    <!-- Max number of connected audio devices supported by Bluetooth stack -->
-    <integer name="config_bluetooth_max_connected_audio_devices">5</integer>
-
-    <!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
-    <bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
-
-    <!-- Enabling autoconnect over pan -->
-    <bool name="config_bluetooth_pan_enable_autoconnect">false</bool>
-
     <!-- The default data-use polling period. -->
     <integer name="config_datause_polling_period_sec">600</integer>
 
@@ -2007,10 +1985,6 @@
     <!-- The name of the package that will be allowed to change its components' label/icon. -->
     <string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
 
-    <!-- Enable/disable default bluetooth profiles:
-        HSP_AG, ObexObjectPush, Audio, NAP -->
-    <bool name="config_bluetooth_default_profiles">true</bool>
-
     <!-- IP address of the dns server to use if nobody else suggests one -->
     <string name="config_default_dns_server" translatable="false">8.8.8.8</string>
 
@@ -4141,8 +4115,6 @@
     <!-- Component name that should be granted Notification Assistant access -->
     <string name="config_defaultAssistantAccessComponent" translatable="false">android.ext.services/android.ext.services.notification.Assistant</string>
 
-    <bool name="config_supportBluetoothPersistedState">true</bool>
-
     <bool name="config_keepRestrictedProfilesInBackground">true</bool>
 
     <!-- Cellular network service package name to bind to by default. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2403a60..6ef5bd4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3200,11 +3200,87 @@
     <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
     <public type="string" name="config_defaultRingtoneVibrationSound" id="0x0104003b" />
 
+    <!-- ===============================================================
+         Resources added in version T of the platform
+
+         NOTE: add <public> elements within a <staging-public-group> like so:
+
+         <staging-public-group type="attr" first-id="0x01ff0000">
+             <public name="exampleAttr1" />
+             <public name="exampleAttr2" />
+         </staging-public-group>
+
+         To add a new <staging-public-group> block, find the id value for the
+         last <staging-public-group> block defined for thie API level, and
+         subtract 0x00010000 from it to get to the id of the new block.
+
+         For example, if the block closest to the end of this file has an id
+         of 0x01ee0000, the id of the new block should be 0x01ed0000
+         (0x01ee0000 - 0x00010000 = 0x01ed0000).
+         =============================================================== -->
+    <eat-comment />
+
+    <staging-public-group type="attr" first-id="0x01df0000">
+    </staging-public-group>
+
+    <staging-public-group type="id" first-id="0x01de0000">
+    </staging-public-group>
+
+    <staging-public-group type="style" first-id="0x0dfd0000">
+    </staging-public-group>
+
+    <staging-public-group type="string" first-id="0x0dfc0000">
+    </staging-public-group>
+
+    <staging-public-group type="dimen" first-id="0x01db0000">
+    </staging-public-group>
+
+    <staging-public-group type="color" first-id="0x01da0000">
+    </staging-public-group>
+
+    <staging-public-group type="array" first-id="0x01d90000">
+      <!-- @hide @SystemApi -->
+      <public name="config_optionalIpSecAlgorithms" />
+    </staging-public-group>
+
+    <staging-public-group type="drawable" first-id="0x01d80000">
+    </staging-public-group>
+
+    <staging-public-group type="layout" first-id="0x01d70000">
+    </staging-public-group>
+
+    <staging-public-group type="anim" first-id="0x01d60000">
+    </staging-public-group>
+
+    <staging-public-group type="animator" first-id="0x01d50000">
+    </staging-public-group>
+
+    <staging-public-group type="interpolator" first-id="0x01d40000">
+    </staging-public-group>
+
+    <staging-public-group type="mipmap" first-id="0x01d30000">
+    </staging-public-group>
+
+    <staging-public-group type="integer" first-id="0x01d20000">
+    </staging-public-group>
+
+    <staging-public-group type="transition" first-id="0x01d10000">
+    </staging-public-group>
+
+    <staging-public-group type="raw" first-id="0x01d00000">
+    </staging-public-group>
+
+    <staging-public-group type="bool" first-id="0x01cf0000">
+    </staging-public-group>
+
+    <staging-public-group type="fraction" first-id="0x01ce0000">
+    </staging-public-group>
+
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
 
        Any new items (attrs, styles, ids, etc.) *must* be added in a
-       public-group block, as the preceding comment explains.
+       staging-public-group block, as the preceding comment explains.
        Items added outside of a group may have their value recalculated
        every time something new is added to this file.
        =============================================================== -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4db6499..590fcf4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -278,8 +278,6 @@
   <java-symbol type="bool" name="config_flipToScreenOffEnabled" />
   <java-symbol type="integer" name="config_flipToScreenOffMaxLatencyMicros" />
   <java-symbol type="bool" name="config_bluetooth_sco_off_call" />
-  <java-symbol type="bool" name="config_bluetooth_le_peripheral_mode_supported" />
-  <java-symbol type="bool" name="config_bluetooth_hfp_inband_ringing_support" />
   <java-symbol type="bool" name="config_cellBroadcastAppLinks" />
   <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
   <java-symbol type="bool" name="config_disableTransitionAnimation" />
@@ -343,7 +341,6 @@
   <java-symbol type="integer" name="config_timeZoneRulesCheckRetryCount" />
   <java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
   <java-symbol type="bool" name="config_enableScreenshotChord" />
-  <java-symbol type="bool" name="config_bluetooth_default_profiles" />
   <java-symbol type="bool" name="config_enableWifiDisplay" />
   <java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
   <java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
@@ -417,9 +414,6 @@
   <java-symbol type="dimen" name="config_pictureInPictureMaxAspectRatio" />
   <java-symbol type="integer" name="config_pictureInPictureMaxNumberOfActions" />
   <java-symbol type="dimen" name="config_closeToSquareDisplayMaxAspectRatio" />
-  <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
-  <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
-  <java-symbol type="integer" name="config_bluetooth_max_connected_audio_devices" />
   <java-symbol type="integer" name="config_burnInProtectionMinHorizontalOffset" />
   <java-symbol type="integer" name="config_burnInProtectionMaxHorizontalOffset" />
   <java-symbol type="integer" name="config_burnInProtectionMinVerticalOffset" />
@@ -429,9 +423,6 @@
   <java-symbol type="integer" name="config_bluetooth_rx_cur_ma" />
   <java-symbol type="integer" name="config_bluetooth_tx_cur_ma" />
   <java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" />
-  <java-symbol type="bool" name="config_bluetooth_pan_enable_autoconnect" />
-  <java-symbol type="bool" name="config_bluetooth_reload_supported_profiles_when_enabled" />
-  <java-symbol type="bool" name="config_hearing_aid_profile_supported" />
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_drawLockTimeoutMillis" />
   <java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
@@ -450,7 +441,6 @@
   <java-symbol type="integer" name="config_wakeUpToLastStateTimeoutMillis" />
   <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" />
   <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" />
-  <java-symbol type="integer" name="config_max_pan_devices" />
   <java-symbol type="integer" name="config_ntpPollingInterval" />
   <java-symbol type="integer" name="config_ntpPollingIntervalShorter" />
   <java-symbol type="integer" name="config_ntpRetry" />
@@ -3782,8 +3772,6 @@
 
   <java-symbol type="string" name="config_defaultAssistantAccessComponent" />
 
-  <java-symbol type="bool" name="config_supportBluetoothPersistedState" />
-
   <java-symbol type="string" name="slices_permission_request" />
 
   <java-symbol type="string" name="screenshot_edit" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 4c20ae1..d1d86a7 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -154,9 +154,9 @@
     <!-- Israel: 4 digits, known premium codes listed -->
     <shortcode country="il" pattern="\\d{4}" premium="4422|4545" />
 
-    <!-- Italy: 5 digits (premium=4xxxx), plus EU:
-         http://clients.txtnation.com/attachments/token/di5kfblvubttvlw/?name=Italy_CASP_EN.pdf -->
-    <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503" standard="43\\d{3}" />
+    <!-- Italy: 5 digits (premium=41xxx,42xxx), plus EU:
+         https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006B0001PDFE.pdf -->
+    <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503|40\\d{0,12}" standard="430\\d{2}|431\\d{2}|434\\d{4}|435\\d{4}|439\\d{7}" />
 
     <!-- Japan: 8083 used by SOFTBANK_DCB_2 -->
     <shortcode country="jp" pattern="\\d{1,5}" free="8083" />
diff --git a/core/tests/bandwidthtests/Android.bp b/core/tests/bandwidthtests/Android.bp
index f1ecd45..d0b42f7 100644
--- a/core/tests/bandwidthtests/Android.bp
+++ b/core/tests/bandwidthtests/Android.bp
@@ -23,6 +23,7 @@
 
 android_test {
     name: "BandwidthTests",
+    defaults: ["framework-connectivity-test-defaults"],
     // Include all test java files.
     srcs: ["src/**/*.java"],
     libs: [
diff --git a/core/tests/benchmarks/Android.bp b/core/tests/benchmarks/Android.bp
index 4cd5467..0888776 100644
--- a/core/tests/benchmarks/Android.bp
+++ b/core/tests/benchmarks/Android.bp
@@ -27,6 +27,7 @@
 
 java_library {
     name: "frameworks-base-core-benchmarks",
+    defaults: ["framework-connectivity-test-defaults"],
     installable: true,
     srcs: ["src/**/*.java"],
     libs: ["caliper-api-target"],
diff --git a/core/tests/bluetoothtests/Android.bp b/core/tests/bluetoothtests/Android.bp
deleted file mode 100644
index 68416dd..0000000
--- a/core/tests/bluetoothtests/Android.bp
+++ /dev/null
@@ -1,24 +0,0 @@
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-android_test {
-    name: "BluetoothTests",
-    // Include all test java files.
-    srcs: ["src/**/*.java"],
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
-    static_libs: [
-        "junit",
-        "modules-utils-bytesmatcher",
-    ],
-    platform_apis: true,
-    certificate: "platform",
-}
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
deleted file mode 100644
index 75583d5..0000000
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.bluetooth.tests"
-          android:sharedUserId="android.uid.bluetooth" >
-
-    <uses-permission android:name="android.permission.BLUETOOTH" />
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
-    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
-    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
-    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
-    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
-    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
-    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
-    <uses-permission android:name="android.permission.RECEIVE_SMS" />
-    <uses-permission android:name="android.permission.READ_SMS"/>
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
-    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
-
-    <application >
-        <uses-library android:name="android.test.runner" />
-    </application>
-    <instrumentation android:name="android.bluetooth.BluetoothTestRunner"
-            android:targetPackage="com.android.bluetooth.tests"
-            android:label="Bluetooth Tests" />
-    <instrumentation android:name="android.bluetooth.BluetoothInstrumentation"
-            android:targetPackage="com.android.bluetooth.tests"
-            android:label="Bluetooth Test Utils" />
-
-</manifest>
diff --git a/core/tests/bluetoothtests/AndroidTest.xml b/core/tests/bluetoothtests/AndroidTest.xml
deleted file mode 100644
index f93c4eb..0000000
--- a/core/tests/bluetoothtests/AndroidTest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2020 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Config for Bluetooth test cases">
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-suite-tag" value="apct-instrumentation"/>
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="BluetoothTests.apk" />
-    </target_preparer>
-
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-tag" value="BluetoothTests"/>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.bluetooth.tests" />
-        <option name="hidden-api-checks" value="false"/>
-        <option name="runner" value="android.bluetooth.BluetoothTestRunner"/>
-    </test>
-</configuration>
diff --git a/core/tests/bluetoothtests/OWNERS b/core/tests/bluetoothtests/OWNERS
deleted file mode 100644
index 98bb877..0000000
--- a/core/tests/bluetoothtests/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /core/java/android/bluetooth/OWNERS
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
deleted file mode 100644
index bd55426..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link BluetoothCodecConfig}.
- * <p>
- * To run this test, use:
- * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
- */
-public class BluetoothCodecConfigTest extends TestCase {
-    private static final int[] kCodecTypeArray = new int[] {
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID,
-    };
-    private static final int[] kCodecPriorityArray = new int[] {
-        BluetoothCodecConfig.CODEC_PRIORITY_DISABLED,
-        BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-        BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
-    };
-    private static final int[] kSampleRateArray = new int[] {
-        BluetoothCodecConfig.SAMPLE_RATE_NONE,
-        BluetoothCodecConfig.SAMPLE_RATE_44100,
-        BluetoothCodecConfig.SAMPLE_RATE_48000,
-        BluetoothCodecConfig.SAMPLE_RATE_88200,
-        BluetoothCodecConfig.SAMPLE_RATE_96000,
-        BluetoothCodecConfig.SAMPLE_RATE_176400,
-        BluetoothCodecConfig.SAMPLE_RATE_192000,
-    };
-    private static final int[] kBitsPerSampleArray = new int[] {
-        BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
-        BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-        BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-        BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-    };
-    private static final int[] kChannelModeArray = new int[] {
-        BluetoothCodecConfig.CHANNEL_MODE_NONE,
-        BluetoothCodecConfig.CHANNEL_MODE_MONO,
-        BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-    };
-    private static final long[] kCodecSpecific1Array = new long[] { 1000, 1001, 1002, 1003, };
-    private static final long[] kCodecSpecific2Array = new long[] { 2000, 2001, 2002, 2003, };
-    private static final long[] kCodecSpecific3Array = new long[] { 3000, 3001, 3002, 3003, };
-    private static final long[] kCodecSpecific4Array = new long[] { 4000, 4001, 4002, 4003, };
-
-    private static final int kTotalConfigs = kCodecTypeArray.length * kCodecPriorityArray.length *
-        kSampleRateArray.length * kBitsPerSampleArray.length * kChannelModeArray.length *
-        kCodecSpecific1Array.length * kCodecSpecific2Array.length * kCodecSpecific3Array.length *
-        kCodecSpecific4Array.length;
-
-    private int selectCodecType(int configId) {
-        int left = kCodecTypeArray.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kCodecTypeArray.length;
-        return kCodecTypeArray[index];
-    }
-
-    private int selectCodecPriority(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kCodecPriorityArray.length;
-        return kCodecPriorityArray[index];
-    }
-
-    private int selectSampleRate(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kSampleRateArray.length;
-        return kSampleRateArray[index];
-    }
-
-    private int selectBitsPerSample(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
-            kBitsPerSampleArray.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kBitsPerSampleArray.length;
-        return kBitsPerSampleArray[index];
-    }
-
-    private int selectChannelMode(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
-            kBitsPerSampleArray.length * kChannelModeArray.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kChannelModeArray.length;
-        return kChannelModeArray[index];
-    }
-
-    private long selectCodecSpecific1(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
-            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kCodecSpecific1Array.length;
-        return kCodecSpecific1Array[index];
-    }
-
-    private long selectCodecSpecific2(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
-            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
-            kCodecSpecific2Array.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kCodecSpecific2Array.length;
-        return kCodecSpecific2Array[index];
-    }
-
-    private long selectCodecSpecific3(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
-            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
-            kCodecSpecific2Array.length * kCodecSpecific3Array.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kCodecSpecific3Array.length;
-        return kCodecSpecific3Array[index];
-    }
-
-    private long selectCodecSpecific4(int configId) {
-        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
-            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
-            kCodecSpecific2Array.length * kCodecSpecific3Array.length *
-            kCodecSpecific4Array.length;
-        int right = kTotalConfigs / left;
-        int index = configId / right;
-        index = index % kCodecSpecific4Array.length;
-        return kCodecSpecific4Array[index];
-    }
-
-    @SmallTest
-    public void testBluetoothCodecConfig_valid_get_methods() {
-
-        for (int config_id = 0; config_id < kTotalConfigs; config_id++) {
-            int codec_type = selectCodecType(config_id);
-            int codec_priority = selectCodecPriority(config_id);
-            int sample_rate = selectSampleRate(config_id);
-            int bits_per_sample = selectBitsPerSample(config_id);
-            int channel_mode = selectChannelMode(config_id);
-            long codec_specific1 = selectCodecSpecific1(config_id);
-            long codec_specific2 = selectCodecSpecific2(config_id);
-            long codec_specific3 = selectCodecSpecific3(config_id);
-            long codec_specific4 = selectCodecSpecific4(config_id);
-
-            BluetoothCodecConfig bcc = buildBluetoothCodecConfig(codec_type, codec_priority,
-                                                                sample_rate, bits_per_sample,
-                                                                channel_mode, codec_specific1,
-                                                                codec_specific2, codec_specific3,
-                                                                codec_specific4);
-
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
-                assertTrue(bcc.isMandatoryCodec());
-            } else {
-                assertFalse(bcc.isMandatoryCodec());
-            }
-
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
-                assertEquals("SBC", bcc.getCodecName());
-            }
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC) {
-                assertEquals("AAC", bcc.getCodecName());
-            }
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX) {
-                assertEquals("aptX", bcc.getCodecName());
-            }
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD) {
-                assertEquals("aptX HD", bcc.getCodecName());
-            }
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC) {
-                assertEquals("LDAC", bcc.getCodecName());
-            }
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
-                assertEquals("INVALID CODEC", bcc.getCodecName());
-            }
-
-            assertEquals(codec_type, bcc.getCodecType());
-            assertEquals(codec_priority, bcc.getCodecPriority());
-            assertEquals(sample_rate, bcc.getSampleRate());
-            assertEquals(bits_per_sample, bcc.getBitsPerSample());
-            assertEquals(channel_mode, bcc.getChannelMode());
-            assertEquals(codec_specific1, bcc.getCodecSpecific1());
-            assertEquals(codec_specific2, bcc.getCodecSpecific2());
-            assertEquals(codec_specific3, bcc.getCodecSpecific3());
-            assertEquals(codec_specific4, bcc.getCodecSpecific4());
-        }
-    }
-
-    @SmallTest
-    public void testBluetoothCodecConfig_equals() {
-        BluetoothCodecConfig bcc1 =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4000);
-
-        BluetoothCodecConfig bcc2_same =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4000);
-        assertTrue(bcc1.equals(bcc2_same));
-
-        BluetoothCodecConfig bcc3_codec_type =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4000);
-        assertFalse(bcc1.equals(bcc3_codec_type));
-
-        BluetoothCodecConfig bcc4_codec_priority =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4000);
-        assertFalse(bcc1.equals(bcc4_codec_priority));
-
-        BluetoothCodecConfig bcc5_sample_rate =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4000);
-        assertFalse(bcc1.equals(bcc5_sample_rate));
-
-        BluetoothCodecConfig bcc6_bits_per_sample =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4000);
-        assertFalse(bcc1.equals(bcc6_bits_per_sample));
-
-        BluetoothCodecConfig bcc7_channel_mode =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                     1000, 2000, 3000, 4000);
-        assertFalse(bcc1.equals(bcc7_channel_mode));
-
-        BluetoothCodecConfig bcc8_codec_specific1 =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1001, 2000, 3000, 4000);
-        assertFalse(bcc1.equals(bcc8_codec_specific1));
-
-        BluetoothCodecConfig bcc9_codec_specific2 =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2002, 3000, 4000);
-        assertFalse(bcc1.equals(bcc9_codec_specific2));
-
-        BluetoothCodecConfig bcc10_codec_specific3 =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3003, 4000);
-        assertFalse(bcc1.equals(bcc10_codec_specific3));
-
-        BluetoothCodecConfig bcc11_codec_specific4 =
-                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                     1000, 2000, 3000, 4004);
-        assertFalse(bcc1.equals(bcc11_codec_specific4));
-    }
-
-    private BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
-            int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
-            long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
-        return new BluetoothCodecConfig.Builder()
-                    .setCodecType(sourceCodecType)
-                    .setCodecPriority(codecPriority)
-                    .setSampleRate(sampleRate)
-                    .setBitsPerSample(bitsPerSample)
-                    .setChannelMode(channelMode)
-                    .setCodecSpecific1(codecSpecific1)
-                    .setCodecSpecific2(codecSpecific2)
-                    .setCodecSpecific3(codecSpecific3)
-                    .setCodecSpecific4(codecSpecific4)
-                    .build();
-
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
deleted file mode 100644
index 1cb2dca..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Unit test cases for {@link BluetoothCodecStatus}.
- * <p>
- * To run this test, use:
- * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
- */
-public class BluetoothCodecStatusTest extends TestCase {
-
-    // Codec configs: A and B are same; C is different
-    private static final BluetoothCodecConfig config_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig config_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig config_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    // Local capabilities: A and B are same; C is different
-    private static final BluetoothCodecConfig local_capability1_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability1_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability1_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-
-    private static final BluetoothCodecConfig local_capability2_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability2_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability2_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability3_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability3_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability3_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability4_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability4_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability4_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability5_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability5_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig local_capability5_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-
-    // Selectable capabilities: A and B are same; C is different
-    private static final BluetoothCodecConfig selectable_capability1_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability1_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability1_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability2_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability2_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability2_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability3_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability3_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability3_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability4_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability4_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability4_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability5_A =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability5_B =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
-                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final BluetoothCodecConfig selectable_capability5_C =
-            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
-                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
-                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
-                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
-                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
-                                 1000, 2000, 3000, 4000);
-
-    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_A =
-            new ArrayList() {{
-                    add(local_capability1_A);
-                    add(local_capability2_A);
-                    add(local_capability3_A);
-                    add(local_capability4_A);
-                    add(local_capability5_A);
-            }};
-
-    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B =
-            new ArrayList() {{
-                    add(local_capability1_B);
-                    add(local_capability2_B);
-                    add(local_capability3_B);
-                    add(local_capability4_B);
-                    add(local_capability5_B);
-            }};
-
-    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B_REORDERED =
-            new ArrayList() {{
-                    add(local_capability5_B);
-                    add(local_capability4_B);
-                    add(local_capability2_B);
-                    add(local_capability3_B);
-                    add(local_capability1_B);
-            }};
-
-    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_C =
-            new ArrayList() {{
-                    add(local_capability1_C);
-                    add(local_capability2_C);
-                    add(local_capability3_C);
-                    add(local_capability4_C);
-                    add(local_capability5_C);
-            }};
-
-    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_A =
-            new ArrayList() {{
-                    add(selectable_capability1_A);
-                    add(selectable_capability2_A);
-                    add(selectable_capability3_A);
-                    add(selectable_capability4_A);
-                    add(selectable_capability5_A);
-            }};
-
-    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B =
-            new ArrayList() {{
-                    add(selectable_capability1_B);
-                    add(selectable_capability2_B);
-                    add(selectable_capability3_B);
-                    add(selectable_capability4_B);
-                    add(selectable_capability5_B);
-            }};
-
-    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B_REORDERED =
-            new ArrayList() {{
-                    add(selectable_capability5_B);
-                    add(selectable_capability4_B);
-                    add(selectable_capability2_B);
-                    add(selectable_capability3_B);
-                    add(selectable_capability1_B);
-            }};
-
-    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_C =
-            new ArrayList() {{
-                    add(selectable_capability1_C);
-                    add(selectable_capability2_C);
-                    add(selectable_capability3_C);
-                    add(selectable_capability4_C);
-                    add(selectable_capability5_C);
-            }};
-
-    private static final BluetoothCodecStatus bcs_A =
-            new BluetoothCodecStatus(config_A, LOCAL_CAPABILITY_A, SELECTABLE_CAPABILITY_A);
-    private static final BluetoothCodecStatus bcs_B =
-            new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B, SELECTABLE_CAPABILITY_B);
-    private static final BluetoothCodecStatus bcs_B_reordered =
-            new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B_REORDERED,
-                                 SELECTABLE_CAPABILITY_B_REORDERED);
-    private static final BluetoothCodecStatus bcs_C =
-            new BluetoothCodecStatus(config_C, LOCAL_CAPABILITY_C, SELECTABLE_CAPABILITY_C);
-
-    @SmallTest
-    public void testBluetoothCodecStatus_get_methods() {
-
-        assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_A));
-        assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_B));
-        assertFalse(Objects.equals(bcs_A.getCodecConfig(), config_C));
-
-        assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_A));
-        assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_B));
-        assertFalse(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_C));
-
-        assertTrue(bcs_A.getCodecsSelectableCapabilities()
-                                 .equals(SELECTABLE_CAPABILITY_A));
-        assertTrue(bcs_A.getCodecsSelectableCapabilities()
-                                  .equals(SELECTABLE_CAPABILITY_B));
-        assertFalse(bcs_A.getCodecsSelectableCapabilities()
-                                  .equals(SELECTABLE_CAPABILITY_C));
-    }
-
-    @SmallTest
-    public void testBluetoothCodecStatus_equals() {
-        assertTrue(bcs_A.equals(bcs_B));
-        assertTrue(bcs_B.equals(bcs_A));
-        assertTrue(bcs_A.equals(bcs_B_reordered));
-        assertTrue(bcs_B_reordered.equals(bcs_A));
-        assertFalse(bcs_A.equals(bcs_C));
-        assertFalse(bcs_C.equals(bcs_A));
-    }
-
-    private static BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
-            int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
-            long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
-        return new BluetoothCodecConfig.Builder()
-                    .setCodecType(sourceCodecType)
-                    .setCodecPriority(codecPriority)
-                    .setSampleRate(sampleRate)
-                    .setBitsPerSample(bitsPerSample)
-                    .setChannelMode(channelMode)
-                    .setCodecSpecific1(codecSpecific1)
-                    .setCodecSpecific2(codecSpecific2)
-                    .setCodecSpecific3(codecSpecific3)
-                    .setCodecSpecific4(codecSpecific4)
-                    .build();
-
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
deleted file mode 100644
index 37b2a50..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.bluetooth;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.os.Bundle;
-
-import junit.framework.Assert;
-
-import java.util.Set;
-
-public class BluetoothInstrumentation extends Instrumentation {
-
-    private BluetoothTestUtils mUtils = null;
-    private BluetoothAdapter mAdapter = null;
-    private Bundle mArgs = null;
-    private Bundle mSuccessResult = null;
-
-    private BluetoothTestUtils getBluetoothTestUtils() {
-        if (mUtils == null) {
-            mUtils = new BluetoothTestUtils(getContext(),
-                    BluetoothInstrumentation.class.getSimpleName());
-        }
-        return mUtils;
-    }
-
-    private BluetoothAdapter getBluetoothAdapter() {
-        if (mAdapter == null) {
-            mAdapter = ((BluetoothManager)getContext().getSystemService(
-                    Context.BLUETOOTH_SERVICE)).getAdapter();
-        }
-        return mAdapter;
-    }
-
-    @Override
-    public void onCreate(Bundle arguments) {
-        super.onCreate(arguments);
-        mArgs = arguments;
-        // create the default result response, but only use it in success code path
-        mSuccessResult = new Bundle();
-        mSuccessResult.putString("result", "SUCCESS");
-        start();
-    }
-
-    @Override
-    public void onStart() {
-        String command = mArgs.getString("command");
-        if ("enable".equals(command)) {
-            enable();
-        } else if ("disable".equals(command)) {
-            disable();
-        } else if ("unpairAll".equals(command)) {
-            unpairAll();
-        } else if ("getName".equals(command)) {
-            getName();
-        } else if ("getAddress".equals(command)) {
-            getAddress();
-        } else if ("getBondedDevices".equals(command)) {
-            getBondedDevices();
-        } else {
-            finish(null);
-        }
-    }
-
-    public void enable() {
-        getBluetoothTestUtils().enable(getBluetoothAdapter());
-        finish(mSuccessResult);
-    }
-
-    public void disable() {
-        getBluetoothTestUtils().disable(getBluetoothAdapter());
-        finish(mSuccessResult);
-    }
-
-    public void unpairAll() {
-        getBluetoothTestUtils().unpairAll(getBluetoothAdapter());
-        finish(mSuccessResult);
-    }
-
-    public void getName() {
-        String name = getBluetoothAdapter().getName();
-        mSuccessResult.putString("name", name);
-        finish(mSuccessResult);
-    }
-
-    public void getAddress() {
-        String name = getBluetoothAdapter().getAddress();
-        mSuccessResult.putString("address", name);
-        finish(mSuccessResult);
-    }
-
-    public void getBondedDevices() {
-        Set<BluetoothDevice> devices = getBluetoothAdapter().getBondedDevices();
-        int i = 0;
-        for (BluetoothDevice device : devices) {
-            mSuccessResult.putString(String.format("device-%02d", i), device.getAddress());
-            i++;
-        }
-        finish(mSuccessResult);
-    }
-
-    public void finish(Bundle result) {
-        if (result == null) {
-            result = new Bundle();
-        }
-        finish(Activity.RESULT_OK, result);
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
deleted file mode 100644
index c3d707c..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.bluetooth;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link BluetoothLeAudioCodecConfig}.
- */
-public class BluetoothLeAudioCodecConfigTest extends TestCase {
-    private int[] mCodecTypeArray = new int[] {
-        BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3,
-        BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID,
-    };
-
-    @SmallTest
-    public void testBluetoothLeAudioCodecConfig_valid_get_methods() {
-
-        for (int codecIdx = 0; codecIdx < mCodecTypeArray.length; codecIdx++) {
-            int codecType = mCodecTypeArray[codecIdx];
-
-            BluetoothLeAudioCodecConfig leAudioCodecConfig =
-                    buildBluetoothLeAudioCodecConfig(codecType);
-
-            if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3) {
-                assertEquals("LC3", leAudioCodecConfig.getCodecName());
-            }
-            if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
-                assertEquals("INVALID CODEC", leAudioCodecConfig.getCodecName());
-            }
-
-            assertEquals(codecType, leAudioCodecConfig.getCodecType());
-        }
-    }
-
-    private BluetoothLeAudioCodecConfig buildBluetoothLeAudioCodecConfig(int sourceCodecType) {
-        return new BluetoothLeAudioCodecConfig.Builder()
-                    .setCodecType(sourceCodecType)
-                    .build();
-
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java
deleted file mode 100644
index 33e9dd7..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothRebootStressTest.java
+++ /dev/null
@@ -1,94 +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.
- */
-
-package android.bluetooth;
-
-import android.content.Context;
-import android.test.InstrumentationTestCase;
-
-/**
- * Instrumentation test case for stress test involving rebooting the device.
- * <p>
- * This test case tests that bluetooth is enabled after a device reboot. Because
- * the device will reboot, the instrumentation must be driven by a script on the
- * host side.
- */
-public class BluetoothRebootStressTest extends InstrumentationTestCase {
-    private static final String TAG = "BluetoothRebootStressTest";
-    private static final String OUTPUT_FILE = "BluetoothRebootStressTestOutput.txt";
-
-    private BluetoothTestUtils mTestUtils;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        Context context = getInstrumentation().getTargetContext();
-        mTestUtils = new BluetoothTestUtils(context, TAG, OUTPUT_FILE);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-
-        mTestUtils.close();
-    }
-
-    /**
-     * Test method used to start the test by turning bluetooth on.
-     */
-    public void testStart() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        mTestUtils.enable(adapter);
-    }
-
-    /**
-     * Test method used in the middle iterations of the test to check if
-     * bluetooth is on. Does not toggle bluetooth after the check. Assumes that
-     * bluetooth has been turned on by {@code #testStart()}
-     */
-    public void testMiddleNoToggle() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
-        assertTrue(adapter.isEnabled());
-    }
-
-    /**
-     * Test method used in the middle iterations of the test to check if
-     * bluetooth is on. Toggles bluetooth after the check. Assumes that
-     * bluetooth has been turned on by {@code #testStart()}
-     */
-    public void testMiddleToggle() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
-        assertTrue(adapter.isEnabled());
-
-        mTestUtils.disable(adapter);
-        mTestUtils.enable(adapter);
-    }
-
-    /**
-     * Test method used in the stop the test by turning bluetooth off. Assumes
-     * that bluetooth has been turned on by {@code #testStart()}
-     */
-    public void testStop() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
-        assertTrue(adapter.isEnabled());
-
-        mTestUtils.disable(adapter);
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
deleted file mode 100644
index 89dbe3f..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java
+++ /dev/null
@@ -1,393 +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.
- */
-
-package android.bluetooth;
-
-import android.content.Context;
-import android.test.InstrumentationTestCase;
-
-/**
- * Stress test suite for Bluetooth related functions.
- *
- * Includes tests for enabling/disabling bluetooth, enabling/disabling discoverable mode,
- * starting/stopping scans, connecting/disconnecting to HFP, A2DP, HID, PAN profiles, and verifying
- * that remote connections/disconnections occur for the PAN profile.
- * <p>
- * This test suite uses {@link android.bluetooth.BluetoothTestRunner} to for parameters such as the
- * number of iterations and the addresses of remote Bluetooth devices.
- */
-public class BluetoothStressTest extends InstrumentationTestCase {
-    private static final String TAG = "BluetoothStressTest";
-    private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt";
-    /** The amount of time to sleep between issuing start/stop SCO in ms. */
-    private static final long SCO_SLEEP_TIME = 2 * 1000;
-
-    private BluetoothAdapter mAdapter;
-    private BluetoothTestUtils mTestUtils;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        Context context = getInstrumentation().getTargetContext();
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mTestUtils = new BluetoothTestUtils(context, TAG, OUTPUT_FILE);
-
-        // Start all tests in a disabled state.
-        if (mAdapter.isEnabled()) {
-            mTestUtils.disable(mAdapter);
-        }
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        mTestUtils.close();
-    }
-
-    /**
-     * Stress test for enabling and disabling Bluetooth.
-     */
-    public void testEnable() {
-        int iterations = BluetoothTestRunner.sEnableIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("enable iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.enable(mAdapter);
-            mTestUtils.disable(mAdapter);
-        }
-    }
-
-    /**
-     * Stress test for putting the device in and taking the device out of discoverable mode.
-     */
-    public void testDiscoverable() {
-        int iterations = BluetoothTestRunner.sDiscoverableIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        mTestUtils.enable(mAdapter);
-        mTestUtils.undiscoverable(mAdapter);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("discoverable iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.discoverable(mAdapter);
-            mTestUtils.undiscoverable(mAdapter);
-        }
-    }
-
-    /**
-     * Stress test for starting and stopping Bluetooth scans.
-     */
-    public void testScan() {
-        int iterations = BluetoothTestRunner.sScanIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        mTestUtils.enable(mAdapter);
-        mTestUtils.stopScan(mAdapter);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("scan iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.startScan(mAdapter);
-            mTestUtils.stopScan(mAdapter);
-        }
-    }
-
-    /**
-     * Stress test for enabling and disabling the PAN NAP profile.
-     */
-    public void testEnablePan() {
-        int iterations = BluetoothTestRunner.sEnablePanIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        mTestUtils.enable(mAdapter);
-        mTestUtils.disablePan(mAdapter);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("testEnablePan iteration " + (i + 1) + " of "
-                    + iterations);
-            mTestUtils.enablePan(mAdapter);
-            mTestUtils.disablePan(mAdapter);
-        }
-    }
-
-    /**
-     * Stress test for pairing and unpairing with a remote device.
-     * <p>
-     * In this test, the local device initiates pairing with a remote device, and then unpairs with
-     * the device after the pairing has successfully completed.
-     */
-    public void testPair() {
-        int iterations = BluetoothTestRunner.sPairIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("pair iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                    BluetoothTestRunner.sDevicePairPin);
-            mTestUtils.unpair(mAdapter, device);
-        }
-    }
-
-    /**
-     * Stress test for accepting a pairing request and unpairing with a remote device.
-     * <p>
-     * In this test, the local device waits for a pairing request from a remote device.  It accepts
-     * the request and then unpairs after the paring has successfully completed.
-     */
-    public void testAcceptPair() {
-        int iterations = BluetoothTestRunner.sPairIterations;
-        if (iterations == 0) {
-            return;
-        }
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.acceptPair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                    BluetoothTestRunner.sDevicePairPin);
-            mTestUtils.unpair(mAdapter, device);
-        }
-    }
-
-    /**
-     * Stress test for connecting and disconnecting with an A2DP source.
-     * <p>
-     * In this test, the local device plays the role of an A2DP sink, and initiates connections and
-     * disconnections with an A2DP source.
-     */
-    public void testConnectA2dp() {
-        int iterations = BluetoothTestRunner.sConnectA2dpIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                BluetoothTestRunner.sDevicePairPin);
-        mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.A2DP, null);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("connectA2dp iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.A2DP,
-                    String.format("connectA2dp(device=%s)", device));
-            mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.A2DP,
-                    String.format("disconnectA2dp(device=%s)", device));
-        }
-
-        mTestUtils.unpair(mAdapter, device);
-    }
-
-    /**
-     * Stress test for connecting and disconnecting the HFP with a hands free device.
-     * <p>
-     * In this test, the local device plays the role of an HFP audio gateway, and initiates
-     * connections and disconnections with a hands free device.
-     */
-    public void testConnectHeadset() {
-        int iterations = BluetoothTestRunner.sConnectHeadsetIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                BluetoothTestRunner.sDevicePairPin);
-        mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("connectHeadset iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HEADSET,
-                    String.format("connectHeadset(device=%s)", device));
-            mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET,
-                    String.format("disconnectHeadset(device=%s)", device));
-        }
-
-        mTestUtils.unpair(mAdapter, device);
-    }
-
-    /**
-     * Stress test for connecting and disconnecting with a HID device.
-     * <p>
-     * In this test, the local device plays the role of a HID host, and initiates connections and
-     * disconnections with a HID device.
-     */
-    public void testConnectInput() {
-        int iterations = BluetoothTestRunner.sConnectInputIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                BluetoothTestRunner.sDevicePairPin);
-        mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HID_HOST, null);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HID_HOST,
-                    String.format("connectInput(device=%s)", device));
-            mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HID_HOST,
-                    String.format("disconnectInput(device=%s)", device));
-        }
-
-        mTestUtils.unpair(mAdapter, device);
-    }
-
-    /**
-     * Stress test for connecting and disconnecting with a PAN NAP.
-     * <p>
-     * In this test, the local device plays the role of a PANU, and initiates connections and
-     * disconnections with a NAP.
-     */
-    public void testConnectPan() {
-        int iterations = BluetoothTestRunner.sConnectPanIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                BluetoothTestRunner.sDevicePairPin);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("connectPan iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.connectPan(mAdapter, device);
-            mTestUtils.disconnectPan(mAdapter, device);
-        }
-
-        mTestUtils.unpair(mAdapter, device);
-    }
-
-    /**
-     * Stress test for verifying a PANU connecting and disconnecting with the device.
-     * <p>
-     * In this test, the local device plays the role of a NAP which a remote PANU connects and
-     * disconnects from.
-     */
-    public void testIncomingPanConnection() {
-        int iterations = BluetoothTestRunner.sConnectPanIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.disablePan(mAdapter);
-        mTestUtils.enablePan(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.acceptPair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                BluetoothTestRunner.sDevicePairPin);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("incomingPanConnection iteration " + (i + 1) + " of "
-                    + iterations);
-            mTestUtils.incomingPanConnection(mAdapter, device);
-            mTestUtils.incomingPanDisconnection(mAdapter, device);
-        }
-
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.disablePan(mAdapter);
-    }
-
-    /**
-     * Stress test for verifying that AudioManager can open and close SCO connections.
-     * <p>
-     * In this test, a HSP connection is opened with an external headset and the SCO connection is
-     * repeatibly opened and closed.
-     */
-    public void testStartStopSco() {
-        int iterations = BluetoothTestRunner.sStartStopScoIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.unpair(mAdapter, device);
-        mTestUtils.pair(mAdapter, device, BluetoothTestRunner.sDevicePairPasskey,
-                BluetoothTestRunner.sDevicePairPin);
-        mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
-        mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
-        mTestUtils.stopSco(mAdapter, device);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.writeOutput("startStopSco iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.startSco(mAdapter, device);
-            sleep(SCO_SLEEP_TIME);
-            mTestUtils.stopSco(mAdapter, device);
-            sleep(SCO_SLEEP_TIME);
-        }
-
-        mTestUtils.disconnectProfile(mAdapter, device, BluetoothProfile.HEADSET, null);
-        mTestUtils.unpair(mAdapter, device);
-    }
-
-    /* Make sure there is at least 1 unread message in the last week on remote device */
-    public void testMceSetMessageStatus() {
-        int iterations = BluetoothTestRunner.sMceSetMessageStatusIterations;
-        if (iterations == 0) {
-            return;
-        }
-
-        BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress);
-        mTestUtils.enable(mAdapter);
-        mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.MAP_CLIENT, null);
-        mTestUtils.mceGetUnreadMessage(mAdapter, device);
-
-        for (int i = 0; i < iterations; i++) {
-            mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.READ);
-            mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.UNREAD);
-        }
-
-        /**
-         * It is hard to find device to support set undeleted status, so just
-         * set deleted in 1 iteration
-         **/
-        mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.DELETED);
-    }
-
-    private void sleep(long time) {
-        try {
-            Thread.sleep(time);
-        } catch (InterruptedException e) {
-        }
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
deleted file mode 100644
index d19c2c3..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
+++ /dev/null
@@ -1,225 +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.
- */
-
-package android.bluetooth;
-
-import junit.framework.TestSuite;
-
-import android.os.Bundle;
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-import android.util.Log;
-
-/**
- * Instrumentation test runner for Bluetooth tests.
- * <p>
- * To run:
- * <pre>
- * {@code
- * adb shell am instrument \
- *     [-e enable_iterations <iterations>] \
- *     [-e discoverable_iterations <iterations>] \
- *     [-e scan_iterations <iterations>] \
- *     [-e enable_pan_iterations <iterations>] \
- *     [-e pair_iterations <iterations>] \
- *     [-e connect_a2dp_iterations <iterations>] \
- *     [-e connect_headset_iterations <iterations>] \
- *     [-e connect_input_iterations <iterations>] \
- *     [-e connect_pan_iterations <iterations>] \
- *     [-e start_stop_sco_iterations <iterations>] \
- *     [-e mce_set_message_status_iterations <iterations>] \
- *     [-e pair_address <address>] \
- *     [-e headset_address <address>] \
- *     [-e a2dp_address <address>] \
- *     [-e input_address <address>] \
- *     [-e pan_address <address>] \
- *     [-e pair_pin <pin>] \
- *     [-e pair_passkey <passkey>] \
- *     -w com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner
- * }
- * </pre>
- */
-public class BluetoothTestRunner extends InstrumentationTestRunner {
-    private static final String TAG = "BluetoothTestRunner";
-
-    public static int sEnableIterations = 100;
-    public static int sDiscoverableIterations = 1000;
-    public static int sScanIterations = 1000;
-    public static int sEnablePanIterations = 1000;
-    public static int sPairIterations = 100;
-    public static int sConnectHeadsetIterations = 100;
-    public static int sConnectA2dpIterations = 100;
-    public static int sConnectInputIterations = 100;
-    public static int sConnectPanIterations = 100;
-    public static int sStartStopScoIterations = 100;
-    public static int sMceSetMessageStatusIterations = 100;
-
-    public static String sDeviceAddress = "";
-    public static byte[] sDevicePairPin = {'1', '2', '3', '4'};
-    public static int sDevicePairPasskey = 123456;
-
-    @Override
-    public TestSuite getAllTests() {
-        TestSuite suite = new InstrumentationTestSuite(this);
-        suite.addTestSuite(BluetoothStressTest.class);
-        return suite;
-    }
-
-    @Override
-    public ClassLoader getLoader() {
-        return BluetoothTestRunner.class.getClassLoader();
-    }
-
-    @Override
-    public void onCreate(Bundle arguments) {
-        String val = arguments.getString("enable_iterations");
-        if (val != null) {
-            try {
-                sEnableIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("discoverable_iterations");
-        if (val != null) {
-            try {
-                sDiscoverableIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("scan_iterations");
-        if (val != null) {
-            try {
-                sScanIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("enable_pan_iterations");
-        if (val != null) {
-            try {
-                sEnablePanIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("pair_iterations");
-        if (val != null) {
-            try {
-                sPairIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("connect_a2dp_iterations");
-        if (val != null) {
-            try {
-                sConnectA2dpIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("connect_headset_iterations");
-        if (val != null) {
-            try {
-                sConnectHeadsetIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("connect_input_iterations");
-        if (val != null) {
-            try {
-                sConnectInputIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("connect_pan_iterations");
-        if (val != null) {
-            try {
-                sConnectPanIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("start_stop_sco_iterations");
-        if (val != null) {
-            try {
-                sStartStopScoIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("mce_set_message_status_iterations");
-        if (val != null) {
-            try {
-                sMceSetMessageStatusIterations = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        val = arguments.getString("device_address");
-        if (val != null) {
-            sDeviceAddress = val;
-        }
-
-        val = arguments.getString("device_pair_pin");
-        if (val != null) {
-            byte[] pin = BluetoothDevice.convertPinToBytes(val);
-            if (pin != null) {
-                sDevicePairPin = pin;
-            }
-        }
-
-        val = arguments.getString("device_pair_passkey");
-        if (val != null) {
-            try {
-                sDevicePairPasskey = Integer.parseInt(val);
-            } catch (NumberFormatException e) {
-                // Invalid argument, fall back to default value
-            }
-        }
-
-        Log.i(TAG, String.format("enable_iterations=%d", sEnableIterations));
-        Log.i(TAG, String.format("discoverable_iterations=%d", sDiscoverableIterations));
-        Log.i(TAG, String.format("scan_iterations=%d", sScanIterations));
-        Log.i(TAG, String.format("pair_iterations=%d", sPairIterations));
-        Log.i(TAG, String.format("connect_a2dp_iterations=%d", sConnectA2dpIterations));
-        Log.i(TAG, String.format("connect_headset_iterations=%d", sConnectHeadsetIterations));
-        Log.i(TAG, String.format("connect_input_iterations=%d", sConnectInputIterations));
-        Log.i(TAG, String.format("connect_pan_iterations=%d", sConnectPanIterations));
-        Log.i(TAG, String.format("start_stop_sco_iterations=%d", sStartStopScoIterations));
-        Log.i(TAG, String.format("device_address=%s", sDeviceAddress));
-        Log.i(TAG, String.format("device_pair_pin=%s", new String(sDevicePairPin)));
-        Log.i(TAG, String.format("device_pair_passkey=%d", sDevicePairPasskey));
-
-        // Call onCreate last since we want to set the static variables first.
-        super.onCreate(arguments);
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
deleted file mode 100644
index 409025b..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ /dev/null
@@ -1,1649 +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.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.os.Environment;
-import android.util.Log;
-
-import junit.framework.Assert;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-public class BluetoothTestUtils extends Assert {
-
-    /** Timeout for enable/disable in ms. */
-    private static final int ENABLE_DISABLE_TIMEOUT = 20000;
-    /** Timeout for discoverable/undiscoverable in ms. */
-    private static final int DISCOVERABLE_UNDISCOVERABLE_TIMEOUT = 5000;
-    /** Timeout for starting/stopping a scan in ms. */
-    private static final int START_STOP_SCAN_TIMEOUT = 5000;
-    /** Timeout for pair/unpair in ms. */
-    private static final int PAIR_UNPAIR_TIMEOUT = 20000;
-    /** Timeout for connecting/disconnecting a profile in ms. */
-    private static final int CONNECT_DISCONNECT_PROFILE_TIMEOUT = 20000;
-    /** Timeout to start or stop a SCO channel in ms. */
-    private static final int START_STOP_SCO_TIMEOUT = 10000;
-    /** Timeout to connect a profile proxy in ms. */
-    private static final int CONNECT_PROXY_TIMEOUT = 5000;
-    /** Time between polls in ms. */
-    private static final int POLL_TIME = 100;
-    /** Timeout to get map message in ms. */
-    private static final int GET_UNREAD_MESSAGE_TIMEOUT = 10000;
-    /** Timeout to set map message status in ms. */
-    private static final int SET_MESSAGE_STATUS_TIMEOUT = 2000;
-
-    private abstract class FlagReceiver extends BroadcastReceiver {
-        private int mExpectedFlags = 0;
-        private int mFiredFlags = 0;
-        private long mCompletedTime = -1;
-
-        public FlagReceiver(int expectedFlags) {
-            mExpectedFlags = expectedFlags;
-        }
-
-        public int getFiredFlags() {
-            synchronized (this) {
-                return mFiredFlags;
-            }
-        }
-
-        public long getCompletedTime() {
-            synchronized (this) {
-                return mCompletedTime;
-            }
-        }
-
-        protected void setFiredFlag(int flag) {
-            synchronized (this) {
-                mFiredFlags |= flag;
-                if ((mFiredFlags & mExpectedFlags) == mExpectedFlags) {
-                    mCompletedTime = System.currentTimeMillis();
-                }
-            }
-        }
-    }
-
-    private class BluetoothReceiver extends FlagReceiver {
-        private static final int DISCOVERY_STARTED_FLAG = 1;
-        private static final int DISCOVERY_FINISHED_FLAG = 1 << 1;
-        private static final int SCAN_MODE_NONE_FLAG = 1 << 2;
-        private static final int SCAN_MODE_CONNECTABLE_FLAG = 1 << 3;
-        private static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG = 1 << 4;
-        private static final int STATE_OFF_FLAG = 1 << 5;
-        private static final int STATE_TURNING_ON_FLAG = 1 << 6;
-        private static final int STATE_ON_FLAG = 1 << 7;
-        private static final int STATE_TURNING_OFF_FLAG = 1 << 8;
-        private static final int STATE_GET_MESSAGE_FINISHED_FLAG = 1 << 9;
-        private static final int STATE_SET_MESSAGE_STATUS_FINISHED_FLAG = 1 << 10;
-
-        public BluetoothReceiver(int expectedFlags) {
-            super(expectedFlags);
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
-                setFiredFlag(DISCOVERY_STARTED_FLAG);
-            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
-                setFiredFlag(DISCOVERY_FINISHED_FLAG);
-            } else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {
-                int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1);
-                assertNotSame(-1, mode);
-                switch (mode) {
-                    case BluetoothAdapter.SCAN_MODE_NONE:
-                        setFiredFlag(SCAN_MODE_NONE_FLAG);
-                        break;
-                    case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-                        setFiredFlag(SCAN_MODE_CONNECTABLE_FLAG);
-                        break;
-                    case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-                        setFiredFlag(SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG);
-                        break;
-                }
-            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
-                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
-                assertNotSame(-1, state);
-                switch (state) {
-                    case BluetoothAdapter.STATE_OFF:
-                        setFiredFlag(STATE_OFF_FLAG);
-                        break;
-                    case BluetoothAdapter.STATE_TURNING_ON:
-                        setFiredFlag(STATE_TURNING_ON_FLAG);
-                        break;
-                    case BluetoothAdapter.STATE_ON:
-                        setFiredFlag(STATE_ON_FLAG);
-                        break;
-                    case BluetoothAdapter.STATE_TURNING_OFF:
-                        setFiredFlag(STATE_TURNING_OFF_FLAG);
-                        break;
-                }
-            }
-        }
-    }
-
-    private class PairReceiver extends FlagReceiver {
-        private static final int STATE_BONDED_FLAG = 1;
-        private static final int STATE_BONDING_FLAG = 1 << 1;
-        private static final int STATE_NONE_FLAG = 1 << 2;
-
-        private BluetoothDevice mDevice;
-        private int mPasskey;
-        private byte[] mPin;
-
-        public PairReceiver(BluetoothDevice device, int passkey, byte[] pin, int expectedFlags) {
-            super(expectedFlags);
-
-            mDevice = device;
-            mPasskey = passkey;
-            mPin = pin;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
-                return;
-            }
-
-            if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
-                int varient = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, -1);
-                assertNotSame(-1, varient);
-                switch (varient) {
-                    case BluetoothDevice.PAIRING_VARIANT_PIN:
-                    case BluetoothDevice.PAIRING_VARIANT_PIN_16_DIGITS:
-                        mDevice.setPin(mPin);
-                        break;
-                    case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
-                        break;
-                    case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
-                    case BluetoothDevice.PAIRING_VARIANT_CONSENT:
-                        mDevice.setPairingConfirmation(true);
-                        break;
-                    case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
-                        break;
-                }
-            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
-                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
-                assertNotSame(-1, state);
-                switch (state) {
-                    case BluetoothDevice.BOND_NONE:
-                        setFiredFlag(STATE_NONE_FLAG);
-                        break;
-                    case BluetoothDevice.BOND_BONDING:
-                        setFiredFlag(STATE_BONDING_FLAG);
-                        break;
-                    case BluetoothDevice.BOND_BONDED:
-                        setFiredFlag(STATE_BONDED_FLAG);
-                        break;
-                }
-            }
-        }
-    }
-
-    private class ConnectProfileReceiver extends FlagReceiver {
-        private static final int STATE_DISCONNECTED_FLAG = 1;
-        private static final int STATE_CONNECTING_FLAG = 1 << 1;
-        private static final int STATE_CONNECTED_FLAG = 1 << 2;
-        private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
-
-        private BluetoothDevice mDevice;
-        private int mProfile;
-        private String mConnectionAction;
-
-        public ConnectProfileReceiver(BluetoothDevice device, int profile, int expectedFlags) {
-            super(expectedFlags);
-
-            mDevice = device;
-            mProfile = profile;
-
-            switch (mProfile) {
-                case BluetoothProfile.A2DP:
-                    mConnectionAction = BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED;
-                    break;
-                case BluetoothProfile.HEADSET:
-                    mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
-                    break;
-                case BluetoothProfile.HID_HOST:
-                    mConnectionAction = BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED;
-                    break;
-                case BluetoothProfile.PAN:
-                    mConnectionAction = BluetoothPan.ACTION_CONNECTION_STATE_CHANGED;
-                    break;
-                case BluetoothProfile.MAP_CLIENT:
-                    mConnectionAction = BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED;
-                    break;
-                default:
-                    mConnectionAction = null;
-            }
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (mConnectionAction != null && mConnectionAction.equals(intent.getAction())) {
-                if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
-                    return;
-                }
-
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
-                assertNotSame(-1, state);
-                switch (state) {
-                    case BluetoothProfile.STATE_DISCONNECTED:
-                        setFiredFlag(STATE_DISCONNECTED_FLAG);
-                        break;
-                    case BluetoothProfile.STATE_CONNECTING:
-                        setFiredFlag(STATE_CONNECTING_FLAG);
-                        break;
-                    case BluetoothProfile.STATE_CONNECTED:
-                        setFiredFlag(STATE_CONNECTED_FLAG);
-                        break;
-                    case BluetoothProfile.STATE_DISCONNECTING:
-                        setFiredFlag(STATE_DISCONNECTING_FLAG);
-                        break;
-                }
-            }
-        }
-    }
-
-    private class ConnectPanReceiver extends ConnectProfileReceiver {
-        private int mRole;
-
-        public ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) {
-            super(device, BluetoothProfile.PAN, expectedFlags);
-
-            mRole = role;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (mRole != intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, -1)) {
-                return;
-            }
-
-            super.onReceive(context, intent);
-        }
-    }
-
-    private class StartStopScoReceiver extends FlagReceiver {
-        private static final int STATE_CONNECTED_FLAG = 1;
-        private static final int STATE_DISCONNECTED_FLAG = 1 << 1;
-
-        public StartStopScoReceiver(int expectedFlags) {
-            super(expectedFlags);
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) {
-                int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
-                        AudioManager.SCO_AUDIO_STATE_ERROR);
-                assertNotSame(AudioManager.SCO_AUDIO_STATE_ERROR, state);
-                switch(state) {
-                    case AudioManager.SCO_AUDIO_STATE_CONNECTED:
-                        setFiredFlag(STATE_CONNECTED_FLAG);
-                        break;
-                    case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
-                        setFiredFlag(STATE_DISCONNECTED_FLAG);
-                        break;
-                }
-            }
-        }
-    }
-
-
-    private class MceSetMessageStatusReceiver extends FlagReceiver {
-        private static final int MESSAGE_RECEIVED_FLAG = 1;
-        private static final int STATUS_CHANGED_FLAG = 1 << 1;
-
-        public MceSetMessageStatusReceiver(int expectedFlags) {
-            super(expectedFlags);
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (BluetoothMapClient.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
-                String handle = intent.getStringExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE);
-                assertNotNull(handle);
-                setFiredFlag(MESSAGE_RECEIVED_FLAG);
-                mMsgHandle = handle;
-            } else if (BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED.equals(intent.getAction())) {
-                int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE);
-                assertEquals(result, BluetoothMapClient.RESULT_SUCCESS);
-                setFiredFlag(STATUS_CHANGED_FLAG);
-            } else if (BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED.equals(intent.getAction())) {
-                int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE);
-                assertEquals(result, BluetoothMapClient.RESULT_SUCCESS);
-                setFiredFlag(STATUS_CHANGED_FLAG);
-            }
-        }
-    }
-
-    private BluetoothProfile.ServiceListener mServiceListener =
-            new BluetoothProfile.ServiceListener() {
-        @Override
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            synchronized (this) {
-                switch (profile) {
-                    case BluetoothProfile.A2DP:
-                        mA2dp = (BluetoothA2dp) proxy;
-                        break;
-                    case BluetoothProfile.HEADSET:
-                        mHeadset = (BluetoothHeadset) proxy;
-                        break;
-                    case BluetoothProfile.HID_HOST:
-                        mInput = (BluetoothHidHost) proxy;
-                        break;
-                    case BluetoothProfile.PAN:
-                        mPan = (BluetoothPan) proxy;
-                        break;
-                    case BluetoothProfile.MAP_CLIENT:
-                        mMce = (BluetoothMapClient) proxy;
-                        break;
-                }
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(int profile) {
-            synchronized (this) {
-                switch (profile) {
-                    case BluetoothProfile.A2DP:
-                        mA2dp = null;
-                        break;
-                    case BluetoothProfile.HEADSET:
-                        mHeadset = null;
-                        break;
-                    case BluetoothProfile.HID_HOST:
-                        mInput = null;
-                        break;
-                    case BluetoothProfile.PAN:
-                        mPan = null;
-                        break;
-                    case BluetoothProfile.MAP_CLIENT:
-                        mMce = null;
-                        break;
-                }
-            }
-        }
-    };
-
-    private List<BroadcastReceiver> mReceivers = new ArrayList<BroadcastReceiver>();
-
-    private BufferedWriter mOutputWriter;
-    private String mTag;
-    private String mOutputFile;
-
-    private Context mContext;
-    private BluetoothA2dp mA2dp = null;
-    private BluetoothHeadset mHeadset = null;
-    private BluetoothHidHost mInput = null;
-    private BluetoothPan mPan = null;
-    private BluetoothMapClient mMce = null;
-    private String mMsgHandle = null;
-
-    /**
-     * Creates a utility instance for testing Bluetooth.
-     *
-     * @param context The context of the application using the utility.
-     * @param tag The log tag of the application using the utility.
-     */
-    public BluetoothTestUtils(Context context, String tag) {
-        this(context, tag, null);
-    }
-
-    /**
-     * Creates a utility instance for testing Bluetooth.
-     *
-     * @param context The context of the application using the utility.
-     * @param tag The log tag of the application using the utility.
-     * @param outputFile The path to an output file if the utility is to write results to a
-     *        separate file.
-     */
-    public BluetoothTestUtils(Context context, String tag, String outputFile) {
-        mContext = context;
-        mTag = tag;
-        mOutputFile = outputFile;
-
-        if (mOutputFile == null) {
-            mOutputWriter = null;
-        } else {
-            try {
-                mOutputWriter = new BufferedWriter(new FileWriter(new File(
-                        Environment.getExternalStorageDirectory(), mOutputFile), true));
-            } catch (IOException e) {
-                Log.w(mTag, "Test output file could not be opened", e);
-                mOutputWriter = null;
-            }
-        }
-    }
-
-    /**
-     * Closes the utility instance and unregisters any BroadcastReceivers.
-     */
-    public void close() {
-        while (!mReceivers.isEmpty()) {
-            mContext.unregisterReceiver(mReceivers.remove(0));
-        }
-
-        if (mOutputWriter != null) {
-            try {
-                mOutputWriter.close();
-            } catch (IOException e) {
-                Log.w(mTag, "Test output file could not be closed", e);
-            }
-        }
-    }
-
-    /**
-     * Enables Bluetooth and checks to make sure that Bluetooth was turned on and that the correct
-     * actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void enable(BluetoothAdapter adapter) {
-        writeOutput("Enabling Bluetooth adapter.");
-        assertFalse(adapter.isEnabled());
-        int btState = adapter.getState();
-        final Semaphore completionSemaphore = new Semaphore(0);
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                if (!BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
-                    return;
-                }
-                final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                        BluetoothAdapter.ERROR);
-                if (state == BluetoothAdapter.STATE_ON) {
-                    completionSemaphore.release();
-                }
-            }
-        };
-
-        final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        mContext.registerReceiver(receiver, filter);
-        // Note: for Wear Local Edition builds, which have Permission Review Mode enabled to
-        // obey China CMIIT, BluetoothAdapter may not startup immediately on methods enable/disable.
-        // So no assertion applied here.
-        adapter.enable();
-        boolean success = false;
-        try {
-            success = completionSemaphore.tryAcquire(ENABLE_DISABLE_TIMEOUT, TimeUnit.MILLISECONDS);
-            writeOutput(String.format("enable() completed in 0 ms"));
-        } catch (final InterruptedException e) {
-            // This should never happen but just in case it does, the test will fail anyway.
-        }
-        mContext.unregisterReceiver(receiver);
-        if (!success) {
-            fail(String.format("enable() timeout: state=%d (expected %d)", btState,
-                    BluetoothAdapter.STATE_ON));
-        }
-    }
-
-    /**
-     * Disables Bluetooth and checks to make sure that Bluetooth was turned off and that the correct
-     * actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void disable(BluetoothAdapter adapter) {
-        writeOutput("Disabling Bluetooth adapter.");
-        assertTrue(adapter.isEnabled());
-        int btState = adapter.getState();
-        final Semaphore completionSemaphore = new Semaphore(0);
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                if (!BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
-                    return;
-                }
-                final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
-                        BluetoothAdapter.ERROR);
-                if (state == BluetoothAdapter.STATE_OFF) {
-                    completionSemaphore.release();
-                }
-            }
-        };
-
-        final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        mContext.registerReceiver(receiver, filter);
-        // Note: for Wear Local Edition builds, which have Permission Review Mode enabled to
-        // obey China CMIIT, BluetoothAdapter may not startup immediately on methods enable/disable.
-        // So no assertion applied here.
-        adapter.disable();
-        boolean success = false;
-        try {
-            success = completionSemaphore.tryAcquire(ENABLE_DISABLE_TIMEOUT, TimeUnit.MILLISECONDS);
-            writeOutput(String.format("disable() completed in 0 ms"));
-        } catch (final InterruptedException e) {
-            // This should never happen but just in case it does, the test will fail anyway.
-        }
-        mContext.unregisterReceiver(receiver);
-        if (!success) {
-            fail(String.format("disable() timeout: state=%d (expected %d)", btState,
-                    BluetoothAdapter.STATE_OFF));
-        }
-    }
-
-    /**
-     * Puts the local device into discoverable mode and checks to make sure that the local device
-     * is in discoverable mode and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void discoverable(BluetoothAdapter adapter) {
-        if (!adapter.isEnabled()) {
-            fail("discoverable() bluetooth not enabled");
-        }
-
-        int scanMode = adapter.getScanMode();
-        if (scanMode != BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
-            return;
-        }
-
-        final Semaphore completionSemaphore = new Semaphore(0);
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                if (!BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
-                    return;
-                }
-                final int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
-                        BluetoothAdapter.SCAN_MODE_NONE);
-                if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
-                    completionSemaphore.release();
-                }
-            }
-        };
-
-        final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-        mContext.registerReceiver(receiver, filter);
-        assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
-        boolean success = false;
-        try {
-            success = completionSemaphore.tryAcquire(DISCOVERABLE_UNDISCOVERABLE_TIMEOUT,
-                    TimeUnit.MILLISECONDS);
-            writeOutput(String.format("discoverable() completed in 0 ms"));
-        } catch (final InterruptedException e) {
-            // This should never happen but just in case it does, the test will fail anyway.
-        }
-        mContext.unregisterReceiver(receiver);
-        if (!success) {
-            fail(String.format("discoverable() timeout: scanMode=%d (expected %d)", scanMode,
-                    BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
-        }
-    }
-
-    /**
-     * Puts the local device into connectable only mode and checks to make sure that the local
-     * device is in in connectable mode and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void undiscoverable(BluetoothAdapter adapter) {
-        if (!adapter.isEnabled()) {
-            fail("undiscoverable() bluetooth not enabled");
-        }
-
-        int scanMode = adapter.getScanMode();
-        if (scanMode != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
-            return;
-        }
-
-        final Semaphore completionSemaphore = new Semaphore(0);
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                if (!BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
-                    return;
-                }
-                final int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,
-                        BluetoothAdapter.SCAN_MODE_NONE);
-                if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
-                    completionSemaphore.release();
-                }
-            }
-        };
-
-        final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-        mContext.registerReceiver(receiver, filter);
-        assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
-        boolean success = false;
-        try {
-            success = completionSemaphore.tryAcquire(DISCOVERABLE_UNDISCOVERABLE_TIMEOUT,
-                    TimeUnit.MILLISECONDS);
-            writeOutput(String.format("undiscoverable() completed in 0 ms"));
-        } catch (InterruptedException e) {
-            // This should never happen but just in case it does, the test will fail anyway.
-        }
-        mContext.unregisterReceiver(receiver);
-        if (!success) {
-            fail(String.format("undiscoverable() timeout: scanMode=%d (expected %d)", scanMode,
-                    BluetoothAdapter.SCAN_MODE_CONNECTABLE));
-        }
-    }
-
-    /**
-     * Starts a scan for remote devices and checks to make sure that the local device is scanning
-     * and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void startScan(BluetoothAdapter adapter) {
-        int mask = BluetoothReceiver.DISCOVERY_STARTED_FLAG;
-
-        if (!adapter.isEnabled()) {
-            fail("startScan() bluetooth not enabled");
-        }
-
-        if (adapter.isDiscovering()) {
-            return;
-        }
-
-        BluetoothReceiver receiver = getBluetoothReceiver(mask);
-
-        long start = System.currentTimeMillis();
-        assertTrue(adapter.startDiscovery());
-
-        while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
-            if (adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
-                writeOutput(String.format("startScan() completed in %d ms",
-                        (receiver.getCompletedTime() - start)));
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("startScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
-                adapter.isDiscovering(), firedFlags, mask));
-    }
-
-    /**
-     * Stops a scan for remote devices and checks to make sure that the local device is not scanning
-     * and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void stopScan(BluetoothAdapter adapter) {
-        int mask = BluetoothReceiver.DISCOVERY_FINISHED_FLAG;
-
-        if (!adapter.isEnabled()) {
-            fail("stopScan() bluetooth not enabled");
-        }
-
-        if (!adapter.isDiscovering()) {
-            return;
-        }
-
-        BluetoothReceiver receiver = getBluetoothReceiver(mask);
-
-        long start = System.currentTimeMillis();
-        assertTrue(adapter.cancelDiscovery());
-
-        while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
-            if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
-                writeOutput(String.format("stopScan() completed in %d ms",
-                        (receiver.getCompletedTime() - start)));
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("stopScan() timeout: isDiscovering=%b, flags=0x%x (expected 0x%x)",
-                adapter.isDiscovering(), firedFlags, mask));
-
-    }
-
-    /**
-     * Enables PAN tethering on the local device and checks to make sure that tethering is enabled.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void enablePan(BluetoothAdapter adapter) {
-        if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
-        assertNotNull(mPan);
-
-        long start = System.currentTimeMillis();
-        mPan.setBluetoothTethering(true);
-        long stop = System.currentTimeMillis();
-        assertTrue(mPan.isTetheringOn());
-
-        writeOutput(String.format("enablePan() completed in %d ms", (stop - start)));
-    }
-
-    /**
-     * Disables PAN tethering on the local device and checks to make sure that tethering is
-     * disabled.
-     *
-     * @param adapter The BT adapter.
-     */
-    public void disablePan(BluetoothAdapter adapter) {
-        if (mPan == null) mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
-        assertNotNull(mPan);
-
-        long start = System.currentTimeMillis();
-        mPan.setBluetoothTethering(false);
-        long stop = System.currentTimeMillis();
-        assertFalse(mPan.isTetheringOn());
-
-        writeOutput(String.format("disablePan() completed in %d ms", (stop - start)));
-    }
-
-    /**
-     * Initiates a pairing with a remote device and checks to make sure that the devices are paired
-     * and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
-     * @param pin The pairing pin if pairing requires a pin. Any value if not.
-     */
-    public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
-        pairOrAcceptPair(adapter, device, passkey, pin, true);
-    }
-
-    /**
-     * Accepts a pairing with a remote device and checks to make sure that the devices are paired
-     * and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
-     * @param pin The pairing pin if pairing requires a pin. Any value if not.
-     */
-    public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
-            byte[] pin) {
-        pairOrAcceptPair(adapter, device, passkey, pin, false);
-    }
-
-    /**
-     * Helper method used by {@link #pair(BluetoothAdapter, BluetoothDevice, int, byte[])} and
-     * {@link #acceptPair(BluetoothAdapter, BluetoothDevice, int, byte[])} to either pair or accept
-     * a pairing request.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
-     * @param pin The pairing pin if pairing requires a pin. Any value if not.
-     * @param shouldPair Whether to pair or accept the pair.
-     */
-    private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
-            byte[] pin, boolean shouldPair) {
-        int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
-        long start = -1;
-        String methodName;
-        if (shouldPair) {
-            methodName = String.format("pair(device=%s)", device);
-        } else {
-            methodName = String.format("acceptPair(device=%s)", device);
-        }
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        PairReceiver receiver = getPairReceiver(device, passkey, pin, mask);
-
-        int state = device.getBondState();
-        switch (state) {
-            case BluetoothDevice.BOND_NONE:
-                assertFalse(adapter.getBondedDevices().contains(device));
-                start = System.currentTimeMillis();
-                if (shouldPair) {
-                    assertTrue(device.createBond());
-                }
-                break;
-            case BluetoothDevice.BOND_BONDING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            case BluetoothDevice.BOND_BONDED:
-                assertTrue(adapter.getBondedDevices().contains(device));
-                return;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("%s invalid state: state=%d", methodName, state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
-            state = device.getBondState();
-            if (state == BluetoothDevice.BOND_BONDED && (receiver.getFiredFlags() & mask) == mask) {
-                assertTrue(adapter.getBondedDevices().contains(device));
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
-                methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask));
-    }
-
-    /**
-     * Deletes a pairing with a remote device and checks to make sure that the devices are unpaired
-     * and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
-        int mask = PairReceiver.STATE_NONE_FLAG;
-        long start = -1;
-        String methodName = String.format("unpair(device=%s)", device);
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        PairReceiver receiver = getPairReceiver(device, 0, null, mask);
-
-        int state = device.getBondState();
-        switch (state) {
-            case BluetoothDevice.BOND_NONE:
-                assertFalse(adapter.getBondedDevices().contains(device));
-                removeReceiver(receiver);
-                return;
-            case BluetoothDevice.BOND_BONDING:
-                start = System.currentTimeMillis();
-                assertTrue(device.removeBond());
-                break;
-            case BluetoothDevice.BOND_BONDED:
-                assertTrue(adapter.getBondedDevices().contains(device));
-                start = System.currentTimeMillis();
-                assertTrue(device.removeBond());
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("%s invalid state: state=%d", methodName, state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
-            if (device.getBondState() == BluetoothDevice.BOND_NONE
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                assertFalse(adapter.getBondedDevices().contains(device));
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
-                methodName, state, BluetoothDevice.BOND_BONDED, firedFlags, mask));
-    }
-
-    /**
-     * Deletes all pairings of remote devices
-     * @param adapter the BT adapter
-     */
-    public void unpairAll(BluetoothAdapter adapter) {
-        Set<BluetoothDevice> devices = adapter.getBondedDevices();
-        for (BluetoothDevice device : devices) {
-            unpair(adapter, device);
-        }
-    }
-
-    /**
-     * Connects a profile from the local device to a remote device and checks to make sure that the
-     * profile is connected and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param profile The profile to connect. One of {@link BluetoothProfile#A2DP},
-     * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#HID_HOST} or {@link BluetoothProfile#MAP_CLIENT}..
-     * @param methodName The method name to printed in the logs.  If null, will be
-     * "connectProfile(profile=&lt;profile&gt;, device=&lt;device&gt;)"
-     */
-    public void connectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile,
-            String methodName) {
-        if (methodName == null) {
-            methodName = String.format("connectProfile(profile=%d, device=%s)", profile, device);
-        }
-        int mask = (ConnectProfileReceiver.STATE_CONNECTING_FLAG
-                | ConnectProfileReceiver.STATE_CONNECTED_FLAG);
-        long start = -1;
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        BluetoothProfile proxy = connectProxy(adapter, profile);
-        assertNotNull(proxy);
-
-        ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
-
-        int state = proxy.getConnectionState(device);
-        switch (state) {
-            case BluetoothProfile.STATE_CONNECTED:
-                removeReceiver(receiver);
-                return;
-            case BluetoothProfile.STATE_CONNECTING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            case BluetoothProfile.STATE_DISCONNECTED:
-            case BluetoothProfile.STATE_DISCONNECTING:
-                start = System.currentTimeMillis();
-                if (profile == BluetoothProfile.A2DP) {
-                    assertTrue(((BluetoothA2dp)proxy).connect(device));
-                } else if (profile == BluetoothProfile.HEADSET) {
-                    assertTrue(((BluetoothHeadset)proxy).connect(device));
-                } else if (profile == BluetoothProfile.HID_HOST) {
-                    assertTrue(((BluetoothHidHost)proxy).connect(device));
-                } else if (profile == BluetoothProfile.MAP_CLIENT) {
-                    assertTrue(((BluetoothMapClient)proxy).connect(device));
-                }
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("%s invalid state: state=%d", methodName, state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
-            state = proxy.getConnectionState(device);
-            if (state == BluetoothProfile.STATE_CONNECTED
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
-                methodName, state, BluetoothProfile.STATE_CONNECTED, firedFlags, mask));
-    }
-
-    /**
-     * Disconnects a profile between the local device and a remote device and checks to make sure
-     * that the profile is disconnected and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param profile The profile to disconnect. One of {@link BluetoothProfile#A2DP},
-     * {@link BluetoothProfile#HEADSET}, or {@link BluetoothProfile#HID_HOST}.
-     * @param methodName The method name to printed in the logs.  If null, will be
-     * "connectProfile(profile=&lt;profile&gt;, device=&lt;device&gt;)"
-     */
-    public void disconnectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile,
-            String methodName) {
-        if (methodName == null) {
-            methodName = String.format("disconnectProfile(profile=%d, device=%s)", profile, device);
-        }
-        int mask = (ConnectProfileReceiver.STATE_DISCONNECTING_FLAG
-                | ConnectProfileReceiver.STATE_DISCONNECTED_FLAG);
-        long start = -1;
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        BluetoothProfile proxy = connectProxy(adapter, profile);
-        assertNotNull(proxy);
-
-        ConnectProfileReceiver receiver = getConnectProfileReceiver(device, profile, mask);
-
-        int state = proxy.getConnectionState(device);
-        switch (state) {
-            case BluetoothProfile.STATE_CONNECTED:
-            case BluetoothProfile.STATE_CONNECTING:
-                start = System.currentTimeMillis();
-                if (profile == BluetoothProfile.A2DP) {
-                    assertTrue(((BluetoothA2dp)proxy).disconnect(device));
-                } else if (profile == BluetoothProfile.HEADSET) {
-                    assertTrue(((BluetoothHeadset)proxy).disconnect(device));
-                } else if (profile == BluetoothProfile.HID_HOST) {
-                    assertTrue(((BluetoothHidHost)proxy).disconnect(device));
-                } else if (profile == BluetoothProfile.MAP_CLIENT) {
-                    assertTrue(((BluetoothMapClient)proxy).disconnect(device));
-                }
-                break;
-            case BluetoothProfile.STATE_DISCONNECTED:
-                removeReceiver(receiver);
-                return;
-            case BluetoothProfile.STATE_DISCONNECTING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("%s invalid state: state=%d", methodName, state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
-            state = proxy.getConnectionState(device);
-            if (state == BluetoothProfile.STATE_DISCONNECTED
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%x)",
-                methodName, state, BluetoothProfile.STATE_DISCONNECTED, firedFlags, mask));
-    }
-
-    /**
-     * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
-     * the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void connectPan(BluetoothAdapter adapter, BluetoothDevice device) {
-        connectPanOrIncomingPanConnection(adapter, device, true);
-    }
-
-    /**
-     * Checks that a remote PANU connects to the local NAP correctly and that the correct actions
-     * were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void incomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device) {
-        connectPanOrIncomingPanConnection(adapter, device, false);
-    }
-
-    /**
-     * Helper method used by {@link #connectPan(BluetoothAdapter, BluetoothDevice)} and
-     * {@link #incomingPanConnection(BluetoothAdapter, BluetoothDevice)} to either connect to a
-     * remote NAP or verify that a remote device connected to the local NAP.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param connect If the method should initiate the connection (is PANU)
-     */
-    private void connectPanOrIncomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device,
-            boolean connect) {
-        long start = -1;
-        int mask, role;
-        String methodName;
-
-        if (connect) {
-            methodName = String.format("connectPan(device=%s)", device);
-            mask = (ConnectProfileReceiver.STATE_CONNECTED_FLAG |
-                    ConnectProfileReceiver.STATE_CONNECTING_FLAG);
-            role = BluetoothPan.LOCAL_PANU_ROLE;
-        } else {
-            methodName = String.format("incomingPanConnection(device=%s)", device);
-            mask = ConnectProfileReceiver.STATE_CONNECTED_FLAG;
-            role = BluetoothPan.LOCAL_NAP_ROLE;
-        }
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
-        assertNotNull(mPan);
-        ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
-
-        int state = mPan.getConnectionState(device);
-        switch (state) {
-            case BluetoothPan.STATE_CONNECTED:
-                removeReceiver(receiver);
-                return;
-            case BluetoothPan.STATE_CONNECTING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            case BluetoothPan.STATE_DISCONNECTED:
-            case BluetoothPan.STATE_DISCONNECTING:
-                start = System.currentTimeMillis();
-                if (role == BluetoothPan.LOCAL_PANU_ROLE) {
-                    Log.i("BT", "connect to pan");
-                    assertTrue(mPan.connect(device));
-                }
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("%s invalid state: state=%d", methodName, state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
-            state = mPan.getConnectionState(device);
-            if (state == BluetoothPan.STATE_CONNECTED
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
-                methodName, state, BluetoothPan.STATE_CONNECTED, firedFlags, mask));
-    }
-
-    /**
-     * Disconnects the PANU from a remote NAP and checks to make sure that the PANU is disconnected
-     * and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void disconnectPan(BluetoothAdapter adapter, BluetoothDevice device) {
-        disconnectFromRemoteOrVerifyConnectNap(adapter, device, true);
-    }
-
-    /**
-     * Checks that a remote PANU disconnects from the local NAP correctly and that the correct
-     * actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void incomingPanDisconnection(BluetoothAdapter adapter, BluetoothDevice device) {
-        disconnectFromRemoteOrVerifyConnectNap(adapter, device, false);
-    }
-
-    /**
-     * Helper method used by {@link #disconnectPan(BluetoothAdapter, BluetoothDevice)} and
-     * {@link #incomingPanDisconnection(BluetoothAdapter, BluetoothDevice)} to either disconnect
-     * from a remote NAP or verify that a remote device disconnected from the local NAP.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param disconnect Whether the method should connect or verify.
-     */
-    private void disconnectFromRemoteOrVerifyConnectNap(BluetoothAdapter adapter,
-            BluetoothDevice device, boolean disconnect) {
-        long start = -1;
-        int mask, role;
-        String methodName;
-
-        if (disconnect) {
-            methodName = String.format("disconnectPan(device=%s)", device);
-            mask = (ConnectProfileReceiver.STATE_DISCONNECTED_FLAG |
-                    ConnectProfileReceiver.STATE_DISCONNECTING_FLAG);
-            role = BluetoothPan.LOCAL_PANU_ROLE;
-        } else {
-            methodName = String.format("incomingPanDisconnection(device=%s)", device);
-            mask = ConnectProfileReceiver.STATE_DISCONNECTED_FLAG;
-            role = BluetoothPan.LOCAL_NAP_ROLE;
-        }
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        mPan = (BluetoothPan) connectProxy(adapter, BluetoothProfile.PAN);
-        assertNotNull(mPan);
-        ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
-
-        int state = mPan.getConnectionState(device);
-        switch (state) {
-            case BluetoothPan.STATE_CONNECTED:
-            case BluetoothPan.STATE_CONNECTING:
-                start = System.currentTimeMillis();
-                if (role == BluetoothPan.LOCAL_PANU_ROLE) {
-                    assertTrue(mPan.disconnect(device));
-                }
-                break;
-            case BluetoothPan.STATE_DISCONNECTED:
-                removeReceiver(receiver);
-                return;
-            case BluetoothPan.STATE_DISCONNECTING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("%s invalid state: state=%d", methodName, state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
-            state = mPan.getConnectionState(device);
-            if (state == BluetoothHidHost.STATE_DISCONNECTED
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
-                methodName, state, BluetoothHidHost.STATE_DISCONNECTED, firedFlags, mask));
-    }
-
-    /**
-     * Opens a SCO channel using {@link android.media.AudioManager#startBluetoothSco()} and checks
-     * to make sure that the channel is opened and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void startSco(BluetoothAdapter adapter, BluetoothDevice device) {
-        startStopSco(adapter, device, true);
-    }
-
-    /**
-     * Closes a SCO channel using {@link android.media.AudioManager#stopBluetoothSco()} and checks
-     *  to make sure that the channel is closed and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void stopSco(BluetoothAdapter adapter, BluetoothDevice device) {
-        startStopSco(adapter, device, false);
-    }
-    /**
-     * Helper method for {@link #startSco(BluetoothAdapter, BluetoothDevice)} and
-     * {@link #stopSco(BluetoothAdapter, BluetoothDevice)}.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     * @param isStart Whether the SCO channel should be opened.
-     */
-    private void startStopSco(BluetoothAdapter adapter, BluetoothDevice device, boolean isStart) {
-        long start = -1;
-        int mask;
-        String methodName;
-
-        if (isStart) {
-            methodName = String.format("startSco(device=%s)", device);
-            mask = StartStopScoReceiver.STATE_CONNECTED_FLAG;
-        } else {
-            methodName = String.format("stopSco(device=%s)", device);
-            mask = StartStopScoReceiver.STATE_DISCONNECTED_FLAG;
-        }
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        assertNotNull(manager);
-
-        if (!manager.isBluetoothScoAvailableOffCall()) {
-            fail(String.format("%s device does not support SCO", methodName));
-        }
-
-        boolean isScoOn = manager.isBluetoothScoOn();
-        if (isStart == isScoOn) {
-            return;
-        }
-
-        StartStopScoReceiver receiver = getStartStopScoReceiver(mask);
-        start = System.currentTimeMillis();
-        if (isStart) {
-            manager.startBluetoothSco();
-        } else {
-            manager.stopBluetoothSco();
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < START_STOP_SCO_TIMEOUT) {
-            isScoOn = manager.isBluetoothScoOn();
-            if (isStart == isScoOn && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("%s completed in %d ms", methodName,
-                            (finish - start)));
-                } else {
-                    writeOutput(String.format("%s completed", methodName));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: on=%b (expected %b), flags=0x%x (expected 0x%x)",
-                methodName, isScoOn, isStart, firedFlags, mask));
-    }
-
-    /**
-     * Writes a string to the logcat and a file if a file has been specified in the constructor.
-     *
-     * @param s The string to be written.
-     */
-    public void writeOutput(String s) {
-        Log.i(mTag, s);
-        if (mOutputWriter == null) {
-            return;
-        }
-        try {
-            mOutputWriter.write(s + "\n");
-            mOutputWriter.flush();
-        } catch (IOException e) {
-            Log.w(mTag, "Could not write to output file", e);
-        }
-    }
-
-    public void mceGetUnreadMessage(BluetoothAdapter adapter, BluetoothDevice device) {
-        int mask;
-        String methodName = "getUnreadMessage";
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        mMce = (BluetoothMapClient) connectProxy(adapter, BluetoothProfile.MAP_CLIENT);
-        assertNotNull(mMce);
-
-        if (mMce.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
-            fail(String.format("%s device is not connected", methodName));
-        }
-
-        mMsgHandle = null;
-        mask = MceSetMessageStatusReceiver.MESSAGE_RECEIVED_FLAG;
-        MceSetMessageStatusReceiver receiver = getMceSetMessageStatusReceiver(device, mask);
-        assertTrue(mMce.getUnreadMessages(device));
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < GET_UNREAD_MESSAGE_TIMEOUT) {
-            if ((receiver.getFiredFlags() & mask) == mask) {
-                writeOutput(String.format("%s completed", methodName));
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
-                methodName, mMce.getConnectionState(device), BluetoothMapClient.STATE_CONNECTED, firedFlags, mask));
-    }
-
-    /**
-     * Set a message to read/unread/deleted/undeleted
-     */
-    public void mceSetMessageStatus(BluetoothAdapter adapter, BluetoothDevice device, int status) {
-        int mask;
-        String methodName = "setMessageStatus";
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("%s bluetooth not enabled", methodName));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("%s device not paired", methodName));
-        }
-
-        mMce = (BluetoothMapClient) connectProxy(adapter, BluetoothProfile.MAP_CLIENT);
-        assertNotNull(mMce);
-
-        if (mMce.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
-            fail(String.format("%s device is not connected", methodName));
-        }
-
-        assertNotNull(mMsgHandle);
-        mask = MceSetMessageStatusReceiver.STATUS_CHANGED_FLAG;
-        MceSetMessageStatusReceiver receiver = getMceSetMessageStatusReceiver(device, mask);
-
-        assertTrue(mMce.setMessageStatus(device, mMsgHandle, status));
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < SET_MESSAGE_STATUS_TIMEOUT) {
-            if ((receiver.getFiredFlags() & mask) == mask) {
-                writeOutput(String.format("%s completed", methodName));
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)",
-                methodName, mMce.getConnectionState(device), BluetoothPan.STATE_CONNECTED, firedFlags, mask));
-    }
-
-    private void addReceiver(BroadcastReceiver receiver, String[] actions) {
-        IntentFilter filter = new IntentFilter();
-        for (String action: actions) {
-            filter.addAction(action);
-        }
-        mContext.registerReceiver(receiver, filter);
-        mReceivers.add(receiver);
-    }
-
-    private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
-        String[] actions = {
-                BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
-                BluetoothAdapter.ACTION_DISCOVERY_STARTED,
-                BluetoothAdapter.ACTION_SCAN_MODE_CHANGED,
-                BluetoothAdapter.ACTION_STATE_CHANGED};
-        BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
-    private PairReceiver getPairReceiver(BluetoothDevice device, int passkey, byte[] pin,
-            int expectedFlags) {
-        String[] actions = {
-                BluetoothDevice.ACTION_PAIRING_REQUEST,
-                BluetoothDevice.ACTION_BOND_STATE_CHANGED};
-        PairReceiver receiver = new PairReceiver(device, passkey, pin, expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
-    private ConnectProfileReceiver getConnectProfileReceiver(BluetoothDevice device, int profile,
-            int expectedFlags) {
-        String[] actions = {
-                BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
-                BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
-                BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED,
-                BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED};
-        ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
-                expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
-    private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
-            int expectedFlags) {
-        String[] actions = {BluetoothPan.ACTION_CONNECTION_STATE_CHANGED};
-        ConnectPanReceiver receiver = new ConnectPanReceiver(device, role, expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
-    private StartStopScoReceiver getStartStopScoReceiver(int expectedFlags) {
-        String[] actions = {AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED};
-        StartStopScoReceiver receiver = new StartStopScoReceiver(expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
-    private MceSetMessageStatusReceiver getMceSetMessageStatusReceiver(BluetoothDevice device,
-            int expectedFlags) {
-        String[] actions = {BluetoothMapClient.ACTION_MESSAGE_RECEIVED,
-            BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED,
-            BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED};
-        MceSetMessageStatusReceiver receiver = new MceSetMessageStatusReceiver(expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
-    private void removeReceiver(BroadcastReceiver receiver) {
-        mContext.unregisterReceiver(receiver);
-        mReceivers.remove(receiver);
-    }
-
-    private BluetoothProfile connectProxy(BluetoothAdapter adapter, int profile) {
-        switch (profile) {
-            case BluetoothProfile.A2DP:
-                if (mA2dp != null) {
-                    return mA2dp;
-                }
-                break;
-            case BluetoothProfile.HEADSET:
-                if (mHeadset != null) {
-                    return mHeadset;
-                }
-                break;
-            case BluetoothProfile.HID_HOST:
-                if (mInput != null) {
-                    return mInput;
-                }
-                break;
-            case BluetoothProfile.PAN:
-                if (mPan != null) {
-                    return mPan;
-                }
-            case BluetoothProfile.MAP_CLIENT:
-                if (mMce != null) {
-                    return mMce;
-                }
-                break;
-            default:
-                return null;
-        }
-        adapter.getProfileProxy(mContext, mServiceListener, profile);
-        long s = System.currentTimeMillis();
-        switch (profile) {
-            case BluetoothProfile.A2DP:
-                while (mA2dp == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
-                    sleep(POLL_TIME);
-                }
-                return mA2dp;
-            case BluetoothProfile.HEADSET:
-                while (mHeadset == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
-                    sleep(POLL_TIME);
-                }
-                return mHeadset;
-            case BluetoothProfile.HID_HOST:
-                while (mInput == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
-                    sleep(POLL_TIME);
-                }
-                return mInput;
-            case BluetoothProfile.PAN:
-                while (mPan == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
-                    sleep(POLL_TIME);
-                }
-                return mPan;
-            case BluetoothProfile.MAP_CLIENT:
-                while (mMce == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
-                    sleep(POLL_TIME);
-                }
-                return mMce;
-            default:
-                return null;
-        }
-    }
-
-    private void sleep(long time) {
-        try {
-            Thread.sleep(time);
-        } catch (InterruptedException e) {
-        }
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
deleted file mode 100644
index 536d722..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link BluetoothUuid}.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.BluetoothUuidTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class BluetoothUuidTest extends TestCase {
-
-    @SmallTest
-    public void testUuidParser() {
-        byte[] uuid16 = new byte[] {
-                0x0B, 0x11 };
-        assertEquals(ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"),
-                BluetoothUuid.parseUuidFrom(uuid16));
-
-        byte[] uuid32 = new byte[] {
-                0x0B, 0x11, 0x33, (byte) 0xFE };
-        assertEquals(ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB"),
-                BluetoothUuid.parseUuidFrom(uuid32));
-
-        byte[] uuid128 = new byte[] {
-                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-                0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, (byte) 0xFF };
-        assertEquals(ParcelUuid.fromString("FF0F0E0D-0C0B-0A09-0807-0060504030201"),
-                BluetoothUuid.parseUuidFrom(uuid128));
-    }
-
-    @SmallTest
-    public void testUuidType() {
-        assertTrue(BluetoothUuid.is16BitUuid(
-                ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB")));
-        assertFalse(BluetoothUuid.is32BitUuid(
-                ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB")));
-
-        assertFalse(BluetoothUuid.is16BitUuid(
-                ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB")));
-        assertTrue(BluetoothUuid.is32BitUuid(
-                ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB")));
-        assertFalse(BluetoothUuid.is32BitUuid(
-                ParcelUuid.fromString("FE33110B-1000-1000-8000-00805F9B34FB")));
-
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/AdvertiseDataTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/AdvertiseDataTest.java
deleted file mode 100644
index e58d905..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/AdvertiseDataTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for {@link AdvertiseData}.
- * <p>
- * To run the test, use adb shell am instrument -e class 'android.bluetooth.le.AdvertiseDataTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class AdvertiseDataTest extends TestCase {
-
-    private AdvertiseData.Builder mAdvertiseDataBuilder;
-
-    @Override
-    protected void setUp() throws Exception {
-        mAdvertiseDataBuilder = new AdvertiseData.Builder();
-    }
-
-    @SmallTest
-    public void testEmptyData() {
-        Parcel parcel = Parcel.obtain();
-        AdvertiseData data = mAdvertiseDataBuilder.build();
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-
-    @SmallTest
-    public void testEmptyServiceUuid() {
-        Parcel parcel = Parcel.obtain();
-        AdvertiseData data = mAdvertiseDataBuilder.setIncludeDeviceName(true).build();
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-
-    @SmallTest
-    public void testEmptyManufacturerData() {
-        Parcel parcel = Parcel.obtain();
-        int manufacturerId = 50;
-        byte[] manufacturerData = new byte[0];
-        AdvertiseData data =
-                mAdvertiseDataBuilder.setIncludeDeviceName(true)
-                        .addManufacturerData(manufacturerId, manufacturerData).build();
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-
-    @SmallTest
-    public void testEmptyServiceData() {
-        Parcel parcel = Parcel.obtain();
-        ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-        byte[] serviceData = new byte[0];
-        AdvertiseData data =
-                mAdvertiseDataBuilder.setIncludeDeviceName(true)
-                        .addServiceData(uuid, serviceData).build();
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-
-    @SmallTest
-    public void testServiceUuid() {
-        Parcel parcel = Parcel.obtain();
-        ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-        ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-
-        AdvertiseData data =
-                mAdvertiseDataBuilder.setIncludeDeviceName(true)
-                        .addServiceUuid(uuid).addServiceUuid(uuid2).build();
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-
-    @SmallTest
-    public void testManufacturerData() {
-        Parcel parcel = Parcel.obtain();
-        ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-        ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-
-        int manufacturerId = 50;
-        byte[] manufacturerData = new byte[] {
-                (byte) 0xF0, 0x00, 0x02, 0x15 };
-        AdvertiseData data =
-                mAdvertiseDataBuilder.setIncludeDeviceName(true)
-                        .addServiceUuid(uuid).addServiceUuid(uuid2)
-                        .addManufacturerData(manufacturerId, manufacturerData).build();
-
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-
-    @SmallTest
-    public void testServiceData() {
-        Parcel parcel = Parcel.obtain();
-        ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-        byte[] serviceData = new byte[] {
-                (byte) 0xF0, 0x00, 0x02, 0x15 };
-        AdvertiseData data =
-                mAdvertiseDataBuilder.setIncludeDeviceName(true)
-                        .addServiceData(uuid, serviceData).build();
-        data.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AdvertiseData dataFromParcel =
-                AdvertiseData.CREATOR.createFromParcel(parcel);
-        assertEquals(data, dataFromParcel);
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
deleted file mode 100644
index 35da4bc..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanFilterTest.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanRecord;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for Bluetooth LE scan filters.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanFilterTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class ScanFilterTest extends TestCase {
-
-    private static final String DEVICE_MAC = "01:02:03:04:05:AB";
-    private ScanResult mScanResult;
-    private ScanFilter.Builder mFilterBuilder;
-
-    @Override
-    protected void setUp() throws Exception {
-        byte[] scanRecord = new byte[] {
-                0x02, 0x01, 0x1a, // advertising flags
-                0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids
-                0x04, 0x09, 0x50, 0x65, 0x64, // setName
-                0x02, 0x0A, (byte) 0xec, // tx power level
-                0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data
-                0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data
-                0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble
-        };
-
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        BluetoothDevice device = adapter.getRemoteDevice(DEVICE_MAC);
-        mScanResult = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord),
-                -10, 1397545200000000L);
-        mFilterBuilder = new ScanFilter.Builder();
-    }
-
-    @SmallTest
-    public void testsetNameFilter() {
-        ScanFilter filter = mFilterBuilder.setDeviceName("Ped").build();
-        assertTrue("setName filter fails", filter.matches(mScanResult));
-
-        filter = mFilterBuilder.setDeviceName("Pem").build();
-        assertFalse("setName filter fails", filter.matches(mScanResult));
-
-    }
-
-    @SmallTest
-    public void testDeviceFilter() {
-        ScanFilter filter = mFilterBuilder.setDeviceAddress(DEVICE_MAC).build();
-        assertTrue("device filter fails", filter.matches(mScanResult));
-
-        filter = mFilterBuilder.setDeviceAddress("11:22:33:44:55:66").build();
-        assertFalse("device filter fails", filter.matches(mScanResult));
-    }
-
-    @SmallTest
-    public void testsetServiceUuidFilter() {
-        ScanFilter filter = mFilterBuilder.setServiceUuid(
-                ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB")).build();
-        assertTrue("uuid filter fails", filter.matches(mScanResult));
-
-        filter = mFilterBuilder.setServiceUuid(
-                ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB")).build();
-        assertFalse("uuid filter fails", filter.matches(mScanResult));
-
-        filter = mFilterBuilder
-                .setServiceUuid(ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"),
-                        ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF"))
-                .build();
-        assertTrue("uuid filter fails", filter.matches(mScanResult));
-    }
-
-    @SmallTest
-    public void testsetServiceDataFilter() {
-        byte[] setServiceData = new byte[] {
-                0x50, 0x64 };
-        ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-        ScanFilter filter = mFilterBuilder.setServiceData(serviceDataUuid, setServiceData).build();
-        assertTrue("service data filter fails", filter.matches(mScanResult));
-
-        byte[] emptyData = new byte[0];
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, emptyData).build();
-        assertTrue("service data filter fails", filter.matches(mScanResult));
-
-        byte[] prefixData = new byte[] {
-                0x50 };
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, prefixData).build();
-        assertTrue("service data filter fails", filter.matches(mScanResult));
-
-        byte[] nonMatchData = new byte[] {
-                0x51, 0x64 };
-        byte[] mask = new byte[] {
-                (byte) 0x00, (byte) 0xFF };
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData, mask).build();
-        assertTrue("partial service data filter fails", filter.matches(mScanResult));
-
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, nonMatchData).build();
-        assertFalse("service data filter fails", filter.matches(mScanResult));
-    }
-
-    @SmallTest
-    public void testManufacturerSpecificData() {
-        byte[] setManufacturerData = new byte[] {
-                0x02, 0x15 };
-        int manufacturerId = 0xE0;
-        ScanFilter filter =
-                mFilterBuilder.setManufacturerData(manufacturerId, setManufacturerData).build();
-        assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
-
-        byte[] emptyData = new byte[0];
-        filter = mFilterBuilder.setManufacturerData(manufacturerId, emptyData).build();
-        assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
-
-        byte[] prefixData = new byte[] {
-                0x02 };
-        filter = mFilterBuilder.setManufacturerData(manufacturerId, prefixData).build();
-        assertTrue("manufacturer data filter fails", filter.matches(mScanResult));
-
-        // Test data mask
-        byte[] nonMatchData = new byte[] {
-                0x02, 0x14 };
-        filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData).build();
-        assertFalse("manufacturer data filter fails", filter.matches(mScanResult));
-        byte[] mask = new byte[] {
-                (byte) 0xFF, (byte) 0x00
-        };
-        filter = mFilterBuilder.setManufacturerData(manufacturerId, nonMatchData, mask).build();
-        assertTrue("partial setManufacturerData filter fails", filter.matches(mScanResult));
-    }
-
-    @SmallTest
-    public void testReadWriteParcel() {
-        ScanFilter filter = mFilterBuilder.build();
-        testReadWriteParcelForFilter(filter);
-
-        filter = mFilterBuilder.setDeviceName("Ped").build();
-        testReadWriteParcelForFilter(filter);
-
-        filter = mFilterBuilder.setDeviceAddress("11:22:33:44:55:66").build();
-        testReadWriteParcelForFilter(filter);
-
-        filter = mFilterBuilder.setServiceUuid(
-                ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB")).build();
-        testReadWriteParcelForFilter(filter);
-
-        filter = mFilterBuilder.setServiceUuid(
-                ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB"),
-                ParcelUuid.fromString("FFFFFFF0-FFFF-FFFF-FFFF-FFFFFFFFFFFF")).build();
-        testReadWriteParcelForFilter(filter);
-
-        byte[] serviceData = new byte[] {
-                0x50, 0x64 };
-
-        ParcelUuid serviceDataUuid = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData).build();
-        testReadWriteParcelForFilter(filter);
-
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build();
-        testReadWriteParcelForFilter(filter);
-
-        byte[] serviceDataMask = new byte[] {
-                (byte) 0xFF, (byte) 0xFF };
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, serviceData, serviceDataMask)
-                .build();
-        testReadWriteParcelForFilter(filter);
-
-        byte[] manufacturerData = new byte[] {
-                0x02, 0x15 };
-        int manufacturerId = 0xE0;
-        filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData).build();
-        testReadWriteParcelForFilter(filter);
-
-        filter = mFilterBuilder.setServiceData(serviceDataUuid, new byte[0]).build();
-        testReadWriteParcelForFilter(filter);
-
-        byte[] manufacturerDataMask = new byte[] {
-                (byte) 0xFF, (byte) 0xFF
-        };
-        filter = mFilterBuilder.setManufacturerData(manufacturerId, manufacturerData,
-                manufacturerDataMask).build();
-        testReadWriteParcelForFilter(filter);
-    }
-
-    private void testReadWriteParcelForFilter(ScanFilter filter) {
-        Parcel parcel = Parcel.obtain();
-        filter.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        ScanFilter filterFromParcel =
-                ScanFilter.CREATOR.createFromParcel(parcel);
-        assertEquals(filter, filterFromParcel);
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
deleted file mode 100644
index 4e817d4..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanRecordTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.os.ParcelUuid;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.internal.util.HexDump;
-import com.android.modules.utils.BytesMatcher;
-
-import junit.framework.TestCase;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Predicate;
-
-/**
- * Unit test cases for {@link ScanRecord}.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanRecordTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class ScanRecordTest extends TestCase {
-    /**
-     * Example raw beacons captured from a Blue Charm BC011
-     */
-    private static final String RECORD_URL = "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730009168020691E0EFE13551109426C7565436861726D5F313639363835000000";
-    private static final String RECORD_UUID = "0201060303AAFE1716AAFE00EE626C7565636861726D31000000000001000009168020691E0EFE13551109426C7565436861726D5F313639363835000000";
-    private static final String RECORD_TLM = "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080EFE13551109426C7565436861726D5F313639363835000000000000000000";
-    private static final String RECORD_IBEACON = "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000";
-
-    @SmallTest
-    public void testMatchesAnyField_Eddystone_Parser() {
-        final List<String> found = new ArrayList<>();
-        final Predicate<byte[]> matcher = (v) -> {
-            found.add(HexDump.toHexString(v));
-            return false;
-        };
-        ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(RECORD_URL))
-                .matchesAnyField(matcher);
-
-        assertEquals(Arrays.asList(
-                "020106",
-                "0303AAFE",
-                "1716AAFE10EE01626C7565636861726D626561636F6E7300",
-                "09168020691E0EFE1355",
-                "1109426C7565436861726D5F313639363835"), found);
-    }
-
-    @SmallTest
-    public void testMatchesAnyField_Eddystone() {
-        final BytesMatcher matcher = BytesMatcher.decode("⊆0016AAFE/00FFFFFF");
-        assertMatchesAnyField(RECORD_URL, matcher);
-        assertMatchesAnyField(RECORD_UUID, matcher);
-        assertMatchesAnyField(RECORD_TLM, matcher);
-        assertNotMatchesAnyField(RECORD_IBEACON, matcher);
-    }
-
-    @SmallTest
-    public void testMatchesAnyField_iBeacon_Parser() {
-        final List<String> found = new ArrayList<>();
-        final Predicate<byte[]> matcher = (v) -> {
-            found.add(HexDump.toHexString(v));
-            return false;
-        };
-        ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(RECORD_IBEACON))
-                .matchesAnyField(matcher);
-
-        assertEquals(Arrays.asList(
-                "020106",
-                "1AFF4C000215426C7565436861726D426561636F6E730EFE1355C5",
-                "09168020691E0EFE1355",
-                "1109426C7565436861726D5F313639363835"), found);
-    }
-
-    @SmallTest
-    public void testMatchesAnyField_iBeacon() {
-        final BytesMatcher matcher = BytesMatcher.decode("⊆00FF4C0002/00FFFFFFFF");
-        assertNotMatchesAnyField(RECORD_URL, matcher);
-        assertNotMatchesAnyField(RECORD_UUID, matcher);
-        assertNotMatchesAnyField(RECORD_TLM, matcher);
-        assertMatchesAnyField(RECORD_IBEACON, matcher);
-    }
-
-    @SmallTest
-    public void testParser() {
-        byte[] scanRecord = new byte[] {
-                0x02, 0x01, 0x1a, // advertising flags
-                0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids
-                0x04, 0x09, 0x50, 0x65, 0x64, // name
-                0x02, 0x0A, (byte) 0xec, // tx power level
-                0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data
-                0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data
-                0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble
-        };
-        ScanRecord data = ScanRecord.parseFromBytes(scanRecord);
-        assertEquals(0x1a, data.getAdvertiseFlags());
-        ParcelUuid uuid1 = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-        ParcelUuid uuid2 = ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-        assertTrue(data.getServiceUuids().contains(uuid1));
-        assertTrue(data.getServiceUuids().contains(uuid2));
-
-        assertEquals("Ped", data.getDeviceName());
-        assertEquals(-20, data.getTxPowerLevel());
-
-        assertTrue(data.getManufacturerSpecificData().get(0x00E0) != null);
-        assertArrayEquals(new byte[] {
-                0x02, 0x15 }, data.getManufacturerSpecificData().get(0x00E0));
-
-        assertTrue(data.getServiceData().containsKey(uuid2));
-        assertArrayEquals(new byte[] {
-                0x50, 0x64 }, data.getServiceData().get(uuid2));
-    }
-
-    // Assert two byte arrays are equal.
-    private static void assertArrayEquals(byte[] expected, byte[] actual) {
-        if (!Arrays.equals(expected, actual)) {
-            fail("expected:<" + Arrays.toString(expected) +
-                    "> but was:<" + Arrays.toString(actual) + ">");
-        }
-
-    }
-
-    private static void assertMatchesAnyField(String record, BytesMatcher matcher) {
-        assertTrue(ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(record))
-                .matchesAnyField(matcher));
-    }
-
-    private static void assertNotMatchesAnyField(String record, BytesMatcher matcher) {
-        assertFalse(ScanRecord.parseFromBytes(HexDump.hexStringToByteArray(record))
-                .matchesAnyField(matcher));
-    }
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanResultTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanResultTest.java
deleted file mode 100644
index 01d5c59..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanResultTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Unit test cases for Bluetooth LE scans.
- * <p>
- * To run this test, use adb shell am instrument -e class 'android.bluetooth.ScanResultTest' -w
- * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
-public class ScanResultTest extends TestCase {
-
-    /**
-     * Test read and write parcel of ScanResult
-     */
-    @SmallTest
-    public void testScanResultParceling() {
-        BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(
-                "01:02:03:04:05:06");
-        byte[] scanRecord = new byte[] {
-                1, 2, 3 };
-        int rssi = -10;
-        long timestampMicros = 10000L;
-
-        ScanResult result = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi,
-                timestampMicros);
-        Parcel parcel = Parcel.obtain();
-        result.writeToParcel(parcel, 0);
-        // Need to reset parcel data position to the beginning.
-        parcel.setDataPosition(0);
-        ScanResult resultFromParcel = ScanResult.CREATOR.createFromParcel(parcel);
-        assertEquals(result, resultFromParcel);
-    }
-
-}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanSettingsTest.java b/core/tests/bluetoothtests/src/android/bluetooth/le/ScanSettingsTest.java
deleted file mode 100644
index 7c42c3b..0000000
--- a/core/tests/bluetoothtests/src/android/bluetooth/le/ScanSettingsTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.le;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-/**
- * Test for Bluetooth LE {@link ScanSettings}.
- */
-public class ScanSettingsTest extends TestCase {
-
-    @SmallTest
-    public void testCallbackType() {
-        ScanSettings.Builder builder = new ScanSettings.Builder();
-        builder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
-        builder.setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH);
-        builder.setCallbackType(ScanSettings.CALLBACK_TYPE_MATCH_LOST);
-        builder.setCallbackType(
-                ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST);
-        try {
-            builder.setCallbackType(
-                    ScanSettings.CALLBACK_TYPE_ALL_MATCHES | ScanSettings.CALLBACK_TYPE_MATCH_LOST);
-            fail("should have thrown IllegalArgumentException!");
-        } catch (IllegalArgumentException e) {
-            // nothing to do
-        }
-
-        try {
-            builder.setCallbackType(
-                    ScanSettings.CALLBACK_TYPE_ALL_MATCHES |
-                    ScanSettings.CALLBACK_TYPE_FIRST_MATCH);
-            fail("should have thrown IllegalArgumentException!");
-        } catch (IllegalArgumentException e) {
-            // nothing to do
-        }
-
-        try {
-            builder.setCallbackType(
-                    ScanSettings.CALLBACK_TYPE_ALL_MATCHES |
-                    ScanSettings.CALLBACK_TYPE_FIRST_MATCH |
-                    ScanSettings.CALLBACK_TYPE_MATCH_LOST);
-            fail("should have thrown IllegalArgumentException!");
-        } catch (IllegalArgumentException e) {
-            // nothing to do
-        }
-
-    }
-}
diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS
index 0b94589..a69c6ff 100644
--- a/core/tests/coretests/src/android/content/OWNERS
+++ b/core/tests/coretests/src/android/content/OWNERS
@@ -1,6 +1,7 @@
 per-file AssetTest.java = file:/core/java/android/content/res/OWNERS
-per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Context* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Context* = charlesccchen@google.com
 per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
 per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
-per-file ComponentCallbacksControllerTest = file:/services/core/java/com/android/server/wm/OWNERS
-per-file ComponentCallbacksControllerTest = charlesccchen@google.com
+per-file *ComponentCallbacks* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file *ComponentCallbacks* = charlesccchen@google.com
diff --git a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
index 3c8f90c..6360a2d 100644
--- a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
+++ b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
@@ -16,7 +16,9 @@
 
 package android.net
 
+import android.net.NetworkStats.METERED_YES
 import android.net.NetworkTemplate.MATCH_BLUETOOTH
+import android.net.NetworkTemplate.MATCH_CARRIER
 import android.net.NetworkTemplate.MATCH_ETHERNET
 import android.net.NetworkTemplate.MATCH_MOBILE
 import android.net.NetworkTemplate.MATCH_WIFI
@@ -39,11 +41,19 @@
     @Test
     fun testTemplateBackupRestore() {
         assertPolicyBackupRestore(createTestPolicyForTemplate(
-                NetworkTemplate.buildTemplateWifi(TEST_WIFI_NETWORK_KEY1)))
+                NetworkTemplate.Builder(MATCH_WIFI)
+                    .setWifiNetworkKeys(setOf(TEST_WIFI_NETWORK_KEY1))
+                    .build()))
         assertPolicyBackupRestore(createTestPolicyForTemplate(
-                NetworkTemplate.buildTemplateMobileAll(TEST_IMSI1)))
+                NetworkTemplate.Builder(MATCH_MOBILE)
+                    .setSubscriberIds(setOf(TEST_IMSI1))
+                    .setMeteredness(METERED_YES)
+                    .build()))
         assertPolicyBackupRestore(createTestPolicyForTemplate(
-                NetworkTemplate.buildTemplateCarrierMetered(TEST_IMSI1)))
+                NetworkTemplate.Builder(MATCH_CARRIER)
+                    .setSubscriberIds(setOf(TEST_IMSI1))
+                    .setMeteredness(METERED_YES)
+                    .build()))
     }
 
     private fun createTestPolicyForTemplate(template: NetworkTemplate): NetworkPolicy {
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
index 74cdd21..10f6f1f 100644
--- a/core/tests/coretests/src/android/view/OWNERS
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -16,3 +16,6 @@
 
 # Scroll Capture
 per-file *ScrollCapture*.java = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS
+
+# Stylus
+per-file stylus/* = file:/core/java/android/text/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/widget/OWNERS b/core/tests/coretests/src/android/widget/OWNERS
new file mode 100644
index 0000000..5a9aed3
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/OWNERS
@@ -0,0 +1,5 @@
+include /core/java/android/widget/OWNERS
+
+per-file *SuggestionsPopup* = file:/core/java/android/text/OWNERS
+
+per-file *FloatingToolbar*, *SelectionToolbar* = file:/core/java/android/view/textclassifier/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 40ef04a..152992c 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates;
+import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
 import static android.widget.espresso.DragHandleUtils.onHandleView;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
@@ -426,6 +427,41 @@
     }
 
     @Test
+    public void testSelectionOnCreateActionModeReturnsFalse() throws Throwable {
+        final String text = "hello world";
+        mActivityRule.runOnUiThread(() -> {
+            final TextView textView = mActivity.findViewById(R.id.textview);
+            textView.setText(text);
+            textView.setCustomSelectionActionModeCallback(
+                    new ActionMode.Callback() {
+                        @Override
+                        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+                            return false;
+                        }
+
+                        @Override
+                        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+                            return false;
+                        }
+
+                        @Override
+                        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+                            return false;
+                        }
+
+
+                        @Override
+                        public void onDestroyActionMode(ActionMode mode) {
+                        }
+                    });
+        });
+        mInstrumentation.waitForIdleSync();
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("d")));
+        mInstrumentation.waitForIdleSync();
+        assertNoSelectionHandles();
+    }
+
+    @Test
     public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable {
         final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
         final int position = (textLink.getStart() + textLink.getEnd()) / 2;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
index 74b6dbe..93910b9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -39,6 +39,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import libcore.testing.io.TestIoUtils;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,8 +54,11 @@
     private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
     private static final long MINUTE_IN_MS = 60 * 1000;
 
+    private final File mHistoryDir =
+            TestIoUtils.createTemporaryDirectory(getClass().getSimpleName());
+
     @Rule
-    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345)
+    public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345, mHistoryDir)
             .setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0);
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index 083090c..2c6f5fa 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -40,6 +40,7 @@
 import org.junit.runners.model.Statement;
 import org.mockito.stubbing.Answer;
 
+import java.io.File;
 import java.util.Arrays;
 
 public class BatteryUsageStatsRule implements TestRule {
@@ -57,14 +58,18 @@
     private boolean mScreenOn;
 
     public BatteryUsageStatsRule() {
-        this(0);
+        this(0, null);
     }
 
     public BatteryUsageStatsRule(long currentTime) {
+        this(currentTime, null);
+    }
+
+    public BatteryUsageStatsRule(long currentTime, File historyDir) {
         Context context = InstrumentationRegistry.getContext();
         mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
         mMockClocks.currentTime = currentTime;
-        mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
+        mBatteryStats = new MockBatteryStatsImpl(mMockClocks, historyDir);
         mBatteryStats.setPowerProfile(mPowerProfile);
         mBatteryStats.onSystemReady();
     }
diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
index 48a1da1..a48a882 100644
--- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.os;
 
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
 import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -23,6 +26,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.app.usage.NetworkStatsManager;
 import android.net.NetworkCapabilities;
 import android.net.NetworkStats;
 import android.os.BatteryConsumer;
@@ -40,12 +44,15 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class MobileRadioPowerCalculatorTest {
     private static final double PRECISION = 0.00001;
     private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+    @Mock
+    NetworkStatsManager mNetworkStatsManager;
 
     @Rule
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
@@ -85,12 +92,14 @@
 
         // Note application network activity
         NetworkStats networkStats = new NetworkStats(10000, 1)
-                .insertEntry("cellular", APP_UID, 0, 0, 1000, 100, 2000, 20, 100);
+                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
         mStatsRule.setNetworkStats(networkStats);
 
         ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
                 new int[] {100, 200, 300, 400, 500}, 600);
-        stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000);
+        stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000,
+                mNetworkStatsManager);
 
         mStatsRule.setTime(12_000_000, 12_000_000);
 
@@ -145,12 +154,13 @@
 
         // Note application network activity
         NetworkStats networkStats = new NetworkStats(10000, 1)
-                .insertEntry("cellular", APP_UID, 0, 0, 1000, 100, 2000, 20, 100);
+                .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+                        METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
         mStatsRule.setNetworkStats(networkStats);
 
         ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
                 new int[] {100, 200, 300, 400, 500}, 600);
-        stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000);
+        stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager);
 
         mStatsRule.setTime(12_000_000, 12_000_000);
 
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index cee1a03..11d20f2 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.os;
 
+import android.annotation.NonNull;
+import android.app.usage.NetworkStatsManager;
 import android.net.NetworkStats;
 import android.os.Handler;
 import android.os.Looper;
@@ -27,6 +29,7 @@
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 import com.android.internal.power.MeasuredEnergyStats;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Queue;
@@ -38,10 +41,16 @@
 public class MockBatteryStatsImpl extends BatteryStatsImpl {
     public BatteryStatsImpl.Clocks clocks;
     public boolean mForceOnBattery;
+    // The mNetworkStats will be used for both wifi and mobile categories
     private NetworkStats mNetworkStats;
 
     MockBatteryStatsImpl(Clocks clocks) {
-        super(clocks);
+        this(clocks, null);
+    }
+
+    MockBatteryStatsImpl(Clocks clocks, File historyDirectory) {
+        super(clocks, historyDirectory);
+
         this.clocks = mClocks;
         initTimersAndCounters();
 
@@ -105,10 +114,16 @@
     }
 
     @Override
-    protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
+    protected NetworkStats readMobileNetworkStatsLocked(
+            @NonNull NetworkStatsManager networkStatsManager) {
         return mNetworkStats;
     }
 
+    @Override
+    protected NetworkStats readWifiNetworkStatsLocked(
+            @NonNull NetworkStatsManager networkStatsManager) {
+        return mNetworkStats;
+    }
     public MockBatteryStatsImpl setPowerProfile(PowerProfile powerProfile) {
         mPowerProfile = powerProfile;
         return this;
diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
index fc44ddc..0d944e9 100644
--- a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -16,11 +16,14 @@
 
 package com.android.internal.os;
 
-
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
 import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.usage.NetworkStatsManager;
 import android.net.NetworkCapabilities;
 import android.net.NetworkStats;
 import android.os.BatteryConsumer;
@@ -35,6 +38,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -43,6 +47,9 @@
 
     private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
 
+    @Mock
+    NetworkStatsManager mNetworkStatsManager;
+
     @Rule
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
             .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0)
@@ -62,8 +69,10 @@
                 new int[]{NetworkCapabilities.TRANSPORT_WIFI});
 
         NetworkStats networkStats = new NetworkStats(10000, 1)
-                .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
-                .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
+                .addEntry(new NetworkStats.Entry("wifi", APP_UID, 0, 0, METERED_NO,
+                        ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100))
+                .addEntry(new NetworkStats.Entry("wifi", Process.WIFI_UID, 0, 0, METERED_NO,
+                        ROAMING_NO, DEFAULT_NETWORK_NO, 1111, 111, 2222, 22, 111));
         mStatsRule.setNetworkStats(networkStats);
 
         return batteryStats;
@@ -80,7 +89,8 @@
         final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
         final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
 
-        batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000);
+        batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000,
+                mNetworkStatsManager);
 
         WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
         mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
@@ -113,7 +123,7 @@
         final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
         final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
 
-        batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000);
+        batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000, mNetworkStatsManager);
 
         WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
         mStatsRule.apply(calculator);
@@ -160,7 +170,8 @@
 
         // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
         // on the packet counts.
-        batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000);
+        batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000,
+                mNetworkStatsManager);
 
         WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
         mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
@@ -180,7 +191,8 @@
 
         // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
         // on the packet counts.
-        batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000);
+        batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000,
+                mNetworkStatsManager);
 
         WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
         mStatsRule.apply(calculator);
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 597ea14..12e52c6 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -288,9 +288,8 @@
         }
 
         @Override
-        public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
-                final int deviceType) {
-        }
+        public void addVendorCommandListener(
+                final IHdmiVendorCommandListener listener, final int vendorId) {}
 
         @Override
         public void sendVendorCommand(final int deviceType, final int targetAddress,
diff --git a/core/tests/utillib/Android.bp b/core/tests/utillib/Android.bp
index d40d1d2..1d5c16c 100644
--- a/core/tests/utillib/Android.bp
+++ b/core/tests/utillib/Android.bp
@@ -23,6 +23,7 @@
 
 java_library {
     name: "frameworks-core-util-lib",
+    defaults: ["framework-connectivity-test-defaults"],
 
     srcs: ["**/*.java"],
 
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index be1e2b2..dc07758 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C} 2018 The Android Open Source Project
+// Copyright (C) 2018 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License"};
 // you may not use this file except in compliance with the License.
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 // Sysconfig files
 
 package {
@@ -134,13 +133,6 @@
 }
 
 prebuilt_etc {
-    name: "privapp_whitelist_com.android.networkstack.tethering",
-    sub_dir: "permissions",
-    src: "com.android.networkstack.tethering.xml",
-    filename_from_src: true,
-}
-
-prebuilt_etc {
     name: "privapp_whitelist_com.android.provision",
     system_ext_specific: true,
     sub_dir: "permissions",
diff --git a/data/etc/com.android.networkstack.tethering.xml b/data/etc/com.android.networkstack.tethering.xml
deleted file mode 100644
index f26a961..0000000
--- a/data/etc/com.android.networkstack.tethering.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
--->
-
-<permissions>
-    <privapp-permissions package="com.android.networkstack.tethering">
-        <permission name="android.permission.BLUETOOTH_PRIVILEGED" />
-        <permission name="android.permission.MANAGE_USB"/>
-        <permission name="android.permission.MODIFY_PHONE_STATE"/>
-        <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
-        <permission name="android.permission.TETHER_PRIVILEGED"/>
-        <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
-        <permission name="android.permission.UPDATE_DEVICE_STATS"/>
-      </privapp-permissions>
-</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fefcebe..191d400 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -390,6 +390,10 @@
         <permission name="android.permission.SET_WALLPAPER" />
         <permission name="android.permission.SET_WALLPAPER_COMPONENT" />
         <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
+        <!-- Permission required for CTS test - TrustTestCases -->
+        <permission name="android.permission.PROVIDE_TRUST_AGENT" />
+        <permission name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+        <permission name="android.permission.TRUST_LISTENER" />
         <!-- Permissions required for Incremental CTS tests -->
         <permission name="com.android.permission.USE_INSTALLER_V2"/>
         <permission name="android.permission.LOADER_USAGE_STATS"/>
@@ -458,6 +462,11 @@
         <!-- Permission needed for CTS test - WifiManagerTest -->
         <permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
         <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+        <permission name="android.permission.NEARBY_WIFI_DEVICES" />
+        <permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
+        <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
+             P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. -->
+        <permission name="android.permission.MANAGE_WIFI_AUTO_JOIN" />
         <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest -->
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
         <!-- Permission required for CTS test - MusicRecognitionManagerTest -->
@@ -515,17 +524,6 @@
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.traceur">
-        <!-- Permissions required to receive BUGREPORT_STARTED intent -->
-        <permission name="android.permission.DUMP"/>
-        <!-- Permissions required to start/stop tracing -->
-        <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
-        <!-- Permissions required for quick settings tile -->
-        <permission name="android.permission.STATUS_BAR"/>
-        <!-- Permissions required to query Betterbug -->
-        <permission name="android.permission.QUERY_ALL_PACKAGES"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.tv">
         <permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
         <permission name="android.permission.DVB_DEVICE"/>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 42e470b..5bfc321 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1611,7 +1611,7 @@
      * Return the paint's Align value for drawing text. This controls how the
      * text is positioned relative to its origin. LEFT align means that all of
      * the text will be drawn to the right of its origin (i.e. the origin
-     * specifieds the LEFT edge of the text) and so on.
+     * specifies the LEFT edge of the text) and so on.
      *
      * @return the paint's Align value for drawing text.
      */
@@ -1623,7 +1623,7 @@
      * Set the paint's text alignment. This controls how the
      * text is positioned relative to its origin. LEFT align means that all of
      * the text will be drawn to the right of its origin (i.e. the origin
-     * specifieds the LEFT edge of the text) and so on.
+     * specifies the LEFT edge of the text) and so on.
      *
      * @param align set the paint's Align value for drawing text.
      */
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 9b2effc..0fadae2 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -288,7 +288,7 @@
      * context at a time.
      *
      * @param texName The name of the OpenGL ES texture that will be created.  This texture name
-     * must be unusued in the OpenGL ES context that is current on the calling thread.
+     * must be unused in the OpenGL ES context that is current on the calling thread.
      */
     public void attachToGLContext(int texName) {
         int err = nativeAttachToGLContext(texName);
diff --git a/identity/java/android/security/identity/CredentialDataRequest.java b/identity/java/android/security/identity/CredentialDataRequest.java
new file mode 100644
index 0000000..2a47a02
--- /dev/null
+++ b/identity/java/android/security/identity/CredentialDataRequest.java
@@ -0,0 +1,232 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * An object representing a request for credential data.
+ */
+public class CredentialDataRequest {
+    CredentialDataRequest() {}
+
+    /**
+     * Gets the device-signed entries to request.
+     *
+     * @return the device-signed entries to request.
+     */
+    public @NonNull Map<String, Collection<String>> getDeviceSignedEntriesToRequest() {
+        return mDeviceSignedEntriesToRequest;
+    }
+
+    /**
+     * Gets the issuer-signed entries to request.
+     *
+     * @return the issuer-signed entries to request.
+     */
+    public @NonNull Map<String, Collection<String>> getIssuerSignedEntriesToRequest() {
+        return mIssuerSignedEntriesToRequest;
+    }
+
+    /**
+     * Gets whether to allow using an authentication key which use count has been exceeded.
+     *
+     * <p>By default this is set to true.
+     *
+     * @return whether to allow using an authentication key which use
+     *         count has been exceeded if no other key is available.
+     */
+    public boolean isAllowUsingExhaustedKeys() {
+        return mAllowUsingExhaustedKeys;
+    }
+
+    /**
+     * Gets whether to allow using an authentication key which is expired.
+     *
+     * <p>By default this is set to false.
+     *
+     * @return whether to allow using an authentication key which is
+     *         expired if no other key is available.
+     */
+    public boolean isAllowUsingExpiredKeys() {
+        return mAllowUsingExpiredKeys;
+    }
+
+    /**
+     * Gets whether to increment the use-count for the authentication key used.
+     *
+     * <p>By default this is set to true.
+     *
+     * @return whether to increment the use count of the authentication key used.
+     */
+    public boolean isIncrementUseCount() {
+        return mIncrementUseCount;
+    }
+
+    /**
+     * Gets the request message CBOR.
+     *
+     * <p>This data structure is described in the documentation for the
+     * {@link PresentationSession#getCredentialData(String, CredentialDataRequest)} method.
+     *
+     * @return the request message CBOR as described above.
+     */
+    public @Nullable byte[] getRequestMessage() {
+        return mRequestMessage;
+    }
+
+    /**
+     * Gets the reader signature.
+     *
+     * <p>This data structure is described in the documentation for the
+     * {@link PresentationSession#getCredentialData(String, CredentialDataRequest)} method.
+     *
+     * @return a {@code COSE_Sign1} structure as described above.
+     */
+    public @Nullable byte[] getReaderSignature() {
+        return mReaderSignature;
+    }
+
+    Map<String, Collection<String>> mDeviceSignedEntriesToRequest = new LinkedHashMap<>();
+    Map<String, Collection<String>> mIssuerSignedEntriesToRequest = new LinkedHashMap<>();
+    boolean mAllowUsingExhaustedKeys = true;
+    boolean mAllowUsingExpiredKeys = false;
+    boolean mIncrementUseCount = true;
+    byte[] mRequestMessage = null;
+    byte[] mReaderSignature = null;
+
+    /**
+     * A builder for {@link CredentialDataRequest}.
+     */
+    public static final class Builder {
+        private CredentialDataRequest mData;
+
+        /**
+         * Creates a new builder.
+         */
+        public Builder() {
+            mData = new CredentialDataRequest();
+        }
+
+        /**
+         * Sets the device-signed entries to request.
+         *
+         * @param entriesToRequest the device-signed entries to request.
+         */
+        public @NonNull Builder setDeviceSignedEntriesToRequest(
+                @NonNull Map<String, Collection<String>> entriesToRequest) {
+            mData.mDeviceSignedEntriesToRequest = entriesToRequest;
+            return this;
+        }
+
+        /**
+         * Sets the issuer-signed entries to request.
+         *
+         * @param entriesToRequest the issuer-signed entries to request.
+         * @return the builder.
+         */
+        public @NonNull Builder setIssuerSignedEntriesToRequest(
+                @NonNull Map<String, Collection<String>> entriesToRequest) {
+            mData.mIssuerSignedEntriesToRequest = entriesToRequest;
+            return this;
+        }
+
+        /**
+         * Sets whether to allow using an authentication key which use count has been exceeded.
+         *
+         * By default this is set to true.
+         *
+         * @param allowUsingExhaustedKeys whether to allow using an authentication key which use
+         *                                count has been exceeded if no other key is available.
+         * @return the builder.
+         */
+        public @NonNull Builder setAllowUsingExhaustedKeys(boolean allowUsingExhaustedKeys) {
+            mData.mAllowUsingExhaustedKeys = allowUsingExhaustedKeys;
+            return this;
+        }
+
+        /**
+         * Sets whether to allow using an authentication key which is expired.
+         *
+         * By default this is set to false.
+         *
+         * @param allowUsingExpiredKeys whether to allow using an authentication key which is
+         *                              expired if no other key is available.
+         * @return the builder.
+         */
+        public @NonNull Builder setAllowUsingExpiredKeys(boolean allowUsingExpiredKeys) {
+            mData.mAllowUsingExpiredKeys = allowUsingExpiredKeys;
+            return this;
+        }
+
+        /**
+         * Sets whether to increment the use-count for the authentication key used.
+         *
+         * By default this is set to true.
+         *
+         * @param incrementUseCount whether to increment the use count of the authentication
+         *                          key used.
+         * @return the builder.
+         */
+        public @NonNull Builder setIncrementUseCount(boolean incrementUseCount) {
+            mData.mIncrementUseCount = incrementUseCount;
+            return this;
+        }
+
+        /**
+         * Sets the request message CBOR.
+         *
+         * <p>This data structure is described in the documentation for the
+         * {@link PresentationSession#getCredentialData(String, CredentialDataRequest)} method.
+         *
+         * @param requestMessage the request message CBOR as described above.
+         * @return the builder.
+         */
+        public @NonNull Builder setRequestMessage(@NonNull byte[] requestMessage) {
+            mData.mRequestMessage = requestMessage;
+            return this;
+        }
+
+        /**
+         * Sets the reader signature.
+         *
+         * <p>This data structure is described in the documentation for the
+         * {@link PresentationSession#getCredentialData(String, CredentialDataRequest)} method.
+         *
+         * @param readerSignature a {@code COSE_Sign1} structure as described above.
+         * @return the builder.
+         */
+        public @NonNull Builder setReaderSignature(@NonNull byte[] readerSignature) {
+            mData.mReaderSignature = readerSignature;
+            return this;
+        }
+
+        /**
+         * Finishes building a {@link CredentialDataRequest}.
+         *
+         * @return the {@link CredentialDataRequest} object.
+         */
+        public @NonNull CredentialDataRequest build() {
+            return mData;
+        }
+    }
+}
diff --git a/identity/java/android/security/identity/CredentialDataResult.java b/identity/java/android/security/identity/CredentialDataResult.java
new file mode 100644
index 0000000..beb03af
--- /dev/null
+++ b/identity/java/android/security/identity/CredentialDataResult.java
@@ -0,0 +1,232 @@
+/*
+ * 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.security.identity;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.util.Collection;
+
+
+/**
+ * An object that contains the result of retrieving data from a credential. This is used to return
+ * data requested in a {@link PresentationSession}.
+ */
+public abstract class CredentialDataResult {
+    /**
+     * @hide
+     */
+    protected CredentialDataResult() {}
+
+    /**
+     * Returns a CBOR structure containing the retrieved device-signed data.
+     *
+     * <p>This structure - along with the session transcript - may be cryptographically
+     * authenticated to prove to the reader that the data is from a trusted credential and
+     * {@link #getDeviceMac()} can be used to get a MAC.
+     *
+     * <p>The CBOR structure which is cryptographically authenticated is the
+     * {@code DeviceAuthenticationBytes} structure according to the following
+     * <a href="https://tools.ietf.org/html/rfc8610">CDDL</a> schema:
+     *
+     * <pre>
+     *   DeviceAuthentication = [
+     *     "DeviceAuthentication",
+     *     SessionTranscript,
+     *     DocType,
+     *     DeviceNameSpacesBytes
+     *   ]
+     *
+     *   DocType = tstr
+     *   SessionTranscript = any
+     *   DeviceNameSpacesBytes = #6.24(bstr .cbor DeviceNameSpaces)
+     *   DeviceAuthenticationBytes = #6.24(bstr .cbor DeviceAuthentication)
+     * </pre>
+     *
+     * <p>where
+     *
+     * <pre>
+     *   DeviceNameSpaces = {
+     *     * NameSpace => DeviceSignedItems
+     *   }
+     *
+     *   DeviceSignedItems = {
+     *     + DataItemName => DataItemValue
+     *   }
+     *
+     *   NameSpace = tstr
+     *   DataItemName = tstr
+     *   DataItemValue = any
+     * </pre>
+     *
+     * <p>The returned data is the binary encoding of the {@code DeviceNameSpaces} structure
+     * as defined above.
+     *
+     * @return The bytes of the {@code DeviceNameSpaces} CBOR structure.
+     */
+    public abstract @NonNull byte[] getDeviceNameSpaces();
+
+    /**
+     * Returns a message authentication code over the {@code DeviceAuthenticationBytes} CBOR
+     * specified in {@link #getDeviceNameSpaces()}, to prove to the reader that the data
+     * is from a trusted credential.
+     *
+     * <p>The MAC proves to the reader that the data is from a trusted credential. This code is
+     * produced by using the key agreement and key derivation function from the ciphersuite
+     * with the authentication private key and the reader ephemeral public key to compute a
+     * shared message authentication code (MAC) key, then using the MAC function from the
+     * ciphersuite to compute a MAC of the authenticated data. See section 9.2.3.5 of
+     * ISO/IEC 18013-5 for details of this operation.
+     *
+     * <p>If the session transcript or reader ephemeral key wasn't set on the {@link
+     * PresentationSession} used to obtain this data no message authencation code will be produced
+     * and this method will return {@code null}.
+     *
+     * @return A COSE_Mac0 structure with the message authentication code as described above
+     *         or {@code null} if the conditions specified above are not met.
+     */
+    public abstract @Nullable byte[] getDeviceMac();
+
+    /**
+     * Returns the static authentication data associated with the dynamic authentication
+     * key used to MAC the data returned by {@link #getDeviceNameSpaces()}.
+     *
+     * @return The static authentication data associated with dynamic authentication key used to
+     * MAC the data.
+     */
+    public abstract @NonNull byte[] getStaticAuthenticationData();
+
+    /**
+     * Gets the device-signed entries that was returned.
+     *
+     * @return an object to examine the entries returned.
+     */
+    public abstract @NonNull Entries getDeviceSignedEntries();
+
+    /**
+     * Gets the issuer-signed entries that was returned.
+     *
+     * @return an object to examine the entries returned.
+     */
+    public abstract @NonNull Entries getIssuerSignedEntries();
+
+    /**
+     * A class for representing data elements returned.
+     */
+    public interface Entries {
+        /** Value was successfully retrieved. */
+        int STATUS_OK = 0;
+
+        /** The entry does not exist. */
+        int STATUS_NO_SUCH_ENTRY = 1;
+
+        /** The entry was not requested. */
+        int STATUS_NOT_REQUESTED = 2;
+
+        /** The entry wasn't in the request message. */
+        int STATUS_NOT_IN_REQUEST_MESSAGE = 3;
+
+        /** The entry was not retrieved because user authentication failed. */
+        int STATUS_USER_AUTHENTICATION_FAILED = 4;
+
+        /** The entry was not retrieved because reader authentication failed. */
+        int STATUS_READER_AUTHENTICATION_FAILED = 5;
+
+        /**
+         * The entry was not retrieved because it was configured without any access
+         * control profile.
+         */
+        int STATUS_NO_ACCESS_CONTROL_PROFILES = 6;
+
+        /**
+         * Gets the names of namespaces with retrieved entries.
+         *
+         * @return collection of name of namespaces containing retrieved entries. May be empty if no
+         *     data was retrieved.
+         */
+        @NonNull Collection<String> getNamespaces();
+
+        /**
+         * Get the names of all requested entries in a name space.
+         *
+         * <p>This includes the name of entries that wasn't successfully retrieved.
+         *
+         * @param namespaceName the namespace name to get entries for.
+         * @return A collection of names for the given namespace or the empty collection if no
+         *   entries was returned for the given name space.
+         */
+        @NonNull Collection<String> getEntryNames(@NonNull String namespaceName);
+
+        /**
+         * Get the names of all entries that was successfully retrieved from a name space.
+         *
+         * <p>This only return entries for which {@link #getStatus(String, String)} will return
+         * {@link #STATUS_OK}.
+         *
+         * @param namespaceName the namespace name to get entries for.
+         * @return The entries in the given namespace that were successfully rerieved or the
+         *   empty collection if no entries was returned for the given name space.
+         */
+        @NonNull Collection<String> getRetrievedEntryNames(@NonNull String namespaceName);
+
+        /**
+         * Gets the status of an entry.
+         *
+         * <p>This returns {@link #STATUS_OK} if the value was retrieved, {@link
+         * #STATUS_NO_SUCH_ENTRY} if the given entry wasn't retrieved, {@link
+         * #STATUS_NOT_REQUESTED} if it wasn't requested, {@link #STATUS_NOT_IN_REQUEST_MESSAGE} if
+         * the request message was set but the entry wasn't present in the request message, {@link
+         * #STATUS_USER_AUTHENTICATION_FAILED} if the value wasn't retrieved because the necessary
+         * user authentication wasn't performed, {@link #STATUS_READER_AUTHENTICATION_FAILED} if
+         * the supplied reader certificate chain didn't match the set of certificates the entry was
+         * provisioned with, or {@link #STATUS_NO_ACCESS_CONTROL_PROFILES} if the entry was
+         * configured without any access control profiles.
+         *
+         * @param namespaceName the namespace name of the entry.
+         * @param name the name of the entry to get the value for.
+         * @return the status indicating whether the value was retrieved and if not, why.
+         */
+        @Status int getStatus(@NonNull String namespaceName, @NonNull String name);
+
+        /**
+         * Gets the raw CBOR data for the value of an entry.
+         *
+         * <p>This should only be called on an entry for which the {@link #getStatus(String,
+         * String)} method returns {@link #STATUS_OK}.
+         *
+         * @param namespaceName the namespace name of the entry.
+         * @param name the name of the entry to get the value for.
+         * @return the raw CBOR data or {@code null} if no entry with the given name exists.
+         */
+        @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name);
+
+        /**
+         * The type of the entry status.
+         * @hide
+         */
+        @Retention(SOURCE)
+        @IntDef({STATUS_OK, STATUS_NO_SUCH_ENTRY, STATUS_NOT_REQUESTED,
+                    STATUS_NOT_IN_REQUEST_MESSAGE, STATUS_USER_AUTHENTICATION_FAILED,
+                    STATUS_READER_AUTHENTICATION_FAILED, STATUS_NO_ACCESS_CONTROL_PROFILES})
+                    @interface Status {}
+    }
+
+}
diff --git a/identity/java/android/security/identity/CredstoreCredentialDataResult.java b/identity/java/android/security/identity/CredstoreCredentialDataResult.java
new file mode 100644
index 0000000..7afe3d4
--- /dev/null
+++ b/identity/java/android/security/identity/CredstoreCredentialDataResult.java
@@ -0,0 +1,106 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+class CredstoreCredentialDataResult extends CredentialDataResult {
+
+    ResultData mDeviceSignedResult;
+    ResultData mIssuerSignedResult;
+    CredstoreEntries mDeviceSignedEntries;
+    CredstoreEntries mIssuerSignedEntries;
+
+    CredstoreCredentialDataResult(ResultData deviceSignedResult, ResultData issuerSignedResult) {
+        mDeviceSignedResult = deviceSignedResult;
+        mIssuerSignedResult = issuerSignedResult;
+        mDeviceSignedEntries = new CredstoreEntries(deviceSignedResult);
+        mIssuerSignedEntries = new CredstoreEntries(issuerSignedResult);
+    }
+
+    @Override
+    public @NonNull byte[] getDeviceNameSpaces() {
+        return mDeviceSignedResult.getAuthenticatedData();
+    }
+
+    @Override
+    public @Nullable byte[] getDeviceMac() {
+        return mDeviceSignedResult.getMessageAuthenticationCode();
+    }
+
+    @Override
+    public @NonNull byte[] getStaticAuthenticationData() {
+        return mDeviceSignedResult.getStaticAuthenticationData();
+    }
+
+    @Override
+    public @NonNull CredentialDataResult.Entries getDeviceSignedEntries() {
+        return mDeviceSignedEntries;
+    }
+
+    @Override
+    public @NonNull CredentialDataResult.Entries getIssuerSignedEntries() {
+        return mIssuerSignedEntries;
+    }
+
+    static class CredstoreEntries implements CredentialDataResult.Entries {
+        ResultData mResultData;
+
+        CredstoreEntries(ResultData resultData) {
+            mResultData = resultData;
+        }
+
+        @Override
+        public @NonNull Collection<String> getNamespaces() {
+            return mResultData.getNamespaces();
+        }
+
+        @Override
+        public @NonNull Collection<String> getEntryNames(@NonNull String namespaceName) {
+            Collection<String> ret = mResultData.getEntryNames(namespaceName);
+            if (ret == null) {
+                ret = new LinkedList<String>();
+            }
+            return ret;
+        }
+
+        @Override
+        public @NonNull Collection<String> getRetrievedEntryNames(@NonNull String namespaceName) {
+            Collection<String> ret = mResultData.getRetrievedEntryNames(namespaceName);
+            if (ret == null) {
+                ret = new LinkedList<String>();
+            }
+            return ret;
+        }
+
+        @Override
+        @Status
+        public int getStatus(@NonNull String namespaceName, @NonNull String name) {
+            return mResultData.getStatus(namespaceName, name);
+        }
+
+        @Override
+        public @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name) {
+            return mResultData.getEntry(namespaceName, name);
+        }
+    }
+
+}
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredential.java b/identity/java/android/security/identity/CredstoreIdentityCredential.java
index 6398cee..8e01105 100644
--- a/identity/java/android/security/identity/CredstoreIdentityCredential.java
+++ b/identity/java/android/security/identity/CredstoreIdentityCredential.java
@@ -58,14 +58,17 @@
     private @IdentityCredentialStore.Ciphersuite int mCipherSuite;
     private Context mContext;
     private ICredential mBinder;
+    private CredstorePresentationSession mSession;
 
     CredstoreIdentityCredential(Context context, String credentialName,
             @IdentityCredentialStore.Ciphersuite int cipherSuite,
-            ICredential binder) {
+            ICredential binder,
+            @Nullable CredstorePresentationSession session) {
         mContext = context;
         mCredentialName = credentialName;
         mCipherSuite = cipherSuite;
         mBinder = binder;
+        mSession = session;
     }
 
     private KeyPair mEphemeralKeyPair = null;
@@ -239,6 +242,7 @@
 
     private boolean mAllowUsingExhaustedKeys = true;
     private boolean mAllowUsingExpiredKeys = false;
+    private boolean mIncrementKeyUsageCount = true;
 
     @Override
     public void setAllowUsingExhaustedKeys(boolean allowUsingExhaustedKeys) {
@@ -250,6 +254,11 @@
         mAllowUsingExpiredKeys = allowUsingExpiredKeys;
     }
 
+    @Override
+    public void setIncrementKeyUsageCount(boolean incrementKeyUsageCount) {
+        mIncrementKeyUsageCount = incrementKeyUsageCount;
+    }
+
     private boolean mOperationHandleSet = false;
     private long mOperationHandle = 0;
 
@@ -264,7 +273,8 @@
         if (!mOperationHandleSet) {
             try {
                 mOperationHandle = mBinder.selectAuthKey(mAllowUsingExhaustedKeys,
-                        mAllowUsingExpiredKeys);
+                                                         mAllowUsingExpiredKeys,
+                                                         mIncrementKeyUsageCount);
                 mOperationHandleSet = true;
             } catch (android.os.RemoteException e) {
                 throw new RuntimeException("Unexpected RemoteException ", e);
@@ -315,7 +325,8 @@
                 sessionTranscript != null ? sessionTranscript : new byte[0],
                 readerSignature != null ? readerSignature : new byte[0],
                 mAllowUsingExhaustedKeys,
-                mAllowUsingExpiredKeys);
+                mAllowUsingExpiredKeys,
+                mIncrementKeyUsageCount);
         } catch (android.os.RemoteException e) {
             throw new RuntimeException("Unexpected RemoteException ", e);
         } catch (android.os.ServiceSpecificException e) {
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
index d8d4742..fb0880c 100644
--- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
+++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
@@ -126,7 +126,8 @@
             ICredential credstoreCredential;
             credstoreCredential = mStore.getCredentialByName(credentialName, cipherSuite);
             return new CredstoreIdentityCredential(mContext, credentialName, cipherSuite,
-                    credstoreCredential);
+                    credstoreCredential,
+                    null);
         } catch (android.os.RemoteException e) {
             throw new RuntimeException("Unexpected RemoteException ", e);
         } catch (android.os.ServiceSpecificException e) {
@@ -162,4 +163,23 @@
                     + e.errorCode, e);
         }
     }
+
+    @Override
+    public @NonNull PresentationSession createPresentationSession(@Ciphersuite int cipherSuite)
+            throws CipherSuiteNotSupportedException {
+        try {
+            ISession credstoreSession = mStore.createPresentationSession(cipherSuite);
+            return new CredstorePresentationSession(mContext, cipherSuite, this, credstoreSession);
+        } catch (android.os.RemoteException e) {
+            throw new RuntimeException("Unexpected RemoteException ", e);
+        } catch (android.os.ServiceSpecificException e) {
+            if (e.errorCode == ICredentialStore.ERROR_CIPHER_SUITE_NOT_SUPPORTED) {
+                throw new CipherSuiteNotSupportedException(e.getMessage(), e);
+            } else {
+                throw new RuntimeException("Unexpected ServiceSpecificException with code "
+                        + e.errorCode, e);
+            }
+        }
+    }
+
 }
diff --git a/identity/java/android/security/identity/CredstorePresentationSession.java b/identity/java/android/security/identity/CredstorePresentationSession.java
new file mode 100644
index 0000000..e3c6689
--- /dev/null
+++ b/identity/java/android/security/identity/CredstorePresentationSession.java
@@ -0,0 +1,214 @@
+/*
+ * 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.security.identity;
+
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+class CredstorePresentationSession extends PresentationSession {
+    private static final String TAG = "CredstorePresentationSession";
+
+    private @IdentityCredentialStore.Ciphersuite int mCipherSuite;
+    private Context mContext;
+    private CredstoreIdentityCredentialStore mStore;
+    private ISession mBinder;
+    private Map<String, CredstoreIdentityCredential> mCredentialCache = new LinkedHashMap<>();
+    private KeyPair mEphemeralKeyPair = null;
+    private byte[] mSessionTranscript = null;
+    private boolean mOperationHandleSet = false;
+    private long mOperationHandle = 0;
+
+    CredstorePresentationSession(Context context,
+            @IdentityCredentialStore.Ciphersuite int cipherSuite,
+            CredstoreIdentityCredentialStore store,
+            ISession binder) {
+        mContext = context;
+        mCipherSuite = cipherSuite;
+        mStore = store;
+        mBinder = binder;
+    }
+
+    private void ensureEphemeralKeyPair() {
+        if (mEphemeralKeyPair != null) {
+            return;
+        }
+        try {
+            // This PKCS#12 blob is generated in credstore, using BoringSSL.
+            //
+            // The main reason for this convoluted approach and not just sending the decomposed
+            // key-pair is that this would require directly using (device-side) BouncyCastle which
+            // is tricky due to various API hiding efforts. So instead we have credstore generate
+            // this PKCS#12 blob. The blob is encrypted with no password (sadly, also, BoringSSL
+            // doesn't support not using encryption when building a PKCS#12 blob).
+            //
+            byte[] pkcs12 = mBinder.getEphemeralKeyPair();
+            String alias = "ephemeralKey";
+            char[] password = {};
+
+            KeyStore ks = KeyStore.getInstance("PKCS12");
+            ByteArrayInputStream bais = new ByteArrayInputStream(pkcs12);
+            ks.load(bais, password);
+            PrivateKey privKey = (PrivateKey) ks.getKey(alias, password);
+
+            Certificate cert = ks.getCertificate(alias);
+            PublicKey pubKey = cert.getPublicKey();
+
+            mEphemeralKeyPair = new KeyPair(pubKey, privKey);
+        } catch (android.os.ServiceSpecificException e) {
+            throw new RuntimeException("Unexpected ServiceSpecificException with code "
+                    + e.errorCode, e);
+        } catch (android.os.RemoteException
+                | KeyStoreException
+                | CertificateException
+                | UnrecoverableKeyException
+                | NoSuchAlgorithmException
+                | IOException e) {
+            throw new RuntimeException("Unexpected exception ", e);
+        }
+    }
+
+    @Override
+    public @NonNull KeyPair getEphemeralKeyPair() {
+        ensureEphemeralKeyPair();
+        return mEphemeralKeyPair;
+    }
+
+    @Override
+    public void setReaderEphemeralPublicKey(@NonNull PublicKey readerEphemeralPublicKey)
+            throws InvalidKeyException {
+        try {
+            byte[] uncompressedForm =
+                    Util.publicKeyEncodeUncompressedForm(readerEphemeralPublicKey);
+            mBinder.setReaderEphemeralPublicKey(uncompressedForm);
+        } catch (android.os.RemoteException e) {
+            throw new RuntimeException("Unexpected RemoteException ", e);
+        } catch (android.os.ServiceSpecificException e) {
+            throw new RuntimeException("Unexpected ServiceSpecificException with code "
+                    + e.errorCode, e);
+        }
+    }
+
+    @Override
+    public void setSessionTranscript(@NonNull byte[] sessionTranscript) {
+        try {
+            mBinder.setSessionTranscript(sessionTranscript);
+            mSessionTranscript = sessionTranscript;
+        } catch (android.os.RemoteException e) {
+            throw new RuntimeException("Unexpected RemoteException ", e);
+        } catch (android.os.ServiceSpecificException e) {
+            throw new RuntimeException("Unexpected ServiceSpecificException with code "
+                    + e.errorCode, e);
+        }
+    }
+
+    @Override
+    public @Nullable CredentialDataResult getCredentialData(@NonNull String credentialName,
+                                                            @NonNull CredentialDataRequest request)
+            throws NoAuthenticationKeyAvailableException, InvalidReaderSignatureException,
+            InvalidRequestMessageException, EphemeralPublicKeyNotFoundException {
+        try {
+            // Cache the IdentityCredential to satisfy the property that AuthKey usage counts are
+            // incremented on only the _first_ getCredentialData() call.
+            //
+            CredstoreIdentityCredential credential = mCredentialCache.get(credentialName);
+            if (credential == null) {
+                ICredential credstoreCredential =
+                    mBinder.getCredentialForPresentation(credentialName);
+                credential = new CredstoreIdentityCredential(mContext, credentialName,
+                                                             mCipherSuite, credstoreCredential,
+                                                             this);
+                mCredentialCache.put(credentialName, credential);
+
+                credential.setAllowUsingExhaustedKeys(request.isAllowUsingExhaustedKeys());
+                credential.setAllowUsingExpiredKeys(request.isAllowUsingExpiredKeys());
+                credential.setIncrementKeyUsageCount(request.isIncrementUseCount());
+            }
+
+            ResultData deviceSignedResult = credential.getEntries(
+                    request.getRequestMessage(),
+                    request.getDeviceSignedEntriesToRequest(),
+                    mSessionTranscript,
+                    request.getReaderSignature());
+
+            // By design this second getEntries() call consumes the same auth-key.
+
+            ResultData issuerSignedResult = credential.getEntries(
+                    request.getRequestMessage(),
+                    request.getIssuerSignedEntriesToRequest(),
+                    mSessionTranscript,
+                    request.getReaderSignature());
+
+            return new CredstoreCredentialDataResult(deviceSignedResult, issuerSignedResult);
+
+        } catch (SessionTranscriptMismatchException e) {
+            throw new RuntimeException("Unexpected ", e);
+        } catch (android.os.RemoteException e) {
+            throw new RuntimeException("Unexpected RemoteException ", e);
+        } catch (android.os.ServiceSpecificException e) {
+            if (e.errorCode == ICredentialStore.ERROR_NO_SUCH_CREDENTIAL) {
+                return null;
+            } else {
+                throw new RuntimeException("Unexpected ServiceSpecificException with code "
+                        + e.errorCode, e);
+            }
+        }
+    }
+
+    /**
+     * Called by android.hardware.biometrics.CryptoObject#getOpId() to get an
+     * operation handle.
+     *
+     * @hide
+     */
+    @Override
+    public long getCredstoreOperationHandle() {
+        if (!mOperationHandleSet) {
+            try {
+                mOperationHandle = mBinder.getAuthChallenge();
+                mOperationHandleSet = true;
+            } catch (android.os.RemoteException e) {
+                throw new RuntimeException("Unexpected RemoteException ", e);
+            } catch (android.os.ServiceSpecificException e) {
+                if (e.errorCode == ICredentialStore.ERROR_NO_AUTHENTICATION_KEY_AVAILABLE) {
+                    // The NoAuthenticationKeyAvailableException will be thrown when
+                    // the caller proceeds to call getEntries().
+                }
+                throw new RuntimeException("Unexpected ServiceSpecificException with code "
+                        + e.errorCode, e);
+            }
+        }
+        return mOperationHandle;
+    }
+
+}
diff --git a/identity/java/android/security/identity/IdentityCredential.java b/identity/java/android/security/identity/IdentityCredential.java
index 1e68585..f440b69 100644
--- a/identity/java/android/security/identity/IdentityCredential.java
+++ b/identity/java/android/security/identity/IdentityCredential.java
@@ -48,7 +48,9 @@
      * encryption".
      *
      * @return ephemeral key pair to use to establish a secure channel with a reader.
+     * @deprecated Use {@link PresentationSession} instead.
      */
+    @Deprecated
     public @NonNull abstract KeyPair createEphemeralKeyPair();
 
     /**
@@ -58,7 +60,9 @@
      * @param readerEphemeralPublicKey The ephemeral public key provided by the reader to
      *                                 establish a secure session.
      * @throws InvalidKeyException if the given key is invalid.
+     * @deprecated Use {@link PresentationSession} instead.
      */
+    @Deprecated
     public abstract void setReaderEphemeralPublicKey(@NonNull PublicKey readerEphemeralPublicKey)
             throws InvalidKeyException;
 
@@ -72,7 +76,10 @@
      *
      * @param messagePlaintext unencrypted message to encrypt.
      * @return encrypted message.
+     * @deprecated Applications should use {@link PresentationSession} and
+     *             implement encryption/decryption themselves.
      */
+    @Deprecated
     public @NonNull abstract byte[] encryptMessageToReader(@NonNull byte[] messagePlaintext);
 
     /**
@@ -86,7 +93,10 @@
      * @param messageCiphertext encrypted message to decrypt.
      * @return decrypted message.
      * @throws MessageDecryptionException if the ciphertext couldn't be decrypted.
+     * @deprecated Applications should use {@link PresentationSession} and
+     *             implement encryption/decryption themselves.
      */
+    @Deprecated
     public @NonNull abstract byte[] decryptMessageFromReader(@NonNull byte[] messageCiphertext)
             throws MessageDecryptionException;
 
@@ -111,7 +121,9 @@
      *
      * @param allowUsingExhaustedKeys whether to allow using an authentication key which use count
      *                                has been exceeded if no other key is available.
+     * @deprecated Use {@link PresentationSession} instead.
      */
+    @Deprecated
     public abstract void setAllowUsingExhaustedKeys(boolean allowUsingExhaustedKeys);
 
     /**
@@ -128,12 +140,36 @@
      *
      * @param allowUsingExpiredKeys whether to allow using an authentication key which use count
      *                              has been exceeded if no other key is available.
+     * @deprecated Use {@link PresentationSession} instead.
      */
+    @Deprecated
     public void setAllowUsingExpiredKeys(boolean allowUsingExpiredKeys) {
         throw new UnsupportedOperationException();
     }
 
     /**
+     * @hide
+     *
+     * Sets whether the usage count of an authentication key should be increased. This must be
+     * called prior to calling
+     * {@link #getEntries(byte[], Map, byte[], byte[])} or using a
+     * {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which references this object.
+     *
+     * <p>By default this is set to true.
+     *
+     * <p>This is only implemented in feature version 202201 or later. If not implemented, the call
+     * fails with {@link UnsupportedOperationException}. See
+     * {@link android.content.pm.PackageManager#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} for known
+     * feature versions.
+     *
+     * @param incrementKeyUsageCount whether the usage count of the key should be increased.
+     * @deprecated Use {@link PresentationSession} instead.
+     */
+    public void setIncrementKeyUsageCount(boolean incrementKeyUsageCount) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Called by android.hardware.biometrics.CryptoObject#getOpId() to get an
      * operation handle.
      *
@@ -149,15 +185,19 @@
      * by using the {@link ResultData#getStatus(String, String)} method on each of the requested
      * entries.
      *
-     * <p>It is the responsibility of the calling application to know if authentication is needed
-     * and use e.g. {@link android.hardware.biometrics.BiometricPrompt} to make the user
-     * authenticate using a {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which
-     * references this object. If needed, this must be done before calling
-     * {@link #getEntries(byte[], Map, byte[], byte[])}.
-     *
      * <p>It is permissible to call this method multiple times using the same instance but if this
      * is done, the {@code sessionTranscript} parameter must be identical for each call. If this is
      * not the case, the {@link SessionTranscriptMismatchException} exception is thrown.
+     * Additionally, if this is done the same auth-key will be used.
+     *
+     * <p>The application should not make any assumptions on whether user authentication is needed.
+     * Instead, the application should request the data elements values first and then examine
+     * the returned {@link ResultData}. If {@link ResultData#STATUS_USER_AUTHENTICATION_FAILED}
+     * is returned the application should get a
+     * {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which references this
+     * object and use it with a {@link android.hardware.biometrics.BiometricPrompt}. Upon successful
+     * authentication the application may call {@link #getEntries(byte[], Map, byte[], byte[])}
+     * again.
      *
      * <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, but
@@ -269,7 +309,9 @@
      * @throws InvalidRequestMessageException         if the requestMessage is malformed.
      * @throws EphemeralPublicKeyNotFoundException    if the ephemeral public key was not found in
      *                                                the session transcript.
+     * @deprecated Use {@link PresentationSession} instead.
      */
+    @Deprecated
     public abstract @NonNull ResultData getEntries(
             @Nullable byte[] requestMessage,
             @NonNull Map<String, Collection<String>> entriesToRequest,
@@ -412,7 +454,8 @@
      * @param challenge is a non-empty byte array whose contents should be unique, fresh and
      *                  provided by the issuing authority. The value provided is embedded in the
      *                  generated CBOR and enables the issuing authority to verify that the
-     *                  returned proof is fresh.
+     *                  returned proof is fresh. Implementations are required to support
+     *                  challenges at least 32 bytes of length.
      * @return the COSE_Sign1 data structure above
      */
     public @NonNull byte[] proveOwnership(@NonNull byte[] challenge)  {
@@ -443,7 +486,8 @@
      * @param challenge is a non-empty byte array whose contents should be unique, fresh and
      *                  provided by the issuing authority. The value provided is embedded in the
      *                  generated CBOR and enables the issuing authority to verify that the
-     *                  returned proof is fresh.
+     *                  returned proof is fresh. Implementations are required to support
+     *                  challenges at least 32 bytes of length.
      * @return the COSE_Sign1 data structure above
      */
     public @NonNull byte[] delete(@NonNull byte[] challenge)  {
diff --git a/identity/java/android/security/identity/IdentityCredentialStore.java b/identity/java/android/security/identity/IdentityCredentialStore.java
index 6ccd0e8..dbb8aaa 100644
--- a/identity/java/android/security/identity/IdentityCredentialStore.java
+++ b/identity/java/android/security/identity/IdentityCredentialStore.java
@@ -209,6 +209,25 @@
     @Deprecated
     public abstract @Nullable byte[] deleteCredentialByName(@NonNull String credentialName);
 
+    /**
+     * Creates a new presentation session.
+     *
+     * <p>This method gets an object to be used for interaction with a remote verifier for
+     * presentation of one or more credentials.
+     *
+     * <p>This is only implemented in feature version 202201 or later. If not implemented, the call
+     * fails with {@link UnsupportedOperationException}. See
+     * {@link android.content.pm.PackageManager#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} for known
+     * feature versions.
+     *
+     * @param cipherSuite    the cipher suite to use for communicating with the verifier.
+     * @return The presentation session.
+     */
+    public @NonNull PresentationSession createPresentationSession(@Ciphersuite int cipherSuite)
+            throws CipherSuiteNotSupportedException {
+        throw new UnsupportedOperationException();
+    }
+
     /** @hide */
     @IntDef(value = {CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256})
     @Retention(RetentionPolicy.SOURCE)
diff --git a/identity/java/android/security/identity/PresentationSession.java b/identity/java/android/security/identity/PresentationSession.java
new file mode 100644
index 0000000..afaafce
--- /dev/null
+++ b/identity/java/android/security/identity/PresentationSession.java
@@ -0,0 +1,173 @@
+/*
+ * 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.security.identity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.PublicKey;
+
+/**
+ * Class for presenting multiple documents to a remote verifier.
+ *
+ * Use {@link IdentityCredentialStore#createPresentationSession(int)} to create a {@link
+ * PresentationSession} instance.
+ */
+public abstract class PresentationSession {
+    /**
+     * @hide
+     */
+    protected PresentationSession() {}
+
+    /**
+     * Gets the ephemeral key pair to use to establish a secure channel with the verifier.
+     *
+     * <p>Applications should use this key-pair for the communications channel with the verifier
+     * using a protocol / cipher-suite appropriate for the application. One example of such a
+     * protocol is the one used for Mobile Driving Licenses, see ISO 18013-5.
+     *
+     * <p>The ephemeral key pair is tied to the {@link PresentationSession} instance so subsequent
+     * calls to this method will return the same key-pair.
+     *
+     * @return ephemeral key pair to use to establish a secure channel with a reader.
+     */
+    public @NonNull abstract KeyPair getEphemeralKeyPair();
+
+    /**
+     * Set the ephemeral public key provided by the verifier.
+     *
+     * <p>If called, this must be called before any calls to
+     * {@link #getCredentialData(String, CredentialDataRequest)}.
+     *
+     * <p>This method can only be called once per {@link PresentationSession} instance.
+     *
+     * @param readerEphemeralPublicKey The ephemeral public key provided by the reader to
+     *                                 establish a secure session.
+     * @throws InvalidKeyException if the given key is invalid.
+     */
+    public abstract void setReaderEphemeralPublicKey(@NonNull PublicKey readerEphemeralPublicKey)
+            throws InvalidKeyException;
+
+    /**
+     * Set the session transcript.
+     *
+     * <p>If called, this must be called before any calls to
+     * {@link #getCredentialData(String, CredentialDataRequest)}.
+     *
+     * <p>The X and Y coordinates of the public part of the key-pair returned by {@link
+     * #getEphemeralKeyPair()} must appear somewhere in the bytes of the passed in CBOR.  Each of
+     * these coordinates must appear encoded with the most significant bits first and use the exact
+     * amount of bits indicated by the key size of the ephemeral keys. For example, if the
+     * ephemeral key is using the P-256 curve then the 32 bytes for the X coordinate encoded with
+     * the most significant bits first must appear somewhere and ditto for the 32 bytes for the Y
+     * coordinate.
+     *
+     * <p>This method can only be called once per {@link PresentationSession} instance.
+     *
+     * @param sessionTranscript the session transcript.
+     */
+    public abstract void setSessionTranscript(@NonNull byte[] sessionTranscript);
+
+    /**
+     * Retrieves data from a named credential in the current presentation session.
+     *
+     * <p>If an access control check fails for one of the requested entries or if the entry
+     * doesn't exist, the entry is simply not returned. The application can detect this
+     * by using the {@link CredentialDataResult.Entries#getStatus(String, String)} method on
+     * each of the requested entries.
+     *
+     * <p>The application should not make any assumptions on whether user authentication is needed.
+     * Instead, the application should request the data elements values first and then examine
+     * the returned {@link CredentialDataResult.Entries}. If
+     * {@link CredentialDataResult.Entries#STATUS_USER_AUTHENTICATION_FAILED} is returned the
+     * application should get a
+     * {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which references this
+     * object and use it with a {@link android.hardware.biometrics.BiometricPrompt}. Upon successful
+     * authentication the application may call
+     * {@link #getCredentialData(String, CredentialDataRequest)} again.
+     *
+     * <p>It is permissible to call this method multiple times using the same credential name.
+     * If this is done the same auth-key will be used.
+     *
+     * <p>If the reader signature is set in the request parameter (via the
+     * {@link CredentialDataRequest.Builder#setReaderSignature(byte[])} method) it must contain
+     * the bytes of a {@code COSE_Sign1} structure as defined in RFC 8152. For the payload
+     * {@code nil} shall be used and the detached payload is the {@code ReaderAuthenticationBytes}
+     * CBOR described below.
+     * <pre>
+     *     ReaderAuthentication = [
+     *       "ReaderAuthentication",
+     *       SessionTranscript,
+     *       ItemsRequestBytes
+     *     ]
+     *
+     *     ItemsRequestBytes = #6.24(bstr .cbor ItemsRequest)
+     *
+     *     ReaderAuthenticationBytes = #6.24(bstr .cbor ReaderAuthentication)
+     * </pre>
+     *
+     * <p>where {@code ItemsRequestBytes} are the bytes of the request message set in
+     * the request parameter (via the
+     * {@link CredentialDataRequest.Builder#setRequestMessage(byte[])} method).
+     *
+     * <p>The public key corresponding to the key used to make the signature, can be found in the
+     * {@code x5chain} unprotected header element of the {@code COSE_Sign1} structure (as as
+     * described in
+     * <a href="https://tools.ietf.org/html/draft-ietf-cose-x509-08">draft-ietf-cose-x509-08</a>).
+     * There will be at least one certificate in said element and there may be more (and if so,
+     * each certificate must be signed by its successor).
+     *
+     * <p>Data elements protected by reader authentication are returned if, and only if,
+     * {@code requestMessage} is signed by the top-most certificate in the reader's certificate
+     * chain, and the data element is configured with an {@link AccessControlProfile} configured
+     * with an X.509 certificate for a key which appear in the certificate chain.
+     *
+     * <p>Note that the request message CBOR is used only for enforcing reader authentication, it's
+     * not used for determining which entries this API will return. The application is expected to
+     * have parsed the request message and filtered it according to user preference and/or consent.
+     *
+     * @param credentialName the name of the credential to retrieve.
+     * @param request the data to retrieve from the credential
+     * @return If the credential wasn't found, returns null. Otherwise a
+     *         {@link CredentialDataResult} object containing entry data organized by namespace and
+     *         a cryptographically authenticated representation of the same data, bound to the
+     *         current session.
+     * @throws NoAuthenticationKeyAvailableException  if authentication keys were never
+     *                                                provisioned for the credential or if they
+     *                                                are expired or exhausted their use-count.
+     * @throws InvalidRequestMessageException         if the requestMessage is malformed.
+     * @throws InvalidReaderSignatureException        if the reader signature is invalid, or it
+     *                                                doesn't contain a certificate chain, or if
+     *                                                the signature failed to validate.
+     * @throws EphemeralPublicKeyNotFoundException    if the ephemeral public key was not found in
+     *                                                the session transcript.
+     */
+    public abstract @Nullable CredentialDataResult getCredentialData(
+            @NonNull String credentialName, @NonNull CredentialDataRequest request)
+            throws NoAuthenticationKeyAvailableException, InvalidReaderSignatureException,
+            InvalidRequestMessageException, EphemeralPublicKeyNotFoundException;
+
+    /**
+     * Called by android.hardware.biometrics.CryptoObject#getOpId() to get an
+     * operation handle.
+     *
+     * @hide
+     */
+    public abstract long getCredstoreOperationHandle();
+}
diff --git a/identity/java/android/security/identity/ResultData.java b/identity/java/android/security/identity/ResultData.java
index 71860d2..d46f985 100644
--- a/identity/java/android/security/identity/ResultData.java
+++ b/identity/java/android/security/identity/ResultData.java
@@ -28,7 +28,10 @@
 /**
  * An object that contains the result of retrieving data from a credential. This is used to return
  * data requested from a {@link IdentityCredential}.
+ *
+ * @deprecated Use {@link PresentationSession} instead.
  */
+@Deprecated
 public abstract class ResultData {
 
     /** Value was successfully retrieved. */
diff --git a/identity/java/android/security/identity/WritableIdentityCredential.java b/identity/java/android/security/identity/WritableIdentityCredential.java
index 305d0ea..6d56964 100644
--- a/identity/java/android/security/identity/WritableIdentityCredential.java
+++ b/identity/java/android/security/identity/WritableIdentityCredential.java
@@ -59,7 +59,8 @@
      * @param challenge is a non-empty byte array whose contents should be unique, fresh and
      *                  provided by the issuing authority. The value provided is embedded in the
      *                  attestation extension and enables the issuing authority to verify that the
-     *                  attestation certificate is fresh.
+     *                  attestation certificate is fresh. Implementations are required to support
+     *                  challenges at least 32 bytes of length.
      * @return the X.509 certificate for this credential's CredentialKey.
      */
     public abstract @NonNull Collection<X509Certificate> getCredentialKeyCertificateChain(
diff --git a/keystore/OWNERS b/keystore/OWNERS
index a63ca46..7ab9d76 100644
--- a/keystore/OWNERS
+++ b/keystore/OWNERS
@@ -1,4 +1,4 @@
+eranm@google.com
 jbires@google.com
 jdanis@google.com
-robbarnes@google.com
 swillden@google.com
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 919a93b..05fb4c3 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
+import android.security.keystore.KeyProperties;
 import android.security.maintenance.IKeystoreMaintenance;
 import android.system.keystore2.Domain;
 import android.system.keystore2.KeyDescriptor;
@@ -157,6 +158,11 @@
      * Migrates a key given by the source descriptor to the location designated by the destination
      * descriptor.
      *
+     * If Domain::APP is selected in either source or destination, nspace must be set to
+     * {@link KeyProperties#NAMESPACE_APPLICATION}, implying the caller's UID.
+     * If the caller has the MIGRATE_ANY_KEY permission, Domain::APP may be used with
+     * other nspace values which then indicates the UID of a different application.
+     *
      * @param source - The key to migrate may be specified by Domain.APP, Domain.SELINUX, or
      *               Domain.KEY_ID. The caller needs the permissions use, delete, and grant for the
      *               source namespace.
@@ -183,4 +189,20 @@
             return SYSTEM_ERROR;
         }
     }
+
+    /**
+     * @see IKeystoreMaintenance#listEntries(int, long)
+     */
+    @Nullable
+    public static KeyDescriptor[] listEntries(int domain, long nspace) {
+        try {
+            return getService().listEntries(domain, nspace);
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "listEntries failed", e);
+            return null;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return null;
+        }
+    }
 }
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index 1034847..3d53cfb 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -108,7 +108,7 @@
             try {
                 return request.execute(service);
             } catch (ServiceSpecificException e) {
-                throw getKeyStoreException(e.errorCode);
+                throw getKeyStoreException(e.errorCode, e.getMessage());
             } catch (RemoteException e) {
                 if (firstTry) {
                     Log.w(TAG, "Looks like we may have lost connection to the Keystore "
@@ -120,7 +120,7 @@
                     firstTry = false;
                 } else {
                     Log.e(TAG, "Cannot connect to Keystore daemon.", e);
-                    throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "");
+                    throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
                 }
             }
         }
@@ -322,26 +322,32 @@
         }
     }
 
-    static KeyStoreException getKeyStoreException(int errorCode) {
+    static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) {
         if (errorCode > 0) {
             // KeyStore layer error
             switch (errorCode) {
                 case ResponseCode.LOCKED:
-                    return new KeyStoreException(errorCode, "User authentication required");
+                    return new KeyStoreException(errorCode, "User authentication required",
+                            serviceErrorMessage);
                 case ResponseCode.UNINITIALIZED:
-                    return new KeyStoreException(errorCode, "Keystore not initialized");
+                    return new KeyStoreException(errorCode, "Keystore not initialized",
+                            serviceErrorMessage);
                 case ResponseCode.SYSTEM_ERROR:
-                    return new KeyStoreException(errorCode, "System error");
+                    return new KeyStoreException(errorCode, "System error", serviceErrorMessage);
                 case ResponseCode.PERMISSION_DENIED:
-                    return new KeyStoreException(errorCode, "Permission denied");
+                    return new KeyStoreException(errorCode, "Permission denied",
+                            serviceErrorMessage);
                 case ResponseCode.KEY_NOT_FOUND:
-                    return new KeyStoreException(errorCode, "Key not found");
+                    return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage);
                 case ResponseCode.VALUE_CORRUPTED:
-                    return new KeyStoreException(errorCode, "Key blob corrupted");
+                    return new KeyStoreException(errorCode, "Key blob corrupted",
+                            serviceErrorMessage);
                 case ResponseCode.KEY_PERMANENTLY_INVALIDATED:
-                    return new KeyStoreException(errorCode, "Key permanently invalidated");
+                    return new KeyStoreException(errorCode, "Key permanently invalidated",
+                            serviceErrorMessage);
                 default:
-                    return new KeyStoreException(errorCode, String.valueOf(errorCode));
+                    return new KeyStoreException(errorCode, String.valueOf(errorCode),
+                            serviceErrorMessage);
             }
         } else {
             // Keymaster layer error
@@ -350,10 +356,12 @@
                     // The name of this parameter significantly differs between Keymaster and
                     // framework APIs. Use the framework wording to make life easier for developers.
                     return new KeyStoreException(errorCode,
-                            "Invalid user authentication validity duration");
+                            "Invalid user authentication validity duration",
+                            serviceErrorMessage);
                 default:
                     return new KeyStoreException(errorCode,
-                            KeymasterDefs.getErrorMessage(errorCode));
+                            KeymasterDefs.getErrorMessage(errorCode),
+                            serviceErrorMessage);
             }
         }
     }
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index 30389a29d..54184db 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -16,25 +16,458 @@
 
 package android.security;
 
+import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.security.keymaster.KeymasterDefs;
+import android.system.keystore2.ResponseCode;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
- * KeyStore/keymaster exception with positive error codes coming from the KeyStore and negative
- * ones from keymaster.
+ * Exception containing information about the failure at the Keystore / KeyMint layer while
+ * generating or using a key.
  *
- * @hide
+ * The public error codes indicate the cause of the error and the methods indicate whether
+ * it's a system/key issue and whether re-trying the operation (with the same key or a new key)
+ * is likely to succeed.
  */
-@TestApi
 public class KeyStoreException extends Exception {
+    /**
+     * This error code is for mapping errors that the caller will not know about. If the caller is
+     * targeting an API level earlier than the one the error was introduced in, then the error will
+     * be mapped to this one.
+     * In API level 33 no errors map to this error.
+     */
+    public static final int ERROR_OTHER = 1;
+    /**
+     * Indicating the key could not be used because the user needs to authenticate first.
+     * See
+     * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}.
+     */
+    public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2;
+    /**
+     * Indicating that {@code load()} has not been called on the Keystore instance, or an attempt
+     * has been made to generate an authorization bound key while the user has not set a lock
+     * screen knowledge factor (LSKF). Instruct the user to set an LSKF and retry.
+     */
+    public static final int ERROR_KEYSTORE_UNINITIALIZED = 3;
+    /**
+     * An internal system error - refer to {@link #isTransientFailure()} to determine whether
+     * re-trying the operation is likely to yield different results.
+     */
+    public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4;
+    /**
+     * The caller has requested key parameters or operation which are only available to system
+     * or privileged apps.
+     */
+    public static final int ERROR_PERMISSION_DENIED = 5;
+    /**
+     * The key the operation refers to doesn't exist.
+     */
+    public static final int ERROR_KEY_DOES_NOT_EXIST = 6;
+    /**
+     * The key is corrupted and could not be recovered.
+     */
+    public static final int ERROR_KEY_CORRUPTED = 7;
+    /**
+     * The error related to inclusion of device identifiers in the attestation record.
+     */
+    public static final int ERROR_ID_ATTESTATION_FAILURE = 8;
+    /**
+     * The attestation challenge specified is too large.
+     */
+    public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9;
+    /**
+     * General error in the KeyMint layer.
+     */
+    public static final int ERROR_KEYMINT_FAILURE = 10;
+    /**
+     * Failure in the Keystore layer.
+     */
+    public static final int ERROR_KEYSTORE_FAILURE = 11;
+    /**
+     * The feature the caller is trying to use is not implemented by the underlying
+     * KeyMint implementation.
+     * This could happen when an unsupported algorithm is requested, or when trying to import
+     * a key in a format other than raw or PKCS#8.
+     */
+    public static final int ERROR_UNIMPLEMENTED = 12;
+    /**
+     * The feature the caller is trying to use is not compatible with the parameters used to
+     * generate the key. For example, trying to use a key generated for a different signature
+     * algorithm, or a digest not specified during key creation.
+     * Another case is the attempt to generate a symmetric AES key and requesting key attestation.
+     */
+    public static final int ERROR_INCORRECT_USAGE = 13;
+    /**
+     * The key is not currently valid: Either at has expired or it will be valid for use in the
+     * future.
+     */
+    public static final int ERROR_KEY_NOT_TEMPORALLY_VALID = 14;
+    /**
+     * The crypto object the caller has been using held a reference to a KeyMint operation that
+     * has been evacuated (likely due to other concurrent operations taking place).
+     * The caller should re-create the crypto object and try again.
+     */
+    public static final int ERROR_KEY_OPERATION_EXPIRED = 15;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = {"ERROR_"}, value = {
+            ERROR_OTHER,
+            ERROR_USER_AUTHENTICATION_REQUIRED,
+            ERROR_KEYSTORE_UNINITIALIZED,
+            ERROR_INTERNAL_SYSTEM_ERROR,
+            ERROR_PERMISSION_DENIED,
+            ERROR_KEY_DOES_NOT_EXIST,
+            ERROR_KEY_CORRUPTED,
+            ERROR_ID_ATTESTATION_FAILURE,
+            ERROR_ATTESTATION_CHALLENGE_TOO_LARGE,
+            ERROR_KEYMINT_FAILURE,
+            ERROR_KEYSTORE_FAILURE,
+            ERROR_UNIMPLEMENTED,
+            ERROR_INCORRECT_USAGE,
+            ERROR_KEY_NOT_TEMPORALLY_VALID,
+            ERROR_KEY_OPERATION_EXPIRED
+    })
+    public @interface PublicErrorCode {
+    }
+
+    // Constants for encoding information about the error encountered:
+    // Whether the error relates to the system state/implementation as a whole, or a specific key.
+    private static final int IS_SYSTEM_ERROR = 1 << 1;
+    // Whether the error is permanent.
+    private static final int IS_TRANSIENT_ERROR = 1 << 2;
+    // Whether the cause of the error is the user not having authenticated recently.
+    private static final int REQUIRES_USER_AUTHENTICATION = 1 << 3;
+
+    // The internal error code. NOT to be returned directly to callers or made part of the
+    // public API.
     private final int mErrorCode;
 
-    public KeyStoreException(int errorCode, String message) {
+    /**
+     * @hide
+     */
+    public KeyStoreException(int errorCode, @Nullable String message) {
         super(message);
         mErrorCode = errorCode;
     }
 
+    /**
+     * @hide
+     */
+    public KeyStoreException(int errorCode, @Nullable String message,
+            @Nullable String keystoreErrorMessage) {
+        super(message + " (internal Keystore code: " + errorCode + " message: "
+                + keystoreErrorMessage + ")");
+        mErrorCode = errorCode;
+    }
+
+    /**
+     * Returns the internal error code. Only for use by the platform.
+     *
+     * @hide
+     */
+    @TestApi
     public int getErrorCode() {
         return mErrorCode;
     }
+
+    /**
+     * Returns one of the error codes exported by the class.
+     *
+     * @return a public error code, one of the values in {@link PublicErrorCode}.
+     */
+    @PublicErrorCode
+    public int getNumericErrorCode() {
+        PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+        return failureInfo.errorCode;
+    }
+
+    /**
+     * Returns true if the failure is a transient failure - that is, performing the same operation
+     * again at a late time is likely to succeed.
+     *
+     * If {@link #isSystemError()} returns true, the transient nature of the failure relates to the
+     * device, otherwise relates to the key (so a permanent failure with an existing key likely
+     * requires creating another key to repeat the operation with).
+     */
+    public boolean isTransientFailure() {
+        PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+        return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0;
+    }
+
+    /**
+     * Indicates whether the failure is due to the device being locked.
+     *
+     * @return true if the key operation failed because the user has to authenticate
+     * (e.g. by unlocking the device).
+     */
+    public boolean requiresUserAuthentication() {
+        PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+        return (failureInfo.indicators & REQUIRES_USER_AUTHENTICATION) != 0;
+    }
+
+    /**
+     * Indicates whether the error related to the Keystore/KeyMint implementation and not
+     * a specific key.
+     *
+     * @return true if the error is related to the system, not the key in use. System
+     * errors indicate a feature isn't working, whereas key-related errors are likely
+     * to succeed with a new key.
+     */
+    public boolean isSystemError() {
+        PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+        return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0;
+    }
+
+    @Override
+    public String toString() {
+        String errorCodes = String.format(" (public error code: %d internal Keystore code: %d)",
+                getNumericErrorCode(), mErrorCode);
+        return super.toString() + errorCodes;
+    }
+
+    private static PublicErrorInformation getErrorInformation(int internalErrorCode) {
+        PublicErrorInformation errorInfo = sErrorCodeToFailureInfo.get(internalErrorCode);
+        if (errorInfo != null) {
+            return errorInfo;
+        }
+
+        /**
+         * KeyStore/keymaster exception with positive error codes coming from the KeyStore and
+         * negative ones from keymaster.
+         * This is a safety fall-back: All error codes should be present in the map.
+         */
+        if (internalErrorCode > 0) {
+            return GENERAL_KEYSTORE_ERROR;
+        } else {
+            return GENERAL_KEYMINT_ERROR;
+        }
+    }
+
+    private static final class PublicErrorInformation {
+        public final int indicators;
+        public final int errorCode;
+
+        PublicErrorInformation(int indicators, @PublicErrorCode int errorCode) {
+            this.indicators = indicators;
+            this.errorCode = errorCode;
+        }
+    }
+
+    private static final PublicErrorInformation GENERAL_KEYMINT_ERROR =
+            new PublicErrorInformation(0, ERROR_KEYMINT_FAILURE);
+
+    private static final PublicErrorInformation GENERAL_KEYSTORE_ERROR =
+            new PublicErrorInformation(0, ERROR_KEYSTORE_FAILURE);
+
+    private static final PublicErrorInformation KEYMINT_UNIMPLEMENTED_ERROR =
+            new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_UNIMPLEMENTED);
+
+    private static final PublicErrorInformation KEYMINT_RETRYABLE_ERROR =
+            new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR,
+                    ERROR_KEYMINT_FAILURE);
+
+    private static final PublicErrorInformation KEYMINT_INCORRECT_USAGE_ERROR =
+            new PublicErrorInformation(0, ERROR_INCORRECT_USAGE);
+
+    private static final PublicErrorInformation KEYMINT_TEMPORAL_VALIDITY_ERROR =
+            new PublicErrorInformation(0, ERROR_KEY_NOT_TEMPORALLY_VALID);
+
+
+    private static final Map<Integer, PublicErrorInformation> sErrorCodeToFailureInfo =
+            new HashMap();
+
+    /**
+     * @hide
+     */
+    @TestApi
+    public static boolean hasFailureInfoForError(int internalErrorCode) {
+        return sErrorCodeToFailureInfo.containsKey(internalErrorCode);
+    }
+
+    static {
+        // KeyMint error codes
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OK, GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ROOT_OF_TRUST_ALREADY_SET,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_PURPOSE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_PURPOSE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_ALGORITHM,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_ALGORITHM,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_SIZE,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_BLOCK_MODE,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_BLOCK_MODE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MAC_LENGTH,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_PADDING_MODE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_PADDING_MODE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_DIGEST,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_DIGEST,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_EXPIRATION_TIME,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_USER_ID,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_FORMAT,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_KEY_FORMAT,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_EXPORT_OPTIONS_INVALID,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DELEGATION_NOT_ALLOWED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID,
+                KEYMINT_TEMPORAL_VALIDITY_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_EXPIRED,
+                KEYMINT_TEMPORAL_VALIDITY_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+                new PublicErrorInformation(REQUIRES_USER_AUTHENTICATION,
+                        ERROR_USER_AUTHENTICATION_REQUIRED));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OUTPUT_PARAMETER_NULL,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE,
+                new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR,
+                        ERROR_KEY_OPERATION_EXPIRED));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_VERIFICATION_FAILED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_TOO_MANY_OPERATIONS,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNEXPECTED_NULL_POINTER,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_KEY_BLOB,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_NOT_SIGNED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_ARGUMENT,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_TAG,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_TAG,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MEMORY_ALLOCATION_FAILED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_ACCESS_DENIED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OPERATION_CANCELLED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CONCURRENT_ACCESS_CONFLICT,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_BUSY,
+                KEYMINT_RETRYABLE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_COMMUNICATION_FAILED,
+                KEYMINT_RETRYABLE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_EC_FIELD,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NONCE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_NONCE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_MAC_LENGTH,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
+                KEYMINT_RETRYABLE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED,
+                GENERAL_KEYMINT_ERROR);
+        // Error related to MAX_USES_PER_BOOT, restricting the number of uses per boot.
+        // It is not re-tryable.
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_MAX_OPS_EXCEEDED,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_MAC_LENGTH,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_MIN_MAC_LENGTH,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KDF,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_EC_CURVE,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_CHALLENGE_MISSING,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEYMINT_NOT_CONFIGURED,
+                new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_KEYMINT_FAILURE));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING,
+                KEYMINT_RETRYABLE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CANNOT_ATTEST_IDS,
+                new PublicErrorInformation(IS_SYSTEM_ERROR,
+                        ERROR_ID_ATTESTATION_FAILURE));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DEVICE_LOCKED,
+                new PublicErrorInformation(IS_SYSTEM_ERROR | REQUIRES_USER_AUTHENTICATION,
+                        ERROR_USER_AUTHENTICATION_REQUIRED));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_STORAGE_KEY_UNSUPPORTED,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_MGF_DIGEST,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MGF_DIGEST,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_BEFORE,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_AFTER,
+                KEYMINT_INCORRECT_USAGE_ERROR);
+        // This should not be exposed to apps as it's handled by Keystore.
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_NOT_YET_AVAILABLE,
+                GENERAL_KEYMINT_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNIMPLEMENTED,
+                KEYMINT_UNIMPLEMENTED_ERROR);
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+                new PublicErrorInformation(IS_SYSTEM_ERROR,
+                        ERROR_KEYMINT_FAILURE));
+        sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_VERSION_MISMATCH, GENERAL_KEYMINT_ERROR);
+
+        // Keystore error codes
+        sErrorCodeToFailureInfo.put(ResponseCode.LOCKED,
+                new PublicErrorInformation(REQUIRES_USER_AUTHENTICATION,
+                        ERROR_USER_AUTHENTICATION_REQUIRED));
+        sErrorCodeToFailureInfo.put(ResponseCode.UNINITIALIZED,
+                new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_KEYSTORE_UNINITIALIZED));
+        sErrorCodeToFailureInfo.put(ResponseCode.SYSTEM_ERROR,
+                new PublicErrorInformation(IS_SYSTEM_ERROR,
+                        ERROR_INTERNAL_SYSTEM_ERROR));
+        sErrorCodeToFailureInfo.put(ResponseCode.PERMISSION_DENIED,
+                new PublicErrorInformation(0, ERROR_PERMISSION_DENIED));
+        sErrorCodeToFailureInfo.put(ResponseCode.KEY_NOT_FOUND,
+                new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
+        sErrorCodeToFailureInfo.put(ResponseCode.VALUE_CORRUPTED,
+                new PublicErrorInformation(0, ERROR_KEY_CORRUPTED));
+        sErrorCodeToFailureInfo.put(ResponseCode.KEY_PERMANENTLY_INVALIDATED,
+                new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
+    }
 }
diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java
index e6c1ea8..737ff2b 100644
--- a/keystore/java/android/security/KeyStoreOperation.java
+++ b/keystore/java/android/security/KeyStoreOperation.java
@@ -75,7 +75,7 @@
                     );
                 }
                 default:
-                    throw KeyStore2.getKeyStoreException(e.errorCode);
+                    throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
             }
         } catch (RemoteException e) {
             // Log exception and report invalid operation handle.
@@ -85,7 +85,8 @@
                     "Remote exception while advancing a KeyStoreOperation.",
                     e
             );
-            throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "");
+            throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "",
+                    e.getMessage());
         }
     }
 
diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java
index b85dd74..9c0b46c 100644
--- a/keystore/java/android/security/KeyStoreSecurityLevel.java
+++ b/keystore/java/android/security/KeyStoreSecurityLevel.java
@@ -54,12 +54,12 @@
         try {
             return request.execute();
         } catch (ServiceSpecificException e) {
-            throw KeyStore2.getKeyStoreException(e.errorCode);
+            throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
         } catch (RemoteException e) {
             // Log exception and report invalid operation handle.
             // This should prompt the caller drop the reference to this operation and retry.
             Log.e(TAG, "Could not connect to Keystore.", e);
-            throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "");
+            throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
         }
     }
 
@@ -117,7 +117,7 @@
                         break;
                     }
                     default:
-                        throw KeyStore2.getKeyStoreException(e.errorCode);
+                        throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
                 }
             } catch (RemoteException e) {
                 Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java
new file mode 100644
index 0000000..31c7422
--- /dev/null
+++ b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import static org.junit.Assert.assertTrue;
+
+import android.security.KeyStoreException;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class KeyStoreExceptionTest {
+    @Test
+    public void testKeystoreMessageIsIncluded() {
+        final String primaryMessage = "some_message";
+        final String keystoreMessage = "ks_message";
+        KeyStoreException exception = new KeyStoreException(-1, primaryMessage, keystoreMessage);
+
+        String exceptionMessage = exception.getMessage();
+        assertTrue(exceptionMessage.contains(primaryMessage));
+        assertTrue(exceptionMessage.contains(keystoreMessage));
+
+        String exceptionString = exception.toString();
+        assertTrue(exceptionString.contains(primaryMessage));
+        assertTrue(exceptionString.contains(keystoreMessage));
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/OWNERS
new file mode 100644
index 0000000..8446b37
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Split Screen
+# Bug component: 928697
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OWNERS
new file mode 100644
index 0000000..566acc8
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Bubbles
+# Bug component: 555586
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OWNERS
new file mode 100644
index 0000000..8446b37
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Split Screen
+# Bug component: 928697
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/OWNERS
new file mode 100644
index 0000000..172e24bf
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Picture-In-Picture
+# Bug component: 316251
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index d17c328..8150e78 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -686,6 +686,12 @@
         std::unordered_set<uint32_t> finalized_ids;
         const auto lib_alias = child_chunk.header<ResTable_staged_alias_header>();
         if (!lib_alias) {
+          LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small.";
+          return {};
+        }
+        if ((child_chunk.data_size() / sizeof(ResTable_staged_alias_entry))
+            < dtohl(lib_alias->count)) {
+          LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small to hold entries.";
           return {};
         }
         const auto entry_begin = child_chunk.data_ptr().convert<ResTable_staged_alias_entry>();
diff --git a/libs/androidfw/tests/BackupHelpers_test.cpp b/libs/androidfw/tests/BackupHelpers_test.cpp
index 86b7fb3..c2fcb69 100644
--- a/libs/androidfw/tests/BackupHelpers_test.cpp
+++ b/libs/androidfw/tests/BackupHelpers_test.cpp
@@ -50,7 +50,7 @@
 TEST_F(BackupHelpersTest, WriteTarFileWithSizeGreaterThan2GB) {
   TemporaryFile tf;
   // Allocate a 2 GB file.
-  off64_t fileSize = 2ll * 1024ll * 1024ll * 1024ll + 512ll;
+  off64_t fileSize = 2LL * 1024LL * 1024LL * 1024LL + 512LL;
   ASSERT_EQ(0, posix_fallocate64(tf.fd, 0, fileSize));
   off64_t tarSize = 0;
   int err = write_tarfile(/* packageName */ String8("test-pkg"), /* domain */ String8(""), /* rootpath */ String8(""), /* filePath */ String8(tf.path), /* outSize */ &tarSize, /* writer */ NULL);
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index f8d6c07..a743d30 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -32,8 +32,6 @@
 
 using namespace android::uirenderer::renderthread;
 
-static constexpr bool sEnableExtraCropInset = true;
-
 namespace android {
 namespace uirenderer {
 
@@ -66,20 +64,6 @@
         ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
         return CopyResult::SourceEmpty;
     }
-
-    if (sEnableExtraCropInset &&
-        (cropRect.right - cropRect.left != bitmap->width() ||
-        cropRect.bottom - cropRect.top != bitmap->height())) {
-       /*
-        * When we need use filtering, we should also make border shrink here like gui.
-        * But we could not check format for YUV or RGB here... Just use 1 pix.
-        */
-        cropRect.left += 0.5f;
-        cropRect.top  += 0.5f;
-        cropRect.right -= 0.5f;
-        cropRect.bottom -= 0.5f;
-    }
-
     UniqueAHardwareBuffer sourceBuffer{rawSourceBuffer};
     AHardwareBuffer_Desc description;
     AHardwareBuffer_describe(sourceBuffer.get(), &description);
diff --git a/libs/hwui/jni/NinePatch.cpp b/libs/hwui/jni/NinePatch.cpp
index 6942017..3ca457f 100644
--- a/libs/hwui/jni/NinePatch.cpp
+++ b/libs/hwui/jni/NinePatch.cpp
@@ -67,7 +67,7 @@
         size_t chunkSize = env->GetArrayLength(obj);
         if (chunkSize < (int) (sizeof(Res_png_9patch))) {
             jniThrowRuntimeException(env, "Array too small for chunk.");
-            return NULL;
+            return 0;
         }
 
         int8_t* storage = new int8_t[chunkSize];
diff --git a/libs/hwui/jni/android_util_PathParser.cpp b/libs/hwui/jni/android_util_PathParser.cpp
index 72995ef..8cbb70e 100644
--- a/libs/hwui/jni/android_util_PathParser.cpp
+++ b/libs/hwui/jni/android_util_PathParser.cpp
@@ -61,7 +61,7 @@
     } else {
         delete pathData;
         doThrowIAE(env, result.failureMessage.c_str());
-        return NULL;
+        return 0;
     }
 }
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2fed468..00561be 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -287,7 +287,7 @@
     };
 
     // Need at least 4 because we do quad buffer. Add a 5th for good measure.
-    RingBuffer<SwapHistory, 5> mSwapHistory;
+    RingBuffer<SwapHistory, 7> mSwapHistory;
     int64_t mFrameNumber = -1;
     int64_t mDamageId = 0;
 
diff --git a/libs/tracingproxy/Android.bp b/libs/tracingproxy/Android.bp
index 7126bfa..23d107b 100644
--- a/libs/tracingproxy/Android.bp
+++ b/libs/tracingproxy/Android.bp
@@ -37,6 +37,7 @@
 
     srcs: [
         ":ITracingServiceProxy.aidl",
+        ":TraceReportParams.aidl",
     ],
 
     shared_libs: [
diff --git a/libs/usb/tests/accessorytest/f_accessory.h b/libs/usb/tests/accessorytest/f_accessory.h
index 312f4ba..75e017c 100644
--- a/libs/usb/tests/accessorytest/f_accessory.h
+++ b/libs/usb/tests/accessorytest/f_accessory.h
@@ -1,148 +1,53 @@
-/*
- * Gadget Function Driver for Android USB accessories
- *
- * Copyright (C) 2011 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __LINUX_USB_F_ACCESSORY_H
-#define __LINUX_USB_F_ACCESSORY_H
-
-/* Use Google Vendor ID when in accessory mode */
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_USB_F_ACCESSORY_H
+#define _UAPI_LINUX_USB_F_ACCESSORY_H
 #define USB_ACCESSORY_VENDOR_ID 0x18D1
-
-
-/* Product ID to use when in accessory mode */
 #define USB_ACCESSORY_PRODUCT_ID 0x2D00
-
-/* Product ID to use when in accessory mode and adb is enabled */
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
-
-/* Indexes for strings sent by the host via ACCESSORY_SEND_STRING */
-#define ACCESSORY_STRING_MANUFACTURER   0
-#define ACCESSORY_STRING_MODEL          1
-#define ACCESSORY_STRING_DESCRIPTION    2
-#define ACCESSORY_STRING_VERSION        3
-#define ACCESSORY_STRING_URI            4
-#define ACCESSORY_STRING_SERIAL         5
-
-/* Control request for retrieving device's protocol version
- *
- *	requestType:    USB_DIR_IN | USB_TYPE_VENDOR
- *	request:        ACCESSORY_GET_PROTOCOL
- *	value:          0
- *	index:          0
- *	data            version number (16 bits little endian)
- *                    1 for original accessory support
- *                    2 adds audio and HID support
- */
-#define ACCESSORY_GET_PROTOCOL  51
-
-/* Control request for host to send a string to the device
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_SEND_STRING
- *	value:          0
- *	index:          string ID
- *	data            zero terminated UTF8 string
- *
- *  The device can later retrieve these strings via the
- *  ACCESSORY_GET_STRING_* ioctls
- */
-#define ACCESSORY_SEND_STRING   52
-
-/* Control request for starting device in accessory mode.
- * The host sends this after setting all its strings to the device.
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_START
- *	value:          0
- *	index:          0
- *	data            none
- */
-#define ACCESSORY_START         53
-
-/* Control request for registering a HID device.
- * Upon registering, a unique ID is sent by the accessory in the
- * value parameter. This ID will be used for future commands for
- * the device
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_REGISTER_HID_DEVICE
- *	value:          Accessory assigned ID for the HID device
- *	index:          total length of the HID report descriptor
- *	data            none
- */
-#define ACCESSORY_REGISTER_HID         54
-
-/* Control request for unregistering a HID device.
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_REGISTER_HID
- *	value:          Accessory assigned ID for the HID device
- *	index:          0
- *	data            none
- */
-#define ACCESSORY_UNREGISTER_HID         55
-
-/* Control request for sending the HID report descriptor.
- * If the HID descriptor is longer than the endpoint zero max packet size,
- * the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
- * commands. The data for the descriptor must be sent sequentially
- * if multiple packets are needed.
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_SET_HID_REPORT_DESC
- *	value:          Accessory assigned ID for the HID device
- *	index:          offset of data in descriptor
- *                  (needed when HID descriptor is too big for one packet)
- *	data            the HID report descriptor
- */
-#define ACCESSORY_SET_HID_REPORT_DESC         56
-
-/* Control request for sending HID events.
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_SEND_HID_EVENT
- *	value:          Accessory assigned ID for the HID device
- *	index:          0
- *	data            the HID report for the event
- */
-#define ACCESSORY_SEND_HID_EVENT         57
-
-/* Control request for setting the audio mode.
- *
- *	requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
- *	request:        ACCESSORY_SET_AUDIO_MODE
- *	value:          0 - no audio
- *                  1 - device to host, 44100 16-bit stereo PCM
- *	index:          0
- *	data            the HID report for the event
- */
-#define ACCESSORY_SET_AUDIO_MODE         58
-
-
-
-/* ioctls for retrieving strings set by the host */
-#define ACCESSORY_GET_STRING_MANUFACTURER   _IOW('M', 1, char[256])
-#define ACCESSORY_GET_STRING_MODEL          _IOW('M', 2, char[256])
-#define ACCESSORY_GET_STRING_DESCRIPTION    _IOW('M', 3, char[256])
-#define ACCESSORY_GET_STRING_VERSION        _IOW('M', 4, char[256])
-#define ACCESSORY_GET_STRING_URI            _IOW('M', 5, char[256])
-#define ACCESSORY_GET_STRING_SERIAL         _IOW('M', 6, char[256])
-/* returns 1 if there is a start request pending */
-#define ACCESSORY_IS_START_REQUESTED        _IO('M', 7)
-/* returns audio mode (set via the ACCESSORY_SET_AUDIO_MODE control request) */
-#define ACCESSORY_GET_AUDIO_MODE            _IO('M', 8)
-
-#endif /* __LINUX_USB_F_ACCESSORY_H */
+#define ACCESSORY_STRING_MANUFACTURER 0
+#define ACCESSORY_STRING_MODEL 1
+#define ACCESSORY_STRING_DESCRIPTION 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+#define ACCESSORY_GET_PROTOCOL 51
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_SEND_STRING 52
+#define ACCESSORY_START 53
+#define ACCESSORY_REGISTER_HID 54
+#define ACCESSORY_UNREGISTER_HID 55
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_SET_HID_REPORT_DESC 56
+#define ACCESSORY_SEND_HID_EVENT 57
+#define ACCESSORY_SET_AUDIO_MODE 58
+#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
+#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256])
+#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
+#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256])
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
+#define ACCESSORY_IS_START_REQUESTED _IO('M', 7)
+#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/media/Android.bp b/media/Android.bp
index 1b7bef5..b7c3a9c 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -100,6 +100,11 @@
             vndk: {
                 enabled: true,
             },
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
         },
     },
 }
diff --git a/media/OWNERS b/media/OWNERS
index 0aff43e..5f50137 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -3,7 +3,6 @@
 essick@google.com
 etalvala@google.com
 hdmoon@google.com
-hkuang@google.com
 hunga@google.com
 insun@google.com
 jaewan@google.com
diff --git a/media/java/Android.bp b/media/java/Android.bp
index eeaf6e9..c7c1d54 100644
--- a/media/java/Android.bp
+++ b/media/java/Android.bp
@@ -8,7 +8,7 @@
 }
 
 filegroup {
-    name: "framework-media-sources",
+    name: "framework-media-non-updatable-sources",
     srcs: [
         "**/*.java",
         "**/*.aidl",
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index a186566..3edb101 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -177,6 +177,11 @@
      */
     public static final int TYPE_HDMI_EARC         = 29;
 
+    /**
+     * A device type describing a Bluetooth Low Energy (BLE) broadcast group.
+     */
+    public static final int TYPE_BLE_BROADCAST   = 30;
+
     /** @hide */
     @IntDef(flag = false, prefix = "TYPE", value = {
             TYPE_BUILTIN_EARPIECE,
@@ -207,7 +212,8 @@
             TYPE_REMOTE_SUBMIX,
             TYPE_BLE_HEADSET,
             TYPE_BLE_SPEAKER,
-            TYPE_ECHO_REFERENCE}
+            TYPE_ECHO_REFERENCE,
+            TYPE_BLE_BROADCAST}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioDeviceType {}
@@ -264,7 +270,8 @@
             TYPE_HEARING_AID,
             TYPE_BUILTIN_SPEAKER_SAFE,
             TYPE_BLE_HEADSET,
-            TYPE_BLE_SPEAKER}
+            TYPE_BLE_SPEAKER,
+            TYPE_BLE_BROADCAST}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioDeviceTypeOut {}
@@ -296,6 +303,7 @@
             case TYPE_BUILTIN_SPEAKER_SAFE:
             case TYPE_BLE_HEADSET:
             case TYPE_BLE_SPEAKER:
+            case TYPE_BLE_BROADCAST:
                 return true;
             default:
                 return false;
@@ -627,6 +635,7 @@
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_HEADSET, TYPE_BLE_HEADSET);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_SPEAKER, TYPE_BLE_SPEAKER);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_BROADCAST, TYPE_BLE_BROADCAST);
 
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
@@ -684,6 +693,7 @@
         EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
         EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET);
         EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER);
+        EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_BROADCAST, AudioSystem.DEVICE_OUT_BLE_BROADCAST);
 
         // privileges mapping to input device
         EXT_TO_INT_INPUT_DEVICE_MAPPING = new SparseIntArray();
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index ebe0882..9211c53 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -90,7 +90,8 @@
      * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER})
      * use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by
      * {@link BluetoothDevice#getAddress()}.
-     * - Deivces that do not have an address will indicate an empty string "".
+     * - Bluetooth LE broadcast group ({@link AudioManager#DEVICE_OUT_BLE_BROADCAST} use the group number.
+     * - Devices that do not have an address will indicate an empty string "".
      */
     public String address() {
         return mAddress;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b7e8c8c..ce2bccf 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5404,6 +5404,10 @@
      */
     public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER;
     /** @hide
+     * The audio output device code for a BLE audio brodcast group.
+     */
+    public static final int DEVICE_OUT_BLE_BROADCAST = AudioSystem.DEVICE_OUT_BLE_BROADCAST;
+    /** @hide
      * This is not used as a returned value from {@link #getDevicesForStream}, but could be
      *  used in the future in a set method to select whatever default device is chosen by the
      *  platform-specific implementation.
@@ -5806,13 +5810,14 @@
      * @param newDevice Bluetooth device connected or null if there is no new devices
      * @param previousDevice Bluetooth device disconnected or null if there is no disconnected
      * devices
-     * @param info contain all info related to the device. {@link BtProfileConnectionInfo}
+     * @param info contain all info related to the device. {@link BluetoothProfileConnectionInfo}
      * {@hide}
      */
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
     public void handleBluetoothActiveDeviceChanged(@Nullable BluetoothDevice newDevice,
-            @Nullable BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
+            @Nullable BluetoothDevice previousDevice,
+            @NonNull BluetoothProfileConnectionInfo info) {
         final IAudioService service = getService();
         try {
             service.handleBluetoothActiveDeviceChanged(newDevice, previousDevice, info);
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index f0e42c0..33b877c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -242,7 +242,8 @@
             AUDIO_FORMAT_SBC,
             AUDIO_FORMAT_APTX,
             AUDIO_FORMAT_APTX_HD,
-            AUDIO_FORMAT_LDAC}
+            AUDIO_FORMAT_LDAC,
+            AUDIO_FORMAT_LC3}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioFormatNativeEnumForBtCodec {}
@@ -274,6 +275,7 @@
             case AUDIO_FORMAT_APTX: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
             case AUDIO_FORMAT_APTX_HD: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
             case AUDIO_FORMAT_LDAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
+            case AUDIO_FORMAT_LC3: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3;
             default:
                 Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat)
                         + " for conversion to BT codec");
@@ -314,6 +316,8 @@
                 return AudioSystem.AUDIO_FORMAT_APTX_HD;
             case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
                 return AudioSystem.AUDIO_FORMAT_LDAC;
+            case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3:
+                return AudioSystem.AUDIO_FORMAT_LC3;
             default:
                 Log.e(TAG, "Unknown BT codec 0x" + Integer.toHexString(btCodec)
                         + " for conversion to audio format");
@@ -414,6 +418,8 @@
                 return "AUDIO_FORMAT_LHDC_LL";
             case /* AUDIO_FORMAT_APTX_TWSP       */ 0x2A000000:
                 return "AUDIO_FORMAT_APTX_TWSP";
+            case /* AUDIO_FORMAT_LC3             */ 0x2B000000:
+                return "AUDIO_FORMAT_LC3";
 
             /* Aliases */
             case /* AUDIO_FORMAT_PCM_16_BIT        */ 0x1:
@@ -976,6 +982,8 @@
     public static final int DEVICE_OUT_BLE_HEADSET = 0x20000000;
     /** @hide */
     public static final int DEVICE_OUT_BLE_SPEAKER = 0x20000001;
+    /** @hide */
+    public static final int DEVICE_OUT_BLE_BROADCAST = 0x20000002;
 
     /** @hide */
     public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -1036,6 +1044,7 @@
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ECHO_CANCELLER);
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_HEADSET);
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_SPEAKER);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_BROADCAST);
         DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
 
         DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
@@ -1066,6 +1075,7 @@
         DEVICE_OUT_ALL_BLE_SET = new HashSet<>();
         DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_HEADSET);
         DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER);
+        DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_BROADCAST);
     }
 
     // input devices
@@ -1249,6 +1259,7 @@
     /** @hide */ public static final String DEVICE_OUT_ECHO_CANCELLER_NAME = "echo_canceller";
     /** @hide */ public static final String DEVICE_OUT_BLE_HEADSET_NAME = "ble_headset";
     /** @hide */ public static final String DEVICE_OUT_BLE_SPEAKER_NAME = "ble_speaker";
+    /** @hide */ public static final String DEVICE_OUT_BLE_BROADCAST_NAME = "ble_broadcast";
 
     /** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
     /** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
@@ -1348,6 +1359,8 @@
             return DEVICE_OUT_BLE_HEADSET_NAME;
         case DEVICE_OUT_BLE_SPEAKER:
             return DEVICE_OUT_BLE_SPEAKER_NAME;
+        case DEVICE_OUT_BLE_BROADCAST:
+            return DEVICE_OUT_BLE_BROADCAST_NAME;
         case DEVICE_OUT_DEFAULT:
         default:
             return Integer.toString(device);
diff --git a/media/java/android/media/BtProfileConnectionInfo.aidl b/media/java/android/media/BluetoothProfileConnectionInfo.aidl
similarity index 93%
rename from media/java/android/media/BtProfileConnectionInfo.aidl
rename to media/java/android/media/BluetoothProfileConnectionInfo.aidl
index 047f06b..0617084 100644
--- a/media/java/android/media/BtProfileConnectionInfo.aidl
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.aidl
@@ -16,5 +16,5 @@
 
 package android.media;
 
-parcelable BtProfileConnectionInfo;
+parcelable BluetoothProfileConnectionInfo;
 
diff --git a/media/java/android/media/BtProfileConnectionInfo.java b/media/java/android/media/BluetoothProfileConnectionInfo.java
similarity index 60%
rename from media/java/android/media/BtProfileConnectionInfo.java
rename to media/java/android/media/BluetoothProfileConnectionInfo.java
index 19ea2de..c148846 100644
--- a/media/java/android/media/BtProfileConnectionInfo.java
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.java
@@ -15,40 +15,25 @@
  */
 package android.media;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.bluetooth.BluetoothProfile;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * Contains information about Bluetooth profile connection state changed
  * {@hide}
  */
 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public final class BtProfileConnectionInfo implements Parcelable {
-    /** @hide */
-    @IntDef({
-            BluetoothProfile.A2DP,
-            BluetoothProfile.A2DP_SINK, // Can only be set by BtHelper
-            BluetoothProfile.HEADSET, // Can only be set by BtHelper
-            BluetoothProfile.HEARING_AID,
-            BluetoothProfile.LE_AUDIO,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface BtProfile {}
-
-    private final @BtProfile int mProfile;
+public final class BluetoothProfileConnectionInfo implements Parcelable {
+    private final int mProfile;
     private final boolean mSupprNoisy;
     private final int mVolume;
     private final boolean mIsLeOutput;
 
-    private BtProfileConnectionInfo(@BtProfile int profile, boolean suppressNoisyIntent, int volume,
-            boolean isLeOutput) {
+    private BluetoothProfileConnectionInfo(int profile, boolean suppressNoisyIntent,
+            int volume, boolean isLeOutput) {
         mProfile = profile;
         mSupprNoisy = suppressNoisyIntent;
         mVolume = volume;
@@ -59,21 +44,21 @@
      * Constructor used by BtHelper when a profile is connected
      * {@hide}
      */
-    public BtProfileConnectionInfo(@BtProfile int profile) {
+    public BluetoothProfileConnectionInfo(int profile) {
         this(profile, false, -1, false);
     }
 
-    public static final @NonNull Parcelable.Creator<BtProfileConnectionInfo> CREATOR =
-            new Parcelable.Creator<BtProfileConnectionInfo>() {
+    public static final @NonNull Parcelable.Creator<BluetoothProfileConnectionInfo> CREATOR =
+            new Parcelable.Creator<BluetoothProfileConnectionInfo>() {
                 @Override
-                public BtProfileConnectionInfo createFromParcel(Parcel source) {
-                    return new BtProfileConnectionInfo(source.readInt(), source.readBoolean(),
-                            source.readInt(), source.readBoolean());
+                public BluetoothProfileConnectionInfo createFromParcel(Parcel source) {
+                    return new BluetoothProfileConnectionInfo(source.readInt(),
+                            source.readBoolean(), source.readInt(), source.readBoolean());
                 }
 
                 @Override
-                public BtProfileConnectionInfo[] newArray(int size) {
-                    return new BtProfileConnectionInfo[size];
+                public BluetoothProfileConnectionInfo[] newArray(int size) {
+                    return new BluetoothProfileConnectionInfo[size];
                 }
             };
 
@@ -98,10 +83,20 @@
      *
      * @param volume of device -1 to ignore value
      */
-    public static @NonNull BtProfileConnectionInfo a2dpInfo(boolean suppressNoisyIntent,
-            int volume) {
-        return new BtProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent, volume,
-            false);
+    public static @NonNull BluetoothProfileConnectionInfo createA2dpInfo(
+            boolean suppressNoisyIntent, int volume) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent,
+            volume, false);
+    }
+
+    /**
+     * Constructor for A2dp sink info
+     * The {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
+     *
+     * @param volume of device -1 to ignore value
+     */
+    public static @NonNull BluetoothProfileConnectionInfo createA2dpSinkInfo(int volume) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false);
     }
 
     /**
@@ -110,9 +105,10 @@
      * @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY}
      * intent will not be sent.
      */
-    public static @NonNull BtProfileConnectionInfo hearingAidInfo(boolean suppressNoisyIntent) {
-        return new BtProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent, -1,
-            false);
+    public static @NonNull BluetoothProfileConnectionInfo createHearingAidInfo(
+            boolean suppressNoisyIntent) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent,
+            -1, false);
     }
 
     /**
@@ -123,16 +119,16 @@
      *
      * @param isLeOutput if true mean the device is an output device, if false it's an input device
      */
-    public static @NonNull BtProfileConnectionInfo leAudio(boolean suppressNoisyIntent,
-            boolean isLeOutput) {
-        return new BtProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent, -1,
-            isLeOutput);
+    public static @NonNull BluetoothProfileConnectionInfo createLeAudioInfo(
+            boolean suppressNoisyIntent, boolean isLeOutput) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent,
+            -1, isLeOutput);
     }
 
     /**
      * @return The profile connection
      */
-    public @BtProfile int getProfile() {
+    public int getProfile() {
         return mProfile;
     }
 
@@ -140,7 +136,7 @@
      * @return {@code true} if {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be
      * sent
      */
-    public boolean getSuppressNoisyIntent() {
+    public boolean isSuppressNoisyIntent() {
         return mSupprNoisy;
     }
 
@@ -157,7 +153,7 @@
      * @return {@code true} is the LE device is an output device, {@code false} if it's an input
      * device
      */
-    public boolean getIsLeOutput() {
+    public boolean isLeOutput() {
         return mIsLeOutput;
     }
 }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5ff56f9..d5a2d07 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -24,7 +24,7 @@
 import android.media.AudioPlaybackConfiguration;
 import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioModeDispatcher;
 import android.media.IAudioRoutesObserver;
@@ -268,7 +268,7 @@
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
     void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice,
-            in BluetoothDevice previousDevice, in BtProfileConnectionInfo info);
+            in BluetoothDevice previousDevice, in BluetoothProfileConnectionInfo info);
 
     oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
             in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3c152fb..77709d7 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -426,10 +426,30 @@
         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
         public static final int COLOR_Format24BitABGR6666           = 43;
 
-        /** @hide
-         * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
-         * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
-         * little-endian value, with the lower 6 bits set to zero. */
+        /**
+         * P010 is 10-bit-per component 4:2:0 YCbCr semiplanar format.
+         * <p>
+         * This format uses 24 allocated bits per pixel with 15 bits of
+         * data per pixel. Chroma planes are subsampled by 2 both
+         * horizontally and vertically. Each chroma and luma component
+         * has 16 allocated bits in little-endian configuration with 10
+         * MSB of actual data.
+         *
+         * <pre>
+         *            byte                   byte
+         *  <--------- i --------> | <------ i + 1 ------>
+         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+         * |     UNUSED      |      Y/Cb/Cr                |
+         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+         *  0               5 6   7 0                    7
+         * bit
+         * </pre>
+         *
+         * Use this format with {@link Image}. This format corresponds
+         * to {@link android.graphics.ImageFormat#YCBCR_P010}.
+         * <p>
+         */
+        @SuppressLint("AllUpper")
         public static final int COLOR_FormatYUVP010                 = 54;
 
         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
@@ -439,6 +459,25 @@
         public static final int COLOR_FormatSurface                   = 0x7F000789;
 
         /**
+         * 64 bits per pixel RGBA color format, with 16-bit signed
+         * floating point red, green, blue, and alpha components.
+         * <p>
+         *
+         * <pre>
+         *         byte              byte             byte              byte
+         *  <-- i -->|<- i+1 ->|<- i+2 ->|<- i+3 ->|<- i+4 ->|<- i+5 ->|<- i+6 ->|<- i+7 ->
+         * +---------+---------+-------------------+---------+---------+---------+---------+
+         * |        RED        |       GREEN       |       BLUE        |       ALPHA       |
+         * +---------+---------+-------------------+---------+---------+---------+---------+
+         *  0       7 0       7 0       7 0       7 0       7 0       7 0       7 0       7
+         * </pre>
+         *
+         * This corresponds to {@link android.graphics.PixelFormat#RGBA_F16}.
+         */
+        @SuppressLint("AllUpper")
+        public static final int COLOR_Format64bitABGRFloat            = 0x7F000F16;
+
+        /**
          * 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components.
          * <p>
          * Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8,
@@ -456,6 +495,26 @@
         public static final int COLOR_Format32bitABGR8888             = 0x7F00A000;
 
         /**
+         * 32 bits per pixel RGBA color format, with 10-bit red, green,
+         * blue, and 2-bit alpha components.
+         * <p>
+         * Using 32-bit little-endian representation, colors stored as
+         * Red 9:0, Green 19:10, Blue 29:20, and Alpha 31:30.
+         * <pre>
+         *         byte              byte             byte              byte
+         *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
+         * +-----------------+---+-------------+-------+---------+-----------+-----+
+         * |       RED           |      GREEN          |       BLUE          |ALPHA|
+         * +-----------------+---+-------------+-------+---------+-----------+-----+
+         *  0               7 0 1 2           7 0     3 4       7 0         5 6   7
+         * </pre>
+         *
+         * This corresponds to {@link android.graphics.PixelFormat#RGBA_1010102}.
+         */
+        @SuppressLint("AllUpper")
+        public static final int COLOR_Format32bitABGR2101010          = 0x7F00AAA2;
+
+        /**
          * Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma
          * components.
          * <p>
@@ -603,6 +662,18 @@
         public static final String FEATURE_QpBounds = "qp-bounds";
 
         /**
+         * <b>video encoder only</b>: codec supports exporting encoding statistics.
+         * Encoders with this feature can provide the App clients with the encoding statistics
+         * information about the frame.
+         * The scope of encoding statistics is controlled by
+         * {@link MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL}.
+         *
+         * @see MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL
+         */
+        @SuppressLint("AllUpper") // for consistency with other FEATURE_* constants
+        public static final String FEATURE_EncodingStatistics = "encoding-statistics";
+
+        /**
          * Query codec feature capabilities.
          * <p>
          * These features are supported to be used by the codec.  These
@@ -641,6 +712,7 @@
             new Feature(FEATURE_MultipleFrames, (1 << 1), false),
             new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
             new Feature(FEATURE_QpBounds, (1 << 3), false),
+            new Feature(FEATURE_EncodingStatistics, (1 << 4), false),
             // feature to exclude codec from REGULAR codec list
             new Feature(FEATURE_SpecialCodec,     (1 << 30), false, true),
         };
@@ -3953,6 +4025,12 @@
         public static final int DolbyVisionLevelUhd30   = 0x40;
         public static final int DolbyVisionLevelUhd48   = 0x80;
         public static final int DolbyVisionLevelUhd60   = 0x100;
+        @SuppressLint("AllUpper")
+        public static final int DolbyVisionLevelUhd120  = 0x200;
+        @SuppressLint("AllUpper")
+        public static final int DolbyVisionLevel8k30    = 0x400;
+        @SuppressLint("AllUpper")
+        public static final int DolbyVisionLevel8k60    = 0x800;
 
         // Profiles and levels for AV1 Codec, corresponding to the definitions in
         // "AV1 Bitstream & Decoding Process Specification", Annex A
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 9bf0db5..aa5c404 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1102,6 +1102,76 @@
     public static final String KEY_VIDEO_QP_B_MIN = "video-qp-b-min";
 
     /**
+     * A key describing the level of encoding statistics information emitted from video encoder.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_ENCODING_STATISTICS_LEVEL =
+            "video-encoding-statistics-level";
+
+    /**
+     * Encoding Statistics Level None.
+     * Encoder generates no information about Encoding statistics.
+     */
+    public static final int VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0;
+
+    /**
+     * Encoding Statistics Level 1.
+     * Encoder generates {@link MediaFormat#KEY_PICTURE_TYPE} and
+     * {@link MediaFormat#KEY_VIDEO_QP_AVERAGE} for each frame.
+     */
+    public static final int VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1;
+
+    /** @hide */
+    @IntDef({
+        VIDEO_ENCODING_STATISTICS_LEVEL_NONE,
+        VIDEO_ENCODING_STATISTICS_LEVEL_1,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface VideoEncodingStatisticsLevel {}
+
+    /**
+     * A key describing the per-frame average block QP (Quantization Parameter).
+     * This is a part of a video 'Encoding Statistics' export feature.
+     * This value is emitted from video encoder for a video frame.
+     * The average value is rounded down (using floor()) to integer value.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_VIDEO_QP_AVERAGE = "video-qp-average";
+
+    /**
+     * A key describing the picture type of the encoded frame.
+     * This is a part of a video 'Encoding Statistics' export feature.
+     * This value is emitted from video encoder for a video frame.
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_PICTURE_TYPE = "picture-type";
+
+    /** Picture Type is unknown. */
+    public static final int PICTURE_TYPE_UNKNOWN = 0;
+
+    /** Picture Type is I Frame. */
+    public static final int PICTURE_TYPE_I = 1;
+
+    /** Picture Type is P Frame. */
+    public static final int PICTURE_TYPE_P = 2;
+
+    /** Picture Type is B Frame. */
+    public static final int PICTURE_TYPE_B = 3;
+
+    /** @hide */
+    @IntDef({
+        PICTURE_TYPE_UNKNOWN,
+        PICTURE_TYPE_I,
+        PICTURE_TYPE_P,
+        PICTURE_TYPE_B,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PictureType {}
+
+    /**
      * A key describing the audio session ID of the AudioTrack associated
      * to a tunneled video codec.
      * The associated value is an integer.
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 3cf0341..86a94a9 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -504,49 +504,51 @@
     }
 
     private boolean playFallbackRingtone() {
-        if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
-                != 0) {
-            int ringtoneType = RingtoneManager.getDefaultType(mUri);
-            if (ringtoneType == -1 ||
-                    RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) != null) {
-                // Default ringtone, try fallback ringtone.
-                try {
-                    AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
-                            com.android.internal.R.raw.fallbackring);
-                    if (afd != null) {
-                        mLocalPlayer = new MediaPlayer();
-                        if (afd.getDeclaredLength() < 0) {
-                            mLocalPlayer.setDataSource(afd.getFileDescriptor());
-                        } else {
-                            mLocalPlayer.setDataSource(afd.getFileDescriptor(),
-                                    afd.getStartOffset(),
-                                    afd.getDeclaredLength());
-                        }
-                        mLocalPlayer.setAudioAttributes(mAudioAttributes);
-                        synchronized (mPlaybackSettingsLock) {
-                            applyPlaybackProperties_sync();
-                        }
-                        if (mVolumeShaperConfig != null) {
-                            mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
-                        }
-                        mLocalPlayer.prepare();
-                        startLocalPlayer();
-                        afd.close();
-                        return true;
-                    } else {
-                        Log.e(TAG, "Could not load fallback ringtone");
-                    }
-                } catch (IOException ioe) {
-                    destroyLocalPlayer();
-                    Log.e(TAG, "Failed to open fallback ringtone");
-                } catch (NotFoundException nfe) {
-                    Log.e(TAG, "Fallback ringtone does not exist");
-                }
-            } else {
-                Log.w(TAG, "not playing fallback for " + mUri);
-            }
+        int streamType = AudioAttributes.toLegacyStreamType(mAudioAttributes);
+        if (mAudioManager.getStreamVolume(streamType) == 0) {
+            return false;
         }
-        return false;
+        int ringtoneType = RingtoneManager.getDefaultType(mUri);
+        if (ringtoneType != -1 &&
+                RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) == null) {
+            Log.w(TAG, "not playing fallback for " + mUri);
+            return false;
+        }
+        // Default ringtone, try fallback ringtone.
+        try {
+            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
+                    com.android.internal.R.raw.fallbackring);
+            if (afd == null) {
+                Log.e(TAG, "Could not load fallback ringtone");
+                return false;
+            }
+            mLocalPlayer = new MediaPlayer();
+            if (afd.getDeclaredLength() < 0) {
+                mLocalPlayer.setDataSource(afd.getFileDescriptor());
+            } else {
+                mLocalPlayer.setDataSource(afd.getFileDescriptor(),
+                        afd.getStartOffset(),
+                        afd.getDeclaredLength());
+            }
+            mLocalPlayer.setAudioAttributes(mAudioAttributes);
+            synchronized (mPlaybackSettingsLock) {
+                applyPlaybackProperties_sync();
+            }
+            if (mVolumeShaperConfig != null) {
+                mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
+            }
+            mLocalPlayer.prepare();
+            startLocalPlayer();
+            afd.close();
+        } catch (IOException ioe) {
+            destroyLocalPlayer();
+            Log.e(TAG, "Failed to open fallback ringtone");
+            return false;
+        } catch (NotFoundException nfe) {
+            Log.e(TAG, "Fallback ringtone does not exist");
+            return false;
+        }
+        return true;
     }
 
     void setTitle(String title) {
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 1da41fb..33bc846 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -407,7 +407,7 @@
     /**
      * Get the session owner's package name.
      *
-     * @return The package name of of the session owner.
+     * @return The package name of the session owner.
      */
     public String getPackageName() {
         if (mPackageName == null) {
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index 33acd0d..fa04293 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -1,6 +1,6 @@
-nchalko@google.com
 quxiangfang@google.com
 shubang@google.com
+hgchen@google.com
 
 # For android remote service
 per-file ITvRemoteServiceInput.aidl = file:/media/lib/tvremote/OWNERS
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index efd9d10..420f4ef 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -27,6 +28,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
+import android.media.AudioDeviceInfo;
+import android.media.AudioFormat.Encoding;
 import android.media.PlaybackParams;
 import android.net.Uri;
 import android.os.Binder;
@@ -59,6 +62,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -2998,6 +3002,16 @@
             return false;
         }
 
+        /**
+         * Override default audio sink from audio policy.
+         *
+         * @param audioType device type of the audio sink to override with.
+         * @param audioAddress device address of the audio sink to override with.
+         * @param samplingRate desired sampling rate. Use default when it's 0.
+         * @param channelMask desired channel mask. Use default when it's
+         *        AudioFormat.CHANNEL_OUT_DEFAULT.
+         * @param format desired format. Use default when it's AudioFormat.ENCODING_DEFAULT.
+         */
         public void overrideAudioSink(int audioType, String audioAddress, int samplingRate,
                 int channelMask, int format) {
             try {
@@ -3007,5 +3021,27 @@
                 throw new RuntimeException(e);
             }
         }
+
+        /**
+         * Override default audio sink from audio policy.
+         *
+         * @param device {@link android.media.AudioDeviceInfo} to use.
+         * @param samplingRate desired sampling rate. Use default when it's 0.
+         * @param channelMask desired channel mask. Use default when it's
+         *        AudioFormat.CHANNEL_OUT_DEFAULT.
+         * @param format desired format. Use default when it's AudioFormat.ENCODING_DEFAULT.
+         */
+        public void overrideAudioSink(@NonNull AudioDeviceInfo device,
+                @IntRange(from = 0) int samplingRate,
+                int channelMask, @Encoding int format) {
+            Objects.requireNonNull(device);
+            try {
+                mInterface.overrideAudioSink(
+                        AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType()),
+                        device.getAddress(), samplingRate, channelMask, format);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
     }
 }
diff --git a/media/java/android/media/tv/tunerresourcemanager/OWNER b/media/java/android/media/tv/tunerresourcemanager/OWNER
index 76b84d9..0eb1c31 100644
--- a/media/java/android/media/tv/tunerresourcemanager/OWNER
+++ b/media/java/android/media/tv/tunerresourcemanager/OWNER
@@ -1,4 +1,3 @@
-amyjojo@google.com
-nchalko@google.com
 quxiangfang@google.com
-shubang@google.com
\ No newline at end of file
+shubang@google.com
+kemiyagi@google.com
\ No newline at end of file
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index d8f48c2..20d711c 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -103,6 +103,7 @@
     private int mDeviceType;
     private String mHostType;
     private boolean mSkipThumbForHost = false;
+    private volatile boolean mHostIsWindows = false;
 
     private MtpServer mServer;
     private MtpStorageManager mManager;
@@ -358,7 +359,7 @@
     }
 
     public void addStorage(StorageVolume storage) {
-        MtpStorage mtpStorage = mManager.addMtpStorage(storage);
+        MtpStorage mtpStorage = mManager.addMtpStorage(storage, () -> mHostIsWindows);
         mStorageMap.put(storage.getPath(), mtpStorage);
         if (mServer != null) {
             mServer.addStorage(mtpStorage);
@@ -413,6 +414,7 @@
         }
         mHostType = "";
         mSkipThumbForHost = false;
+        mHostIsWindows = false;
     }
 
     @VisibleForNative
@@ -736,10 +738,12 @@
                         : MtpConstants.RESPONSE_GENERAL_ERROR);
             case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
                 mHostType = stringValue;
+                Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
+                        + "=" + stringValue);
                 if (stringValue.startsWith("Android/")) {
-                    Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
-                            + "=" + stringValue);
                     mSkipThumbForHost = true;
+                } else if (stringValue.startsWith("Windows/")) {
+                    mHostIsWindows = true;
                 }
                 return MtpConstants.RESPONSE_OK;
         }
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 88c32a3..a3754e90 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -19,6 +19,8 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.storage.StorageVolume;
 
+import java.util.function.Supplier;
+
 /**
  * This class represents a storage unit on an MTP device.
  * Used only for MTP support in USB responder mode.
@@ -33,14 +35,16 @@
     private final boolean mRemovable;
     private final long mMaxFileSize;
     private final String mVolumeName;
+    private final Supplier<Boolean> mIsHostWindows;
 
-    public MtpStorage(StorageVolume volume, int storageId) {
+    public MtpStorage(StorageVolume volume, int storageId, Supplier<Boolean> isHostWindows) {
         mStorageId = storageId;
         mPath = volume.getPath();
         mDescription = volume.getDescription(null);
         mRemovable = volume.isRemovable();
         mMaxFileSize = volume.getMaxFileSize();
         mVolumeName = volume.getMediaStoreVolumeName();
+        mIsHostWindows = isHostWindows;
     }
 
     /**
@@ -93,4 +97,13 @@
     public String getVolumeName() {
         return mVolumeName;
     }
+
+    /**
+     * Returns true if the mtp host of this storage is Windows.
+     *
+     * @return is host Windows
+     */
+    public boolean isHostWindows() {
+        return mIsHostWindows.get();
+    }
 }
diff --git a/media/java/android/mtp/MtpStorageManager.java b/media/java/android/mtp/MtpStorageManager.java
index 0bede0d..e9426cf 100644
--- a/media/java/android/mtp/MtpStorageManager.java
+++ b/media/java/android/mtp/MtpStorageManager.java
@@ -18,7 +18,11 @@
 
 import android.media.MediaFile;
 import android.os.FileObserver;
+import android.os.SystemProperties;
 import android.os.storage.StorageVolume;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -35,6 +39,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Supplier;
 
 /**
  * MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of
@@ -199,7 +204,38 @@
         }
 
         public long getSize() {
-            return mIsDir ? 0 : getPath().toFile().length();
+            return mIsDir ? 0 : maybeApplyTranscodeLengthWorkaround(getPath().toFile().length());
+        }
+
+        private long maybeApplyTranscodeLengthWorkaround(long length) {
+            // Windows truncates transferred files to the size advertised in the object property.
+            if (mStorage.isHostWindows() && isTranscodeMtpEnabled() && isFileTranscodeSupported()) {
+                // If the file supports transcoding, we double the returned size to accommodate
+                // the increase in size from transcoding to AVC. This is the same heuristic
+                // applied in the FUSE daemon (MediaProvider).
+                return length * 2;
+            }
+            return length;
+        }
+
+        private boolean isTranscodeMtpEnabled() {
+            return SystemProperties.getBoolean("sys.fuse.transcode_mtp", false);
+        }
+
+        private boolean isFileTranscodeSupported() {
+            // Check if the file supports transcoding by reading the |st_nlinks| struct stat
+            // field. This will be > 1 if the file supports transcoding. The FUSE daemon
+            // sets the field accordingly to enable the MTP stack workaround some Windows OS
+            // MTP client bug where they ignore the size returned as part of getting the MTP
+            // object, see MtpServer#doGetObject.
+            final Path path = getPath();
+            try {
+                StructStat stat = Os.stat(path.toString());
+                return stat.st_nlink > 1;
+            } catch (ErrnoException e) {
+                Log.w(TAG, "Failed to stat path: " + getPath() + ". Ignoring transcoding.");
+                return false;
+            }
         }
 
         public Path getPath() {
@@ -420,10 +456,12 @@
      * @param volume Storage to add.
      * @return the associated MtpStorage
      */
-    public synchronized MtpStorage addMtpStorage(StorageVolume volume) {
+    public synchronized MtpStorage addMtpStorage(StorageVolume volume,
+                                                 Supplier<Boolean> isHostWindows) {
         int storageId = ((getNextStorageId() & 0x0000FFFF) << 16) + 1;
-        MtpStorage storage = new MtpStorage(volume, storageId);
-        MtpObject root = new MtpObject(storage.getPath(), storageId, storage, null, true);
+        MtpStorage storage = new MtpStorage(volume, storageId, isHostWindows);
+        MtpObject root = new MtpObject(storage.getPath(), storageId, storage, /* parent= */ null,
+                                       /* isDir= */ true);
         mRoots.put(storageId, root);
         return storage;
     }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
new file mode 100644
index 0000000..f23794b
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.mediaframeworktest.unit;
+
+import static org.junit.Assert.assertEquals;
+
+import android.bluetooth.BluetoothProfile;
+import android.media.BluetoothProfileConnectionInfo;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class BluetoothProfileConnectionInfoTest {
+
+    @Test
+    public void testCoverageA2dp() {
+        final boolean supprNoisy = false;
+        final int volume = 42;
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createA2dpInfo(supprNoisy, volume);
+        assertEquals(info.getProfile(), BluetoothProfile.A2DP);
+        assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
+        assertEquals(info.getVolume(), volume);
+    }
+
+    @Test
+    public void testCoverageA2dpSink() {
+        final int volume = 42;
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createA2dpSinkInfo(volume);
+        assertEquals(info.getProfile(), BluetoothProfile.A2DP_SINK);
+        assertEquals(info.getVolume(), volume);
+    }
+
+    @Test
+    public void testCoveragehearingAid() {
+        final boolean supprNoisy = true;
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createHearingAidInfo(supprNoisy);
+        assertEquals(info.getProfile(), BluetoothProfile.HEARING_AID);
+        assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
+    }
+
+    @Test
+    public void testCoverageLeAudio() {
+        final boolean supprNoisy = false;
+        final boolean isLeOutput = true;
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createLeAudioInfo(supprNoisy, isLeOutput);
+        assertEquals(info.getProfile(), BluetoothProfile.LE_AUDIO);
+        assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
+        assertEquals(info.isLeOutput(), isLeOutput);
+    }
+}
+
diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
index fdf6582..eb357f6 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
@@ -159,10 +159,11 @@
                 Log.d(TAG, "sendObjectInfoChanged: " + id);
                 objectsInfoChanged.add(id);
             }
-        }, null);
+        }, /* subdirectories= */ null);
 
-        mainMtpStorage = manager.addMtpStorage(mainStorage);
-        secondaryMtpStorage = manager.addMtpStorage(secondaryStorage);
+        mainMtpStorage = manager.addMtpStorage(mainStorage, /* isHostWindows= */ () -> false);
+        secondaryMtpStorage = manager.addMtpStorage(secondaryStorage,
+                                                    /* isHostWindows= */ () -> false);
     }
 
     @After
diff --git a/media/tests/TunerTest/OWNERS b/media/tests/TunerTest/OWNERS
index 73ea663..7554889 100644
--- a/media/tests/TunerTest/OWNERS
+++ b/media/tests/TunerTest/OWNERS
@@ -1,4 +1,4 @@
-amyjojo@google.com
-nchalko@google.com
 quxiangfang@google.com
 shubang@google.com
+hgchen@google.com
+kemiyagi@google.com
\ No newline at end of file
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 8b35f8d..3fb524d 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,14 +1,23 @@
-jreck@google.com
+jreck@google.com #{LAST_RESORT_SUGGESTION}
 
+# General NDK API reviewers
+per-file libandroid.map.txt = danalbert@google.com, etalvala@google.com, michaelwr@google.com
+per-file libandroid.map.txt = jreck@google.com, zyy@google.com
+
+# Networking
 per-file libandroid_net.map.txt, net.c = set noparent
 per-file libandroid_net.map.txt, net.c = jchalard@google.com, junyulai@google.com
 per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
+
+# Fonts
 per-file system_fonts.cpp = file:/graphics/java/android/graphics/fonts/OWNERS
 
+# Window manager
 per-file native_window_jni.cpp = file:/services/core/java/com/android/server/wm/OWNERS
 per-file native_activity.cpp = file:/services/core/java/com/android/server/wm/OWNERS
 per-file surface_control.cpp = file:/services/core/java/com/android/server/wm/OWNERS
 
+# Graphics
 per-file choreographer.cpp = file:/graphics/java/android/graphics/OWNERS
 per-file hardware_buffer_jni.cpp = file:/graphics/java/android/graphics/OWNERS
 per-file native_window_jni.cpp = file:/graphics/java/android/graphics/OWNERS
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f33e118..2201753 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -300,6 +300,9 @@
     android_res_nquery; # introduced=29
     android_res_nresult; # introduced=29
     android_res_nsend; # introduced=29
+    android_tag_socket_with_uid; # introduced=Tiramisu
+    android_tag_socket; # introduced=Tiramisu
+    android_untag_socket; # introduced=Tiramisu
     AThermal_acquireManager; # introduced=30
     AThermal_releaseManager; # introduced=30
     AThermal_getCurrentThermalStatus; # introduced=30
diff --git a/native/android/libandroid_net.map.txt b/native/android/libandroid_net.map.txt
index a6c1b50..32fd734 100644
--- a/native/android/libandroid_net.map.txt
+++ b/native/android/libandroid_net.map.txt
@@ -18,6 +18,10 @@
     android_getprocnetwork; # llndk
     android_setprocdns; # llndk
     android_getprocdns; # llndk
+    # These functions have been part of the NDK since API 33.
+    android_tag_socket_with_uid; # llndk
+    android_tag_socket;  # llndk
+    android_untag_socket; # llndk
   local:
     *;
 };
diff --git a/native/android/net.c b/native/android/net.c
index e2f36a7..d7c22e1 100644
--- a/native/android/net.c
+++ b/native/android/net.c
@@ -161,3 +161,15 @@
 void android_res_cancel(int nsend_fd) {
     resNetworkCancel(nsend_fd);
 }
+
+int android_tag_socket_with_uid(int sockfd, int tag, uid_t uid) {
+    return tagSocket(sockfd, tag, uid);
+}
+
+int android_tag_socket(int sockfd, int tag) {
+    return tagSocket(sockfd, tag, -1);
+}
+
+int android_untag_socket(int sockfd) {
+    return untagSocket(sockfd);
+}
diff --git a/omapi/OWNERS b/omapi/OWNERS
new file mode 100644
index 0000000..5682fd3
--- /dev/null
+++ b/omapi/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 456592
+
+zachoverflow@google.com
+alisher@google.com
+jackcwyu@google.com
diff --git a/omapi/aidl/vts/functional/config/Android.bp b/omapi/aidl/vts/functional/config/Android.bp
new file mode 100644
index 0000000..7c08257
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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: ["Android-Apache-2.0"],
+}
+
+xsd_config {
+    name: "omapi_uuid_map_config",
+    srcs: ["omapi_uuid_map_config.xsd"],
+    api_dir: "schema",
+    package_name: "omapi.uuid.map.config",
+}
diff --git a/omapi/aidl/vts/functional/config/omapi_uuid_map_config.xsd b/omapi/aidl/vts/functional/config/omapi_uuid_map_config.xsd
new file mode 100644
index 0000000..ffeb7a0
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/omapi_uuid_map_config.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<xs:schema version="2.0"
+           attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+  <xs:element name="ref_do">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="uuid_ref_do" maxOccurs="unbounded" minOccurs="0">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="uids">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element type="xs:short" name="uid" maxOccurs="unbounded" minOccurs="0"/>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+              <xs:element type="xs:string" name="uuid"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+</xs:schema>
diff --git a/omapi/aidl/vts/functional/config/schema/current.txt b/omapi/aidl/vts/functional/config/schema/current.txt
new file mode 100644
index 0000000..c2e930b
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/schema/current.txt
@@ -0,0 +1,30 @@
+// Signature format: 2.0
+package omapi.uuid.map.config {
+
+  public class RefDo {
+    ctor public RefDo();
+    method public java.util.List<omapi.uuid.map.config.RefDo.UuidRefDo> getUuid_ref_do();
+  }
+
+  public static class RefDo.UuidRefDo {
+    ctor public RefDo.UuidRefDo();
+    method public omapi.uuid.map.config.RefDo.UuidRefDo.Uids getUids();
+    method public String getUuid();
+    method public void setUids(omapi.uuid.map.config.RefDo.UuidRefDo.Uids);
+    method public void setUuid(String);
+  }
+
+  public static class RefDo.UuidRefDo.Uids {
+    ctor public RefDo.UuidRefDo.Uids();
+    method public java.util.List<java.lang.Short> getUid();
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static omapi.uuid.map.config.RefDo read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/omapi/aidl/vts/functional/config/schema/last_current.txt b/omapi/aidl/vts/functional/config/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/schema/last_current.txt
diff --git a/omapi/aidl/vts/functional/config/schema/last_removed.txt b/omapi/aidl/vts/functional/config/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/schema/last_removed.txt
diff --git a/apex/media/framework/api/removed.txt b/omapi/aidl/vts/functional/config/schema/removed.txt
similarity index 100%
rename from apex/media/framework/api/removed.txt
rename to omapi/aidl/vts/functional/config/schema/removed.txt
diff --git a/omapi/aidl/vts/functional/omapi/Android.bp b/omapi/aidl/vts/functional/omapi/Android.bp
index c3ab8d1..c41479f 100644
--- a/omapi/aidl/vts/functional/omapi/Android.bp
+++ b/omapi/aidl/vts/functional/omapi/Android.bp
@@ -39,6 +39,11 @@
     static_libs: [
         "VtsHalHidlTargetTestBase",
         "android.se.omapi-V1-ndk",
+        "android.hardware.audio.common.test.utility",
+        "libxml2",
+    ],
+    data: [
+        ":omapi_uuid_map_config",
     ],
     cflags: [
         "-O0",
@@ -51,4 +56,5 @@
         "general-tests",
         "vts",
     ],
+    test_config: "VtsHalOmapiSeServiceV1_TargetTest.xml",
 }
diff --git a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
index 319cb7e..5303651 100644
--- a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
+++ b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
@@ -32,6 +32,7 @@
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
 #include <utils/String16.h>
+#include "utility/ValidateXml.h"
 
 using namespace std;
 using namespace ::testing;
@@ -176,6 +177,25 @@
         return (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str()));
     }
 
+    std::optional<std::string> getUuidMappingFile() {
+        char value[PROPERTY_VALUE_MAX] = {0};
+        int len = property_get("ro.boot.product.hardware.sku", value, "config");
+        std::string uuidMappingConfigFile = UUID_MAPPING_CONFIG_PREFIX
+                + std::string(value, len)
+                + UUID_MAPPING_CONFIG_EXT;
+        std::string uuidMapConfigPath;
+        // Search in predefined folders
+        for (auto path : UUID_MAPPING_CONFIG_PATHS) {
+            uuidMapConfigPath = path + uuidMappingConfigFile;
+            auto confFile = fopen(uuidMapConfigPath.c_str(), "r");
+            if (confFile) {
+                fclose(confFile);
+                return uuidMapConfigPath;
+            }
+        }
+        return std::optional<std::string>();
+    }
+
     void SetUp() override {
         LOG(INFO) << "get OMAPI service with name:" << GetParam();
         ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(GetParam().c_str()));
@@ -300,6 +320,10 @@
 
     std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
         mVSReaders = {};
+
+    std::string UUID_MAPPING_CONFIG_PREFIX = "hal_uuid_map_";
+    std::string UUID_MAPPING_CONFIG_EXT = ".xml";
+    std::string UUID_MAPPING_CONFIG_PATHS[3] = {"/odm/etc/", "/vendor/etc/", "/etc/"};
 };
 
 /** Tests getReaders API */
@@ -600,6 +624,14 @@
     }
 }
 
+TEST_P(OMAPISEServiceHalTest, TestUuidMappingConfig) {
+    constexpr const char* xsd = "/data/local/tmp/omapi_uuid_map_config.xsd";
+    auto uuidMappingFile = getUuidMappingFile();
+    ASSERT_TRUE(uuidMappingFile.has_value()) << "Unable to determine UUID mapping config file path";
+    LOG(INFO) << "UUID Mapping config file: " << uuidMappingFile.value();
+    EXPECT_VALID_XML(uuidMappingFile->c_str(), xsd);
+}
+
 INSTANTIATE_TEST_SUITE_P(PerInstance, OMAPISEServiceHalTest,
                          testing::ValuesIn(::android::getAidlHalInstanceNames(
                              aidl::android::se::omapi::ISecureElementService::descriptor)),
diff --git a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.xml b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.xml
new file mode 100644
index 0000000..3ee0414
--- /dev/null
+++ b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalOmapiSeServiceV1_TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push"
+         value="omapi_uuid_map_config.xsd->/data/local/tmp/omapi_uuid_map_config.xsd" />
+        <option name="push"
+         value="VtsHalOmapiSeServiceV1_TargetTest->/data/local/tmp/VtsHalOmapiSeServiceV1_TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalOmapiSeServiceV1_TargetTest" />
+    </test>
+</configuration>
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 90bb76a..6329565 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -39,7 +39,6 @@
         "src/android/net/TrafficStats.java",
         "src/android/net/UnderlyingNetworkInfo.*",
         "src/android/net/netstats/**/*.*",
-        "src/com/android/server/NetworkManagementSocketTagger.java",
     ],
     path: "src",
     visibility: [
@@ -126,8 +125,13 @@
     name: "framework-connectivity-ethernet-sources",
     srcs: [
         "src/android/net/EthernetManager.java",
+        "src/android/net/EthernetNetworkManagementException.java",
+        "src/android/net/EthernetNetworkManagementException.aidl",
         "src/android/net/EthernetNetworkSpecifier.java",
+        "src/android/net/EthernetNetworkUpdateRequest.java",
+        "src/android/net/EthernetNetworkUpdateRequest.aidl",
         "src/android/net/IEthernetManager.aidl",
+        "src/android/net/IEthernetNetworkManagementListener.aidl",
         "src/android/net/IEthernetServiceListener.aidl",
         "src/android/net/ITetheredInterfaceCallback.aidl",
     ],
@@ -154,10 +158,51 @@
     name: "framework-connectivity-tiramisu-sources",
     srcs: [
         ":framework-connectivity-ethernet-sources",
-        ":framework-connectivity-ipsec-sources",
         ":framework-connectivity-netstats-sources",
+    ],
+    visibility: ["//frameworks/base"],
+}
+
+filegroup {
+    name: "framework-connectivity-tiramisu-updatable-sources",
+    srcs: [
+        ":framework-connectivity-ipsec-sources",
         ":framework-connectivity-nsd-sources",
         ":framework-connectivity-tiramisu-internal-sources",
     ],
-    visibility: ["//frameworks/base"],
+    visibility: [
+        "//frameworks/base",
+        "//packages/modules/Connectivity:__subpackages__",
+    ],
+}
+
+cc_library_shared {
+    name: "libframework-connectivity-tiramisu-jni",
+    min_sdk_version: "30",
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+        // Don't warn about S API usage even with
+        // min_sdk 30: the library is only loaded
+        // on S+ devices
+        "-Wno-unguarded-availability",
+        "-Wthread-safety",
+    ],
+    srcs: [
+        "jni/android_net_TrafficStats.cpp",
+        "jni/onload.cpp",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libnativehelper_compat_libc++",
+    ],
+    stl: "none",
+    apex_available: [
+        "com.android.tethering",
+        // TODO: remove when ConnectivityT moves to APEX.
+        "//apex_available:platform",
+    ],
 }
diff --git a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
new file mode 100644
index 0000000..f3c58b1
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/file_descriptor_jni.h>
+#include <android/multinetwork.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) {
+  int fd = AFileDescriptor_getFd(env, fileDescriptor);
+  if (fd == -1) return -EBADF;
+  return android_tag_socket_with_uid(fd, tag, uid);
+}
+
+static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
+  int fd = AFileDescriptor_getFd(env, fileDescriptor);
+  if (fd == -1) return -EBADF;
+  return android_untag_socket(fd);
+}
+
+static const JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd },
+    { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd },
+};
+
+int register_android_net_TrafficStats(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods));
+}
+
+};  // namespace android
+
diff --git a/packages/ConnectivityT/framework-t/jni/onload.cpp b/packages/ConnectivityT/framework-t/jni/onload.cpp
new file mode 100644
index 0000000..1fb42c6
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/jni/onload.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FrameworkConnectivityJNI"
+
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+int register_android_net_TrafficStats(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+    JNIEnv *env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
+        return JNI_ERR;
+    }
+
+    if (register_android_net_TrafficStats(env) < 0) return JNI_ERR;
+
+    return JNI_VERSION_1_6;
+}
+
+};  // namespace android
+
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
index f684a4d..2b6570a 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
@@ -545,9 +545,18 @@
     }
 
     /**
+     * Collects tagged summary results and sets summary enumeration mode.
+     * @throws RemoteException
+     */
+    void startTaggedSummaryEnumeration() throws RemoteException {
+        mSummary = mSession.getTaggedSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp);
+        mEnumerationIndex = 0;
+    }
+
+    /**
      * Collects history results for uid and resets history enumeration index.
      */
-    void startHistoryEnumeration(int uid, int tag, int state) {
+    void startHistoryUidEnumeration(int uid, int tag, int state) {
         mHistory = null;
         try {
             mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
@@ -562,6 +571,20 @@
     }
 
     /**
+     * Collects history results for network and resets history enumeration index.
+     */
+    void startHistoryDeviceEnumeration() {
+        try {
+            mHistory = mSession.getHistoryIntervalForNetwork(
+                    mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+            mHistory = null;
+        }
+        mEnumerationIndex = 0;
+    }
+
+    /**
      * Starts uid enumeration for current user.
      * @throws RemoteException
      */
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index a316b8a..5ce7e59 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -17,7 +17,11 @@
 package android.app.usage;
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
+import android.Manifest;
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -36,14 +40,12 @@
 import android.net.NetworkStateSnapshot;
 import android.net.NetworkTemplate;
 import android.net.UnderlyingNetworkInfo;
+import android.net.netstats.IUsageCallback;
+import android.net.netstats.NetworkStatsDataMigrationUtils;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
 import android.os.RemoteException;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -54,6 +56,7 @@
 
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.Executor;
 
 /**
  * Provides access to network usage history and statistics. Usage data is collected in
@@ -123,6 +126,14 @@
     private final Context mContext;
     private final INetworkStatsService mService;
 
+    /**
+     * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT}
+     * instead.
+     * @hide
+     */
+    @Deprecated
+    public static final String PREFIX_DEV = "dev";
+
     /** @hide */
     public static final int FLAG_POLL_ON_OPEN = 1 << 0;
     /** @hide */
@@ -130,6 +141,18 @@
     /** @hide */
     public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
 
+    /**
+     * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
+     * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
+     * with NR state as connected. This is a concept added by NetworkStats on top of the telephony
+     * constants for backward compatibility of metrics so this should not be overlapped with any of
+     * the {@code TelephonyManager.NETWORK_TYPE_*} constants.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int NETWORK_TYPE_5G_NSA = -2;
+
     private int mFlags;
 
     /** @hide */
@@ -142,6 +165,25 @@
     }
 
     /** @hide */
+    public INetworkStatsService getBinder() {
+        return mService;
+    }
+
+    /**
+     * Set poll on open flag to indicate the poll is needed before service gets statistics
+     * result. This is default enabled. However, for any non-privileged caller, the poll might
+     * be omitted in case of rate limiting.
+     *
+     * @param pollOnOpen true if poll is needed.
+     * @hide
+     */
+    // The system will ignore any non-default values for non-privileged
+    // processes, so processes that don't hold the appropriate permissions
+    // can make no use of this API.
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK})
     public void setPollOnOpen(boolean pollOnOpen) {
         if (pollOnOpen) {
             mFlags |= FLAG_POLL_ON_OPEN;
@@ -195,9 +237,10 @@
      */
     @NonNull
     @WorkerThread
-    // @SystemApi(client = MODULE_LIBRARIES)
+    @SystemApi(client = MODULE_LIBRARIES)
     public Bucket querySummaryForDevice(@NonNull NetworkTemplate template,
             long startTime, long endTime) {
+        Objects.requireNonNull(template);
         try {
             NetworkStats stats =
                     new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -368,11 +411,12 @@
      * @return Statistics which is described above.
      * @hide
      */
-    @Nullable
-    // @SystemApi(client = MODULE_LIBRARIES)
+    @NonNull
+    @SystemApi(client = MODULE_LIBRARIES)
     @WorkerThread
     public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
             long endTime) throws SecurityException {
+        Objects.requireNonNull(template);
         try {
             NetworkStats result =
                     new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -385,6 +429,77 @@
     }
 
     /**
+     * Query tagged network usage statistics summaries.
+     *
+     * The results will only include tagged traffic made by UIDs belonging to the calling user
+     * profile. The results are aggregated over time, so that all buckets will have the same
+     * start and end timestamps as the passed arguments. Not aggregated over state, uid,
+     * default network, metered, or roaming.
+     * This may take a long time, and apps should avoid calling this on their main thread.
+     *
+     * @param template Template used to match networks. See {@link NetworkTemplate}.
+     * @param startTime Start of period, in milliseconds since the Unix epoch, see
+     *            {@link System#currentTimeMillis}.
+     * @param endTime End of period, in milliseconds since the Unix epoch, see
+     *            {@link System#currentTimeMillis}.
+     * @return Statistics which is described above.
+     * @hide
+     */
+    @NonNull
+    @SystemApi(client = MODULE_LIBRARIES)
+    @WorkerThread
+    public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime,
+            long endTime) throws SecurityException {
+        Objects.requireNonNull(template);
+        try {
+            NetworkStats result =
+                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+            result.startTaggedSummaryEnumeration();
+            return result;
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return null; // To make the compiler happy.
+    }
+
+    /**
+     * Query usage statistics details for networks matching a given {@link NetworkTemplate}.
+     *
+     * Result is not aggregated over time. This means buckets' start and
+     * end timestamps will be between 'startTime' and 'endTime' parameters.
+     * <p>Only includes buckets whose entire time period is included between
+     * startTime and endTime. Doesn't interpolate or return partial buckets.
+     * Since bucket length is in the order of hours, this
+     * method cannot be used to measure data usage on a fine grained time scale.
+     * This may take a long time, and apps should avoid calling this on their main thread.
+     *
+     * @param template Template used to match networks. See {@link NetworkTemplate}.
+     * @param startTime Start of period, in milliseconds since the Unix epoch, see
+     *                  {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period, in milliseconds since the Unix epoch, see
+     *                {@link java.lang.System#currentTimeMillis}.
+     * @return Statistics which is described above.
+     * @hide
+     */
+    @NonNull
+    @SystemApi(client = MODULE_LIBRARIES)
+    @WorkerThread
+    public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
+            long startTime, long endTime) {
+        Objects.requireNonNull(template);
+        try {
+            final NetworkStats result =
+                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+            result.startHistoryDeviceEnumeration();
+            return result;
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+
+        return null; // To make the compiler happy.
+    }
+
+    /**
      * Query network usage statistics details for a given uid.
      * This may take a long time, and apps should avoid calling this on their main thread.
      *
@@ -450,7 +565,8 @@
      * @param endTime End of period. Defined in terms of "Unix time", see
      *            {@link java.lang.System#currentTimeMillis}.
      * @param uid UID of app
-     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
+     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
+     *            across all the tags.
      * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
      *            traffic from all states.
      * @return Statistics object or null if an error happened during statistics collection.
@@ -465,21 +581,52 @@
         return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
     }
 
-    /** @hide */
-    public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
+    /**
+     * Query network usage statistics details for a given template, uid, tag, and state.
+     *
+     * Only usable for uids belonging to calling user. Result is not aggregated over time.
+     * This means buckets' start and end timestamps are going to be between 'startTime' and
+     * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
+     * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
+     * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
+     * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
+     * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
+     * interpolate across partial buckets. Since bucket length is in the order of hours, this
+     * method cannot be used to measure data usage on a fine grained time scale.
+     * This may take a long time, and apps should avoid calling this on their main thread.
+     *
+     * @param template Template used to match networks. See {@link NetworkTemplate}.
+     * @param startTime Start of period, in milliseconds since the Unix epoch, see
+     *                  {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period, in milliseconds since the Unix epoch, see
+     *                {@link java.lang.System#currentTimeMillis}.
+     * @param uid UID of app
+     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
+     *            across all the tags.
+     * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
+     *            traffic from all states.
+     * @return Statistics which is described above.
+     * @hide
+     */
+    @NonNull
+    @SystemApi(client = MODULE_LIBRARIES)
+    @WorkerThread
+    public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
             long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
-
-        NetworkStats result;
+        Objects.requireNonNull(template);
         try {
-            result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-            result.startHistoryEnumeration(uid, tag, state);
+            final NetworkStats result = new NetworkStats(
+                    mContext, template, mFlags, startTime, endTime, mService);
+            result.startHistoryUidEnumeration(uid, tag, state);
+            return result;
         } catch (RemoteException e) {
             Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
                     + " state=" + state, e);
-            return null;
+            e.rethrowFromSystemServer();
         }
 
-        return result;
+        return null; // To make the compiler happy.
     }
 
     /**
@@ -535,26 +682,84 @@
         return result;
     }
 
-    /** @hide */
-    public void registerUsageCallback(NetworkTemplate template, int networkType,
-            long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
-        Objects.requireNonNull(callback, "UsageCallback cannot be null");
-
-        final Looper looper;
-        if (handler == null) {
-            looper = Looper.myLooper();
-        } else {
-            looper = handler.getLooper();
+    /**
+     * Query realtime mobile network usage statistics.
+     *
+     * Return a snapshot of current UID network statistics, as it applies
+     * to the mobile radios of the device. The snapshot will include any
+     * tethering traffic, video calling data usage and count of
+     * network operations set by {@link TrafficStats#incrementOperationCount}
+     * made over a mobile radio.
+     * The snapshot will not include any statistics that cannot be seen by
+     * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+    @NonNull public android.net.NetworkStats getMobileUidStats() {
+        try {
+            return mService.getUidStatsForTransport(TRANSPORT_CELLULAR);
+        } catch (RemoteException e) {
+            if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats");
+            throw e.rethrowFromSystemServer();
         }
+    }
 
-        DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
+    /**
+     * Query realtime Wi-Fi network usage statistics.
+     *
+     * Return a snapshot of current UID network statistics, as it applies
+     * to the Wi-Fi radios of the device. The snapshot will include any
+     * tethering traffic, video calling data usage and count of
+     * network operations set by {@link TrafficStats#incrementOperationCount}
+     * made over a Wi-Fi radio.
+     * The snapshot will not include any statistics that cannot be seen by
+     * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+    @NonNull public android.net.NetworkStats getWifiUidStats() {
+        try {
+            return mService.getUidStatsForTransport(TRANSPORT_WIFI);
+        } catch (RemoteException e) {
+            if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats");
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Registers to receive notifications about data usage on specified networks.
+     *
+     * <p>The callbacks will continue to be called as long as the process is alive or
+     * {@link #unregisterUsageCallback} is called.
+     *
+     * @param template Template used to match networks. See {@link NetworkTemplate}.
+     * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower
+     *                       than 2MiB will be clamped for non-privileged callers.
+     * @param executor The executor on which callback will be invoked. The provided {@link Executor}
+     *                 must run callback sequentially, otherwise the order of callbacks cannot be
+     *                 guaranteed.
+     * @param callback The {@link UsageCallback} that the system will call when data usage
+     *                 has exceeded the specified threshold.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
+            @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
+        Objects.requireNonNull(template, "NetworkTemplate cannot be null");
+        Objects.requireNonNull(callback, "UsageCallback cannot be null");
+        Objects.requireNonNull(executor, "Executor cannot be null");
+
+        final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
                 template, thresholdBytes);
         try {
-            CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
-                    template.getSubscriberId(), callback);
+            final UsageCallbackWrapper callbackWrapper =
+                    new UsageCallbackWrapper(executor, callback);
             callback.request = mService.registerUsageCallback(
-                    mContext.getOpPackageName(), request, new Messenger(callbackHandler),
-                    new Binder());
+                    mContext.getOpPackageName(), request, callbackWrapper);
             if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
 
             if (callback.request == null) {
@@ -607,12 +812,15 @@
         NetworkTemplate template = createTemplate(networkType, subscriberId);
         if (DBG) {
             Log.d(TAG, "registerUsageCallback called with: {"
-                + " networkType=" + networkType
-                + " subscriberId=" + subscriberId
-                + " thresholdBytes=" + thresholdBytes
-                + " }");
+                    + " networkType=" + networkType
+                    + " subscriberId=" + subscriberId
+                    + " thresholdBytes=" + thresholdBytes
+                    + " }");
         }
-        registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
+
+        final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r);
+
+        registerUsageCallback(template, thresholdBytes, executor, callback);
     }
 
     /**
@@ -637,6 +845,26 @@
      * Base class for usage callbacks. Should be extended by applications wanting notifications.
      */
     public static abstract class UsageCallback {
+        /**
+         * Called when data usage has reached the given threshold.
+         *
+         * Called by {@code NetworkStatsService} when the registered threshold is reached.
+         * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system
+         * will not call {@link #onThresholdReached(int, String)}.
+         *
+         * @param template The {@link NetworkTemplate} that associated with this callback.
+         * @hide
+         */
+        @SystemApi(client = MODULE_LIBRARIES)
+        public void onThresholdReached(@NonNull NetworkTemplate template) {
+            // Backward compatibility for those who didn't override this function.
+            final int networkType = networkTypeForTemplate(template);
+            if (networkType != ConnectivityManager.TYPE_NONE) {
+                final String subscriberId = template.getSubscriberIds().isEmpty() ? null
+                        : template.getSubscriberIds().iterator().next();
+                onThresholdReached(networkType, subscriberId);
+            }
+        }
 
         /**
          * Called when data usage has reached the given threshold.
@@ -647,6 +875,25 @@
          * @hide used for internal bookkeeping
          */
         private DataUsageRequest request;
+
+        /**
+         * Get network type from a template if feasible.
+         *
+         * @param template the target {@link NetworkTemplate}.
+         * @return legacy network type, only supports for the types which is already supported in
+         *         {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}.
+         *         {@link ConnectivityManager#TYPE_NONE} for other types.
+         */
+        private static int networkTypeForTemplate(@NonNull NetworkTemplate template) {
+            switch (template.getMatchRule()) {
+                case NetworkTemplate.MATCH_MOBILE:
+                    return ConnectivityManager.TYPE_MOBILE;
+                case NetworkTemplate.MATCH_WIFI:
+                    return ConnectivityManager.TYPE_WIFI;
+                default:
+                    return ConnectivityManager.TYPE_NONE;
+            }
+        }
     }
 
     /**
@@ -765,43 +1012,159 @@
         }
     }
 
-    private static class CallbackHandler extends Handler {
-        private final int mNetworkType;
-        private final String mSubscriberId;
-        private UsageCallback mCallback;
+    private static class UsageCallbackWrapper extends IUsageCallback.Stub {
+        // Null if unregistered.
+        private volatile UsageCallback mCallback;
 
-        CallbackHandler(Looper looper, int networkType, String subscriberId,
-                UsageCallback callback) {
-            super(looper);
-            mNetworkType = networkType;
-            mSubscriberId = subscriberId;
+        private final Executor mExecutor;
+
+        UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) {
             mCallback = callback;
+            mExecutor = executor;
         }
 
         @Override
-        public void handleMessage(Message message) {
-            DataUsageRequest request =
-                    (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
-
-            switch (message.what) {
-                case CALLBACK_LIMIT_REACHED: {
-                    if (mCallback != null) {
-                        mCallback.onThresholdReached(mNetworkType, mSubscriberId);
-                    } else {
-                        Log.e(TAG, "limit reached with released callback for " + request);
-                    }
-                    break;
-                }
-                case CALLBACK_RELEASED: {
-                    if (DBG) Log.d(TAG, "callback released for " + request);
-                    mCallback = null;
-                    break;
-                }
+        public void onThresholdReached(DataUsageRequest request) {
+            // Copy it to a local variable in case mCallback changed inside the if condition.
+            final UsageCallback callback = mCallback;
+            if (callback != null) {
+                mExecutor.execute(() -> callback.onThresholdReached(request.template));
+            } else {
+                Log.e(TAG, "onThresholdReached with released callback for " + request);
             }
         }
 
-        private static Object getObject(Message msg, String key) {
-            return msg.getData().getParcelable(key);
+        @Override
+        public void onCallbackReleased(DataUsageRequest request) {
+            if (DBG) Log.d(TAG, "callback released for " + request);
+            mCallback = null;
+        }
+    }
+
+    /**
+     * Mark given UID as being in foreground for stats purposes.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK})
+    public void setUidForeground(int uid, boolean uidForeground) {
+        try {
+            mService.setUidForeground(uid, uidForeground);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Set default value of global alert bytes, the value will be clamped to [128kB, 2MB].
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            Manifest.permission.NETWORK_STACK})
+    public void setDefaultGlobalAlert(long alertBytes) {
+        try {
+            // TODO: Sync internal naming with the API surface.
+            mService.advisePersistThreshold(alertBytes);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Force update of statistics.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK})
+    public void forceUpdate() {
+        try {
+            mService.forceUpdate();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Set the warning and limit to all registered custom network stats providers.
+     * Note that invocation of any interface will be sent to all providers.
+     *
+     * Asynchronicity notes : because traffic may be happening on the device at the same time, it
+     * doesn't make sense to wait for the warning and limit to be set – a caller still wouldn't
+     * know when exactly it was effective. All that can matter is that it's done quickly. Also,
+     * this method can't fail, so there is no status to return. All providers will see the new
+     * values soon.
+     * As such, this method returns immediately and sends the warning and limit to all providers
+     * as soon as possible through a one-way binder call.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK})
+    public void setStatsProviderWarningAndLimitAsync(@NonNull String iface, long warning,
+            long limit) {
+        try {
+            mService.setStatsProviderWarningAndLimitAsync(iface, warning, limit);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get a RAT type representative of a group of RAT types for network statistics.
+     *
+     * Collapse the given Radio Access Technology (RAT) type into a bucket that
+     * is representative of the original RAT type for network statistics. The
+     * mapping mostly corresponds to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}
+     * but with adaptations specific to the virtual types introduced by
+     * networks stats.
+     *
+     * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static int getCollapsedRatType(int ratType) {
+        switch (ratType) {
+            case TelephonyManager.NETWORK_TYPE_GPRS:
+            case TelephonyManager.NETWORK_TYPE_GSM:
+            case TelephonyManager.NETWORK_TYPE_EDGE:
+            case TelephonyManager.NETWORK_TYPE_IDEN:
+            case TelephonyManager.NETWORK_TYPE_CDMA:
+            case TelephonyManager.NETWORK_TYPE_1xRTT:
+                return TelephonyManager.NETWORK_TYPE_GSM;
+            case TelephonyManager.NETWORK_TYPE_EVDO_0:
+            case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            case TelephonyManager.NETWORK_TYPE_EVDO_B:
+            case TelephonyManager.NETWORK_TYPE_EHRPD:
+            case TelephonyManager.NETWORK_TYPE_UMTS:
+            case TelephonyManager.NETWORK_TYPE_HSDPA:
+            case TelephonyManager.NETWORK_TYPE_HSUPA:
+            case TelephonyManager.NETWORK_TYPE_HSPA:
+            case TelephonyManager.NETWORK_TYPE_HSPAP:
+            case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+                return TelephonyManager.NETWORK_TYPE_UMTS;
+            case TelephonyManager.NETWORK_TYPE_LTE:
+            case TelephonyManager.NETWORK_TYPE_IWLAN:
+                return TelephonyManager.NETWORK_TYPE_LTE;
+            case TelephonyManager.NETWORK_TYPE_NR:
+                return TelephonyManager.NETWORK_TYPE_NR;
+            // Virtual RAT type for 5G NSA mode, see
+            // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
+            case NetworkStatsManager.NETWORK_TYPE_5G_NSA:
+                return NetworkStatsManager.NETWORK_TYPE_5G_NSA;
+            default:
+                return TelephonyManager.NETWORK_TYPE_UNKNOWN;
         }
     }
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
index 630f902e..577ac54 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
@@ -48,5 +48,14 @@
                     return new NsdManager(context, service);
                 }
         );
+
+        SystemServiceRegistry.registerContextAwareService(
+                Context.IPSEC_SERVICE,
+                IpSecManager.class,
+                (context, serviceBinder) -> {
+                    IIpSecService service = IIpSecService.Stub.asInterface(serviceBinder);
+                    return new IpSecManager(context, service);
+                }
+        );
     }
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index ece54df..72243f9 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -16,28 +16,34 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
 import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.RemoteException;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.function.BiConsumer;
 
 /**
- * A class representing the IP configuration of the Ethernet network.
+ * A class that manages and configures Ethernet interfaces.
  *
  * @hide
  */
@@ -52,11 +58,13 @@
     private final IEthernetServiceListener.Stub mServiceListener =
             new IEthernetServiceListener.Stub() {
                 @Override
-                public void onAvailabilityChanged(String iface, boolean isAvailable) {
+                public void onInterfaceStateChanged(String iface, int state, int role,
+                        IpConfiguration configuration) {
                     synchronized (mListeners) {
                         for (ListenerInfo li : mListeners) {
                             li.executor.execute(() ->
-                                    li.listener.onAvailabilityChanged(iface, isAvailable));
+                                    li.listener.onInterfaceStateChanged(iface, state, role,
+                                            configuration));
                         }
                     }
                 }
@@ -66,19 +74,93 @@
         @NonNull
         public final Executor executor;
         @NonNull
-        public final Listener listener;
+        public final InterfaceStateListener listener;
 
-        private ListenerInfo(@NonNull Executor executor, @NonNull Listener listener) {
+        private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) {
             this.executor = executor;
             this.listener = listener;
         }
     }
 
     /**
-     * A listener interface to receive notification on changes in Ethernet.
+     * The interface is absent.
      * @hide
      */
-    public interface Listener {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int STATE_ABSENT = 0;
+
+    /**
+     * The interface is present but link is down.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int STATE_LINK_DOWN = 1;
+
+    /**
+     * The interface is present and link is up.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int STATE_LINK_UP = 2;
+
+    /** @hide */
+    @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InterfaceState {}
+
+    /**
+     * The interface currently does not have any specific role.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int ROLE_NONE = 0;
+
+    /**
+     * The interface is in client mode (e.g., connected to the Internet).
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int ROLE_CLIENT = 1;
+
+    /**
+     * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static final int ROLE_SERVER = 2;
+
+    /** @hide */
+    @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Role {}
+
+    /**
+     * A listener that receives notifications about the state of Ethernet interfaces on the system.
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public interface InterfaceStateListener {
+        /**
+         * Called when an Ethernet interface changes state.
+         *
+         * @param iface the name of the interface.
+         * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
+         *              interface was removed.
+         * @param role whether the interface is in client mode or server mode.
+         * @param configuration the current IP configuration of the interface.
+         * @hide
+         */
+        @SystemApi(client = MODULE_LIBRARIES)
+        void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
+                @Role int role, @Nullable IpConfiguration configuration);
+    }
+
+    /**
+     * A listener interface to receive notification on changes in Ethernet.
+     * This has never been a supported API. Use {@link InterfaceStateListener} instead.
+     * @hide
+     */
+    public interface Listener extends InterfaceStateListener {
         /**
          * Called when Ethernet port's availability is changed.
          * @param iface Ethernet interface name
@@ -87,6 +169,13 @@
          */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         void onAvailabilityChanged(String iface, boolean isAvailable);
+
+        /** Default implementation for backwards compatibility. Only calls the legacy listener. */
+        default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
+                @Role int role, @Nullable IpConfiguration configuration) {
+            onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
+        }
+
     }
 
     /**
@@ -119,7 +208,7 @@
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void setConfiguration(String iface, IpConfiguration config) {
+    public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
         try {
             mService.setConfiguration(iface, config);
         } catch (RemoteException e) {
@@ -153,9 +242,8 @@
 
     /**
      * Adds a listener.
+     * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
      *
-     * Consider using {@link #addListener(Listener, Executor)} instead: this method uses a default
-     * executor that may have higher latency than a provided executor.
      * @param listener A {@link Listener} to add.
      * @throws IllegalArgumentException If the listener is null.
      * @hide
@@ -167,6 +255,8 @@
 
     /**
      * Adds a listener.
+     * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
+     *
      * @param listener A {@link Listener} to add.
      * @param executor Executor to run callbacks on.
      * @throws IllegalArgumentException If the listener or executor is null.
@@ -174,6 +264,28 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
+        addInterfaceStateListener(executor, listener);
+    }
+
+    /**
+     * Listen to changes in the state of Ethernet interfaces.
+     *
+     * Adds a listener to receive notification for any state change of all existing Ethernet
+     * interfaces.
+     * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
+     * existing interfaces upon adding a listener. The same method will be called on the
+     * listener every time any of the interface changes state. In particular, if an
+     * interface is removed, it will be called with state {@link #STATE_ABSENT}.
+     * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
+     *
+     * @param executor Executor to run callbacks on.
+     * @param listener A {@link Listener} to add.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    @SystemApi(client = MODULE_LIBRARIES)
+    public void addInterfaceStateListener(@NonNull Executor executor,
+            @NonNull InterfaceStateListener listener) {
         if (listener == null || executor == null) {
             throw new NullPointerException("listener and executor must not be null");
         }
@@ -204,15 +316,13 @@
 
     /**
      * Removes a listener.
+     *
      * @param listener A {@link Listener} to remove.
-     * @throws IllegalArgumentException If the listener is null.
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void removeListener(@NonNull Listener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
+    @SystemApi(client = MODULE_LIBRARIES)
+    public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
+        Objects.requireNonNull(listener);
         synchronized (mListeners) {
             mListeners.removeIf(l -> l.listener == listener);
             if (mListeners.isEmpty()) {
@@ -226,12 +336,26 @@
     }
 
     /**
+     * Removes a listener.
+     * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
+     * @param listener A {@link Listener} to remove.
+     * @hide
+     */
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    public void removeListener(@NonNull Listener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        removeInterfaceStateListener(listener);
+    }
+
+    /**
      * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
      * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
      * already present on the system.
      * @hide
      */
-    @TestApi
+    @SystemApi(client = MODULE_LIBRARIES)
     public void setIncludeTestInterfaces(boolean include) {
         try {
             mService.setIncludeTestInterfaces(include);
@@ -320,15 +444,15 @@
     }
 
     private static final class InternalNetworkManagementListener
-            extends IInternalNetworkManagementListener.Stub {
+            extends IEthernetNetworkManagementListener.Stub {
         @NonNull
         private final Executor mExecutor;
         @NonNull
-        private final BiConsumer<Network, InternalNetworkManagementException> mListener;
+        private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
 
         InternalNetworkManagementListener(
                 @NonNull final Executor executor,
-                @NonNull final BiConsumer<Network, InternalNetworkManagementException> listener) {
+                @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) {
             Objects.requireNonNull(executor, "Pass a non-null executor");
             Objects.requireNonNull(listener, "Pass a non-null listener");
             mExecutor = executor;
@@ -338,14 +462,14 @@
         @Override
         public void onComplete(
                 @Nullable final Network network,
-                @Nullable final InternalNetworkManagementException e) {
+                @Nullable final EthernetNetworkManagementException e) {
             mExecutor.execute(() -> mListener.accept(network, e));
         }
     }
 
     private InternalNetworkManagementListener getInternalNetworkManagementListener(
             @Nullable final Executor executor,
-            @Nullable final BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) {
         if (null != listener) {
             Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
         }
@@ -358,11 +482,43 @@
         return proxy;
     }
 
-    private void updateConfiguration(
+    /**
+     * Updates the configuration of an automotive device's ethernet network.
+     *
+     * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
+     * configuration for this network.
+     * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
+     * this network to put inside the {@code request}.
+     * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
+     * object for this network to put inside the {@code request}.
+     *
+     * If non-null, the listener will be called exactly once after this is called, unless
+     * a synchronous exception was thrown.
+     *
+     * @param iface the name of the interface to act upon.
+     * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
+     *                {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
+     * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
+     * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+     * @throws SecurityException if the process doesn't hold
+     *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
+     * @throws UnsupportedOperationException if called on a non-automotive device or on an
+     *                                       unsupported interface.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK,
+            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
+    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
+    public void updateConfiguration(
             @NonNull String iface,
-            @NonNull InternalNetworkUpdateRequest request,
+            @NonNull EthernetNetworkUpdateRequest request,
             @Nullable @CallbackExecutor Executor executor,
-            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+        Objects.requireNonNull(iface, "iface must be non-null");
+        Objects.requireNonNull(request, "request must be non-null");
         final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
                 executor, listener);
         try {
@@ -372,10 +528,34 @@
         }
     }
 
-    private void connectNetwork(
+    /**
+     * Set an ethernet network's link state up.
+     *
+     * When the link is successfully turned up, the listener will be called with the resulting
+     * network. If any error or unexpected condition happens while the system tries to turn the
+     * interface up, the listener will be called with an appropriate exception.
+     * The listener is guaranteed to be called exactly once for each call to this method, but this
+     * may take an unbounded amount of time depending on the actual network conditions.
+     *
+     * @param iface the name of the interface to act upon.
+     * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
+     * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+     * @throws SecurityException if the process doesn't hold
+     *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
+     * @throws UnsupportedOperationException if called on a non-automotive device.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK,
+            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
+    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
+    public void connectNetwork(
             @NonNull String iface,
             @Nullable @CallbackExecutor Executor executor,
-            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+        Objects.requireNonNull(iface, "iface must be non-null");
         final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
                 executor, listener);
         try {
@@ -385,10 +565,33 @@
         }
     }
 
-    private void disconnectNetwork(
+    /**
+     * Set an ethernet network's link state down.
+     *
+     * When the link is successfully turned down, the listener will be called with the network that
+     * was torn down, if any. If any error or unexpected condition happens while the system tries to
+     * turn the interface down, the listener will be called with an appropriate exception.
+     * The listener is guaranteed to be called exactly once for each call to this method.
+     *
+     * @param iface the name of the interface to act upon.
+     * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
+     * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+     * @throws SecurityException if the process doesn't hold
+     *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
+     * @throws UnsupportedOperationException if called on a non-automotive device.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+            android.Manifest.permission.NETWORK_STACK,
+            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
+    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
+    public void disconnectNetwork(
             @NonNull String iface,
             @Nullable @CallbackExecutor Executor executor,
-            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+        Objects.requireNonNull(iface, "iface must be non-null");
         final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
                 executor, listener);
         try {
diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
similarity index 92%
rename from core/java/android/net/InternalNetworkManagementException.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
index dcce706..adf9e5a 100644
--- a/core/java/android/net/InternalNetworkManagementException.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
@@ -16,4 +16,4 @@
 
  package android.net;
 
- parcelable InternalNetworkManagementException;
\ No newline at end of file
+ parcelable EthernetNetworkManagementException;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
new file mode 100644
index 0000000..a69cc55
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
@@ -0,0 +1,73 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** @hide */
+@SystemApi
+public final class EthernetNetworkManagementException
+        extends RuntimeException implements Parcelable {
+
+    /* @hide */
+    public EthernetNetworkManagementException(@NonNull final String errorMessage) {
+        super(errorMessage);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getMessage());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null || getClass() != obj.getClass()) return false;
+        final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj;
+
+        return Objects.equals(getMessage(), that.getMessage());
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(getMessage());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR =
+            new Parcelable.Creator<EthernetNetworkManagementException>() {
+                @Override
+                public EthernetNetworkManagementException[] newArray(int size) {
+                    return new EthernetNetworkManagementException[size];
+                }
+
+                @Override
+                public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) {
+                    return new EthernetNetworkManagementException(source.readString());
+                }
+            };
+}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
index 62c5761..e4d6e24 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
@@ -18,22 +18,17 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
-import com.android.internal.util.Preconditions;
-
 import java.util.Objects;
 
 /**
  * A {@link NetworkSpecifier} used to identify ethernet interfaces.
  *
  * @see EthernetManager
- * @hide
  */
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
 public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable {
 
     /**
@@ -47,7 +42,9 @@
      * @param interfaceName Name of the ethernet interface the specifier refers to.
      */
     public EthernetNetworkSpecifier(@NonNull String interfaceName) {
-        Preconditions.checkStringNotEmpty(interfaceName);
+        if (TextUtils.isEmpty(interfaceName)) {
+            throw new IllegalArgumentException();
+        }
         mInterfaceName = interfaceName;
     }
 
@@ -61,6 +58,7 @@
         return mInterfaceName;
     }
 
+    /** @hide */
     @Override
     public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
         return equals(other);
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
similarity index 93%
rename from core/java/android/net/InternalNetworkUpdateRequest.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
index da00cb9..debc348 100644
--- a/core/java/android/net/InternalNetworkUpdateRequest.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
@@ -16,4 +16,4 @@
 
  package android.net;
 
- parcelable InternalNetworkUpdateRequest;
\ No newline at end of file
+ parcelable EthernetNetworkUpdateRequest;
\ No newline at end of file
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
similarity index 68%
rename from core/java/android/net/InternalNetworkUpdateRequest.java
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
index 6f09383..e879e40 100644
--- a/core/java/android/net/InternalNetworkUpdateRequest.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
@@ -17,17 +17,18 @@
 package android.net;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import java.util.Objects;
 
 /** @hide */
-public final class InternalNetworkUpdateRequest implements Parcelable {
+@SystemApi
+public final class EthernetNetworkUpdateRequest implements Parcelable {
     @NonNull
     private final StaticIpConfiguration mIpConfig;
-    @Nullable
+    @NonNull
     private final NetworkCapabilities mNetworkCapabilities;
 
     @NonNull
@@ -37,23 +38,18 @@
 
     @NonNull
     public NetworkCapabilities getNetworkCapabilities() {
-        return mNetworkCapabilities == null
-                ? null : new NetworkCapabilities(mNetworkCapabilities);
+        return new NetworkCapabilities(mNetworkCapabilities);
     }
 
-    /** @hide */
-    public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
-            @Nullable final NetworkCapabilities networkCapabilities) {
+    public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
+            @NonNull final NetworkCapabilities networkCapabilities) {
         Objects.requireNonNull(ipConfig);
+        Objects.requireNonNull(networkCapabilities);
         mIpConfig = new StaticIpConfiguration(ipConfig);
-        if (null == networkCapabilities) {
-            mNetworkCapabilities = null;
-        } else {
-            mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
-        }
+        mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
     }
 
-    private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
+    private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
         Objects.requireNonNull(source);
         mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
         mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
@@ -61,7 +57,7 @@
 
     @Override
     public String toString() {
-        return "InternalNetworkUpdateRequest{"
+        return "EthernetNetworkUpdateRequest{"
                 + "mIpConfig=" + mIpConfig
                 + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
     }
@@ -70,7 +66,7 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-        InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o;
+        EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
 
         return Objects.equals(that.getIpConfig(), mIpConfig)
                 && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
@@ -93,16 +89,16 @@
     }
 
     @NonNull
-    public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR =
-            new Parcelable.Creator<InternalNetworkUpdateRequest>() {
+    public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR =
+            new Parcelable.Creator<EthernetNetworkUpdateRequest>() {
                 @Override
-                public InternalNetworkUpdateRequest[] newArray(int size) {
-                    return new InternalNetworkUpdateRequest[size];
+                public EthernetNetworkUpdateRequest[] newArray(int size) {
+                    return new EthernetNetworkUpdateRequest[size];
                 }
 
                 @Override
-                public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
-                    return new InternalNetworkUpdateRequest(source);
+                public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
+                    return new EthernetNetworkUpdateRequest(source);
                 }
             };
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
index e688bea..544d02b 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
@@ -18,8 +18,8 @@
 
 import android.net.IpConfiguration;
 import android.net.IEthernetServiceListener;
-import android.net.IInternalNetworkManagementListener;
-import android.net.InternalNetworkUpdateRequest;
+import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkUpdateRequest;
 import android.net.ITetheredInterfaceCallback;
 
 /**
@@ -38,8 +38,8 @@
     void setIncludeTestInterfaces(boolean include);
     void requestTetheredInterface(in ITetheredInterfaceCallback callback);
     void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
-    void updateConfiguration(String iface, in InternalNetworkUpdateRequest request,
-        in IInternalNetworkManagementListener listener);
-    void connectNetwork(String iface, in IInternalNetworkManagementListener listener);
-    void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener);
+    void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
+        in IEthernetNetworkManagementListener listener);
+    void connectNetwork(String iface, in IEthernetNetworkManagementListener listener);
+    void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener);
 }
diff --git a/core/java/android/net/IInternalNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
similarity index 80%
rename from core/java/android/net/IInternalNetworkManagementListener.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
index 69cde3b..93edccf 100644
--- a/core/java/android/net/IInternalNetworkManagementListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
@@ -16,10 +16,10 @@
 
 package android.net;
 
-import android.net.InternalNetworkManagementException;
+import android.net.EthernetNetworkManagementException;
 import android.net.Network;
 
 /** @hide */
-oneway interface IInternalNetworkManagementListener {
-    void onComplete(in Network network, in InternalNetworkManagementException exception);
+oneway interface IEthernetNetworkManagementListener {
+    void onComplete(in Network network, in EthernetNetworkManagementException exception);
 }
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
index 782fa19..6d2ba03 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
@@ -16,8 +16,11 @@
 
 package android.net;
 
+import android.net.IpConfiguration;
+
 /** @hide */
 oneway interface IEthernetServiceListener
 {
-    void onAvailabilityChanged(String iface, boolean isAvailable);
+    void onInterfaceStateChanged(String iface, int state, int role,
+            in IpConfiguration configuration);
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
index 12937b5..efe626d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
@@ -24,6 +24,7 @@
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.UnderlyingNetworkInfo;
+import android.net.netstats.IUsageCallback;
 import android.net.netstats.provider.INetworkStatsProvider;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.os.IBinder;
@@ -49,14 +50,8 @@
     @UnsupportedAppUsage
     NetworkStats getDataLayerSnapshotForUid(int uid);
 
-    /** Get a detailed snapshot of stats since boot for all UIDs.
-    *
-    * <p>Results will not always be limited to stats on requiredIfaces when specified: stats for
-    * interfaces stacked on the specified interfaces, or for interfaces on which the specified
-    * interfaces are stacked on, will also be included.
-    * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}.
-    */
-    NetworkStats getDetailedUidStats(in String[] requiredIfaces);
+    /** Get the transport NetworkStats for all UIDs since boot. */
+    NetworkStats getUidStatsForTransport(int transport);
 
     /** Return set of any ifaces associated with mobile networks since boot. */
     @UnsupportedAppUsage
@@ -77,7 +72,7 @@
 
     /** Registers a callback on data usage. */
     DataUsageRequest registerUsageCallback(String callingPackage,
-            in DataUsageRequest request, in Messenger messenger, in IBinder binder);
+            in DataUsageRequest request, in IUsageCallback callback);
 
     /** Unregisters a callback on data usage. */
     void unregisterUsageRequest(in DataUsageRequest request);
@@ -94,4 +89,16 @@
     /** Registers a network stats provider */
     INetworkStatsProviderCallback registerNetworkStatsProvider(String tag,
             in INetworkStatsProvider provider);
+
+    /** Mark given UID as being in foreground for stats purposes. */
+    void setUidForeground(int uid, boolean uidForeground);
+
+    /** Advise persistence threshold; may be overridden internally. */
+    void advisePersistThreshold(long thresholdBytes);
+
+    /**
+     * Set the warning and limit to all registered custom network stats providers.
+     * Note that invocation of any interface will be sent to all providers.
+     */
+     void setStatsProviderWarningAndLimitAsync(String iface, long warning, long limit);
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
index dfedf66..ab70be8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
@@ -32,6 +32,11 @@
     /** Return historical network layer stats for traffic that matches template. */
     @UnsupportedAppUsage
     NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
+    /**
+     * Return historical network layer stats for traffic that matches template, start and end
+     * timestamp.
+     */
+    NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end);
 
     /**
      * Return network layer usage summary per UID for traffic that matches template.
@@ -46,6 +51,10 @@
      */
     @UnsupportedAppUsage
     NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+
+    /** Return network layer usage summary per UID for tagged traffic that matches template. */
+    NetworkStats getTaggedSummaryForAllUid(in NetworkTemplate template, long start, long end);
+
     /** Return historical network layer stats for specific UID traffic that matches template. */
     @UnsupportedAppUsage
     NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
index a84e7a9..10a22ac 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
@@ -343,7 +343,7 @@
         // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
         // the resource are not allowed.
         final String[] resourceAlgos = systemResources.getStringArray(
-                com.android.internal.R.array.config_optionalIpSecAlgorithms);
+                android.R.array.config_optionalIpSecAlgorithms);
         for (String str : resourceAlgos) {
             if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
                 // This error should be caught by CTS and never be thrown to API callers
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
index 0d15dff..9cb0947 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
@@ -17,6 +17,7 @@
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -25,8 +26,8 @@
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.net.annotations.PolicyDirection;
 import android.os.Binder;
+import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
@@ -41,6 +42,8 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.Socket;
@@ -58,7 +61,7 @@
  *     Internet Protocol</a>
  */
 @SystemService(Context.IPSEC_SERVICE)
-public final class IpSecManager {
+public class IpSecManager {
     private static final String TAG = "IpSecManager";
 
     /**
@@ -88,6 +91,11 @@
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int DIRECTION_FWD = 2;
 
+    /** @hide */
+    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PolicyDirection {}
+
     /**
      * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
      *
@@ -981,6 +989,29 @@
     }
 
     /**
+     * @hide
+     */
+    public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder,
+            String callingPackage) {
+        try {
+            return mService.createTransform(config, binder, callingPackage);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void deleteTransform(int resourceId) {
+        try {
+            mService.deleteTransform(resourceId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Construct an instance of IpSecManager within an application context.
      *
      * @param context the application context for this manager
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
index 36199a0..68ae5de 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
@@ -26,9 +26,6 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
 import android.util.Log;
 
@@ -93,16 +90,9 @@
         mResourceId = INVALID_RESOURCE_ID;
     }
 
-    private IIpSecService getIpSecService() {
-        IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
-        if (b == null) {
-            throw new RemoteException("Failed to connect to IpSecService")
-                    .rethrowAsRuntimeException();
-        }
-
-        return IIpSecService.Stub.asInterface(b);
+    private IpSecManager getIpSecManager(Context context) {
+        return context.getSystemService(IpSecManager.class);
     }
-
     /**
      * Checks the result status and throws an appropriate exception if the status is not Status.OK.
      */
@@ -130,8 +120,7 @@
                     IpSecManager.SpiUnavailableException {
         synchronized (this) {
             try {
-                IIpSecService svc = getIpSecService();
-                IpSecTransformResponse result = svc.createTransform(
+                IpSecTransformResponse result = getIpSecManager(mContext).createTransform(
                         mConfig, new Binder(), mContext.getOpPackageName());
                 int status = result.status;
                 checkResultStatus(status);
@@ -140,8 +129,6 @@
                 mCloseGuard.open("build");
             } catch (ServiceSpecificException e) {
                 throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
-            } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
             }
         }
 
@@ -177,10 +164,7 @@
             return;
         }
         try {
-            IIpSecService svc = getIpSecService();
-            svc.deleteTransform(mResourceId);
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
+            getIpSecManager(mContext).deleteTransform(mResourceId);
         } catch (Exception e) {
             // On close we swallow all random exceptions since failure to close is not
             // actionable by the user.
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
index 8f1115e..56faa52 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
@@ -16,18 +16,29 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.net.wifi.WifiInfo;
 import android.service.NetworkIdentityProto;
-import android.telephony.Annotation.NetworkType;
+import android.telephony.TelephonyManager;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.net.module.util.CollectionUtils;
 import com.android.net.module.util.NetworkCapabilitiesUtils;
 import com.android.net.module.util.NetworkIdentityUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Objects;
 
@@ -37,11 +48,24 @@
  *
  * @hide
  */
-public class NetworkIdentity implements Comparable<NetworkIdentity> {
+@SystemApi(client = MODULE_LIBRARIES)
+public class NetworkIdentity {
     private static final String TAG = "NetworkIdentity";
 
+    /** @hide */
+    // TODO: Remove this after migrating all callers to use
+    //  {@link NetworkTemplate#NETWORK_TYPE_ALL} instead.
     public static final int SUBTYPE_COMBINED = -1;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = {
+            NetworkTemplate.OEM_MANAGED_NO,
+            NetworkTemplate.OEM_MANAGED_PAID,
+            NetworkTemplate.OEM_MANAGED_PRIVATE
+    })
+    public @interface OemManaged{}
+
     /**
      * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
      * @hide
@@ -51,29 +75,32 @@
      * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
      * @hide
      */
-    public static final int OEM_PAID = 0x1;
+    public static final int OEM_PAID = 1 << 0;
     /**
      * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
      * @hide
      */
-    public static final int OEM_PRIVATE = 0x2;
+    public static final int OEM_PRIVATE = 1 << 1;
+
+    private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
 
     final int mType;
-    final int mSubType;
+    final int mRatType;
     final String mSubscriberId;
-    final String mNetworkId;
+    final String mWifiNetworkKey;
     final boolean mRoaming;
     final boolean mMetered;
     final boolean mDefaultNetwork;
     final int mOemManaged;
 
+    /** @hide */
     public NetworkIdentity(
-            int type, int subType, String subscriberId, String networkId, boolean roaming,
-            boolean metered, boolean defaultNetwork, int oemManaged) {
+            int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
+            boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) {
         mType = type;
-        mSubType = subType;
+        mRatType = ratType;
         mSubscriberId = subscriberId;
-        mNetworkId = networkId;
+        mWifiNetworkKey = wifiNetworkKey;
         mRoaming = roaming;
         mMetered = metered;
         mDefaultNetwork = defaultNetwork;
@@ -82,7 +109,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
+        return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
                 mDefaultNetwork, mOemManaged);
     }
 
@@ -90,9 +117,9 @@
     public boolean equals(@Nullable Object obj) {
         if (obj instanceof NetworkIdentity) {
             final NetworkIdentity ident = (NetworkIdentity) obj;
-            return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
+            return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming
                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
-                    && Objects.equals(mNetworkId, ident.mNetworkId)
+                    && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
                     && mMetered == ident.mMetered
                     && mDefaultNetwork == ident.mDefaultNetwork
                     && mOemManaged == ident.mOemManaged;
@@ -104,18 +131,18 @@
     public String toString() {
         final StringBuilder builder = new StringBuilder("{");
         builder.append("type=").append(mType);
-        builder.append(", subType=");
-        if (mSubType == SUBTYPE_COMBINED) {
+        builder.append(", ratType=");
+        if (mRatType == NETWORK_TYPE_ALL) {
             builder.append("COMBINED");
         } else {
-            builder.append(mSubType);
+            builder.append(mRatType);
         }
         if (mSubscriberId != null) {
             builder.append(", subscriberId=")
                     .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
         }
-        if (mNetworkId != null) {
-            builder.append(", networkId=").append(mNetworkId);
+        if (mWifiNetworkKey != null) {
+            builder.append(", wifiNetworkKey=").append(mWifiNetworkKey);
         }
         if (mRoaming) {
             builder.append(", ROAMING");
@@ -153,18 +180,14 @@
         }
     }
 
+    /** @hide */
     public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
         proto.write(NetworkIdentityProto.TYPE, mType);
 
-        // Not dumping mSubType, subtypes are no longer supported.
+        // TODO: dump mRatType as well.
 
-        if (mSubscriberId != null) {
-            proto.write(NetworkIdentityProto.SUBSCRIBER_ID,
-                    NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
-        }
-        proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId);
         proto.write(NetworkIdentityProto.ROAMING, mRoaming);
         proto.write(NetworkIdentityProto.METERED, mMetered);
         proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
@@ -173,77 +196,98 @@
         proto.end(start);
     }
 
+    /** Get the network type of this instance. */
     public int getType() {
         return mType;
     }
 
-    public int getSubType() {
-        return mSubType;
+    /** Get the Radio Access Technology(RAT) type of this instance. */
+    public int getRatType() {
+        return mRatType;
     }
 
+    /** Get the Subscriber Id of this instance. */
+    @Nullable
     public String getSubscriberId() {
         return mSubscriberId;
     }
 
-    public String getNetworkId() {
-        return mNetworkId;
+    /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */
+    @Nullable
+    public String getWifiNetworkKey() {
+        return mWifiNetworkKey;
     }
 
+    /** @hide */
+    // TODO: Remove this function after all callers are removed.
     public boolean getRoaming() {
         return mRoaming;
     }
 
+    /** Return whether this network is roaming. */
+    public boolean isRoaming() {
+        return mRoaming;
+    }
+
+    /** @hide */
+    // TODO: Remove this function after all callers are removed.
     public boolean getMetered() {
         return mMetered;
     }
 
+    /** Return whether this network is metered. */
+    public boolean isMetered() {
+        return mMetered;
+    }
+
+    /** @hide */
+    // TODO: Remove this function after all callers are removed.
     public boolean getDefaultNetwork() {
         return mDefaultNetwork;
     }
 
+    /** Return whether this network is the default network. */
+    public boolean isDefaultNetwork() {
+        return mDefaultNetwork;
+    }
+
+    /** Get the OEM managed type of this instance. */
     public int getOemManaged() {
         return mOemManaged;
     }
 
     /**
-     * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and
-     * {@code subType}, assuming that any mobile networks are using the current IMSI.
-     * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_*
-     * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
+     * Assemble a {@link NetworkIdentity} from the passed arguments.
+     *
+     * This methods builds an identity based on the capabilities of the network in the
+     * snapshot and other passed arguments. The identity is used as a key to record data usage.
+     *
+     * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}.
+     * @param defaultNetwork whether the network is a default network.
+     * @param ratType the Radio Access Technology(RAT) type of the network. Or
+     *                {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable.
+     *                See {@code TelephonyManager.NETWORK_TYPE_*}.
+     * @hide
+     * @deprecated See {@link NetworkIdentity.Builder}.
      */
+    // TODO: Remove this after all callers are migrated to use new Api.
+    @Deprecated
+    @NonNull
     public static NetworkIdentity buildNetworkIdentity(Context context,
-            NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) {
-        final int legacyType = snapshot.getLegacyType();
-
-        final String subscriberId = snapshot.getSubscriberId();
-        String networkId = null;
-        boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
-        boolean metered = !(snapshot.getNetworkCapabilities().hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
-                || snapshot.getNetworkCapabilities().hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
-
-        final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
-
-        if (legacyType == TYPE_WIFI) {
-            final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
-                    .getTransportInfo();
-            if (transportInfo instanceof WifiInfo) {
-                final WifiInfo info = (WifiInfo) transportInfo;
-                networkId = info != null ? info.getCurrentNetworkKey() : null;
-            }
+            @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
+        final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
+                .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork);
+        if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
+            builder.setRatType(ratType);
         }
-
-        return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered,
-                defaultNetwork, oemManaged);
+        return builder.build();
     }
 
     /**
      * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
      * @hide
      */
-    public static int getOemBitfield(NetworkCapabilities nc) {
+    public static int getOemBitfield(@NonNull NetworkCapabilities nc) {
         int oemManaged = OEM_NONE;
 
         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
@@ -256,30 +300,266 @@
         return oemManaged;
     }
 
-    @Override
-    public int compareTo(NetworkIdentity another) {
-        int res = Integer.compare(mType, another.mType);
+    /** @hide */
+    public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) {
+        Objects.requireNonNull(right);
+        int res = Integer.compare(left.mType, right.mType);
         if (res == 0) {
-            res = Integer.compare(mSubType, another.mSubType);
+            res = Integer.compare(left.mRatType, right.mRatType);
         }
-        if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
-            res = mSubscriberId.compareTo(another.mSubscriberId);
+        if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) {
+            res = left.mSubscriberId.compareTo(right.mSubscriberId);
         }
-        if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
-            res = mNetworkId.compareTo(another.mNetworkId);
+        if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) {
+            res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey);
         }
         if (res == 0) {
-            res = Boolean.compare(mRoaming, another.mRoaming);
+            res = Boolean.compare(left.mRoaming, right.mRoaming);
         }
         if (res == 0) {
-            res = Boolean.compare(mMetered, another.mMetered);
+            res = Boolean.compare(left.mMetered, right.mMetered);
         }
         if (res == 0) {
-            res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
+            res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork);
         }
         if (res == 0) {
-            res = Integer.compare(mOemManaged, another.mOemManaged);
+            res = Integer.compare(left.mOemManaged, right.mOemManaged);
         }
         return res;
     }
+
+    /**
+     * Builder class for {@link NetworkIdentity}.
+     */
+    public static final class Builder {
+        // Need to be synchronized with ConnectivityManager.
+        // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module.
+        private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST
+        private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
+
+        private int mType;
+        private int mRatType;
+        private String mSubscriberId;
+        private String mWifiNetworkKey;
+        private boolean mRoaming;
+        private boolean mMetered;
+        private boolean mDefaultNetwork;
+        private int mOemManaged;
+
+        /**
+         * Creates a new Builder.
+         */
+        public Builder() {
+            // Initialize with default values. Will be overwritten by setters.
+            mType = ConnectivityManager.TYPE_NONE;
+            mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
+            mSubscriberId = null;
+            mWifiNetworkKey = null;
+            mRoaming = false;
+            mMetered = false;
+            mDefaultNetwork = false;
+            mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
+        }
+
+        /**
+         * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance.
+         * This is a useful shorthand that will read from the snapshot and set the
+         * following fields, if they are set in the snapshot :
+         *  - type
+         *  - subscriberId
+         *  - roaming
+         *  - metered
+         *  - oemManaged
+         *  - wifiNetworkKey
+         *
+         * @param snapshot The target {@link NetworkStateSnapshot} object.
+         * @return The builder object.
+         */
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @NonNull
+        public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) {
+            setType(snapshot.getLegacyType());
+
+            setSubscriberId(snapshot.getSubscriberId());
+            setRoaming(!snapshot.getNetworkCapabilities().hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING));
+            setMetered(!(snapshot.getNetworkCapabilities().hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+                    || snapshot.getNetworkCapabilities().hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)));
+
+            setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
+
+            if (mType == TYPE_WIFI) {
+                final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+                        .getTransportInfo();
+                if (transportInfo instanceof WifiInfo) {
+                    final WifiInfo info = (WifiInfo) transportInfo;
+                    setWifiNetworkKey(info.getNetworkKey());
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Set the network type of the network.
+         *
+         * @param type the network type. See {@link ConnectivityManager#TYPE_*}.
+         *
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setType(int type) {
+            // Include TYPE_NONE for compatibility, type field might not be filled by some
+            // networks such as test networks.
+            if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type)
+                    && type != ConnectivityManager.TYPE_NONE) {
+                throw new IllegalArgumentException("Invalid network type: " + type);
+            }
+            mType = type;
+            return this;
+        }
+
+        /**
+         * Set the Radio Access Technology(RAT) type of the network.
+         *
+         * No RAT type is specified by default. Call clearRatType to reset.
+         *
+         * @param ratType the Radio Access Technology(RAT) type if applicable. See
+         *                {@code TelephonyManager.NETWORK_TYPE_*}.
+         *
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setRatType(int ratType) {
+            if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
+                    && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN
+                    && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) {
+                throw new IllegalArgumentException("Invalid ratType " + ratType);
+            }
+            mRatType = ratType;
+            return this;
+        }
+
+        /**
+         * Clear the Radio Access Technology(RAT) type of the network.
+         *
+         * @return this builder.
+         */
+        @NonNull
+        public Builder clearRatType() {
+            mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
+            return this;
+        }
+
+        /**
+         * Set the Subscriber Id.
+         *
+         * @param subscriberId the Subscriber Id of the network. Or null if not applicable.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setSubscriberId(@Nullable String subscriberId) {
+            mSubscriberId = subscriberId;
+            return this;
+        }
+
+        /**
+         * Set the Wifi Network Key.
+         *
+         * @param wifiNetworkKey Wifi Network Key of the network,
+         *                        see {@link WifiInfo#getNetworkKey()}.
+         *                        Or null if not applicable.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
+            mWifiNetworkKey = wifiNetworkKey;
+            return this;
+        }
+
+        /**
+         * Set whether this network is roaming.
+         *
+         * This field is false by default. Call with false to reset.
+         *
+         * @param roaming the roaming status of the network.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setRoaming(boolean roaming) {
+            mRoaming = roaming;
+            return this;
+        }
+
+        /**
+         * Set whether this network is metered.
+         *
+         * This field is false by default. Call with false to reset.
+         *
+         * @param metered the meteredness of the network.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setMetered(boolean metered) {
+            mMetered = metered;
+            return this;
+        }
+
+        /**
+         * Set whether this network is the default network.
+         *
+         * This field is false by default. Call with false to reset.
+         *
+         * @param defaultNetwork the default network status of the network.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setDefaultNetwork(boolean defaultNetwork) {
+            mDefaultNetwork = defaultNetwork;
+            return this;
+        }
+
+        /**
+         * Set the OEM managed type.
+         *
+         * @param oemManaged Type of OEM managed network or unmanaged networks.
+         *                   See {@code NetworkTemplate#OEM_MANAGED_*}.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setOemManaged(@OemManaged int oemManaged) {
+            // Assert input does not contain illegal oemManage bits.
+            if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) {
+                throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged);
+            }
+            mOemManaged = oemManaged;
+            return this;
+        }
+
+        private void ensureValidParameters() {
+            // Assert non-mobile network cannot have a ratType.
+            if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
+                throw new IllegalArgumentException(
+                        "Invalid ratType " + mRatType + " for type " + mType);
+            }
+
+            // Assert non-wifi network cannot have a wifi network key.
+            if (mType != TYPE_WIFI && mWifiNetworkKey != null) {
+                throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
+            }
+        }
+
+        /**
+         * Builds the instance of the {@link NetworkIdentity}.
+         *
+         * @return the built instance of {@link NetworkIdentity}.
+         */
+        @NonNull
+        public NetworkIdentity build() {
+            ensureValidParameters();
+            return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
+                    mRoaming, mMetered, mDefaultNetwork, mOemManaged);
+        }
+    }
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
index abbebef..dfa347f 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
@@ -18,6 +18,7 @@
 
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 
+import android.annotation.NonNull;
 import android.service.NetworkIdentitySetProto;
 import android.util.proto.ProtoOutputStream;
 
@@ -25,6 +26,8 @@
 import java.io.DataOutput;
 import java.io.IOException;
 import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
 
 /**
  * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
@@ -32,8 +35,7 @@
  *
  * @hide
  */
-public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements
-        Comparable<NetworkIdentitySet> {
+public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
     private static final int VERSION_INIT = 1;
     private static final int VERSION_ADD_ROAMING = 2;
     private static final int VERSION_ADD_NETWORK_ID = 3;
@@ -41,9 +43,19 @@
     private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
     private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
 
+    /**
+     * Construct a {@link NetworkIdentitySet} object.
+     */
     public NetworkIdentitySet() {
+        super();
     }
 
+    /** @hide */
+    public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) {
+        super(ident);
+    }
+
+    /** @hide */
     public NetworkIdentitySet(DataInput in) throws IOException {
         final int version = in.readInt();
         final int size = in.readInt();
@@ -52,7 +64,7 @@
                 final int ignored = in.readInt();
             }
             final int type = in.readInt();
-            final int subType = in.readInt();
+            final int ratType = in.readInt();
             final String subscriberId = readOptionalString(in);
             final String networkId;
             if (version >= VERSION_ADD_NETWORK_ID) {
@@ -91,63 +103,73 @@
                 oemNetCapabilities = NetworkIdentity.OEM_NONE;
             }
 
-            add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
+            add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
                     defaultNetwork, oemNetCapabilities));
         }
     }
 
     /**
      * Method to serialize this object into a {@code DataOutput}.
+     * @hide
      */
     public void writeToStream(DataOutput out) throws IOException {
         out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
         out.writeInt(size());
         for (NetworkIdentity ident : this) {
             out.writeInt(ident.getType());
-            out.writeInt(ident.getSubType());
+            out.writeInt(ident.getRatType());
             writeOptionalString(out, ident.getSubscriberId());
-            writeOptionalString(out, ident.getNetworkId());
-            out.writeBoolean(ident.getRoaming());
-            out.writeBoolean(ident.getMetered());
-            out.writeBoolean(ident.getDefaultNetwork());
+            writeOptionalString(out, ident.getWifiNetworkKey());
+            out.writeBoolean(ident.isRoaming());
+            out.writeBoolean(ident.isMetered());
+            out.writeBoolean(ident.isDefaultNetwork());
             out.writeInt(ident.getOemManaged());
         }
     }
 
-    /** @return whether any {@link NetworkIdentity} in this set is considered metered. */
+    /**
+     * @return whether any {@link NetworkIdentity} in this set is considered metered.
+     * @hide
+     */
     public boolean isAnyMemberMetered() {
         if (isEmpty()) {
             return false;
         }
         for (NetworkIdentity ident : this) {
-            if (ident.getMetered()) {
+            if (ident.isMetered()) {
                 return true;
             }
         }
         return false;
     }
 
-    /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */
+    /**
+     * @return whether any {@link NetworkIdentity} in this set is considered roaming.
+     * @hide
+     */
     public boolean isAnyMemberRoaming() {
         if (isEmpty()) {
             return false;
         }
         for (NetworkIdentity ident : this) {
-            if (ident.getRoaming()) {
+            if (ident.isRoaming()) {
                 return true;
             }
         }
         return false;
     }
 
-    /** @return whether any {@link NetworkIdentity} in this set is considered on the default
-            network. */
+    /**
+     * @return whether any {@link NetworkIdentity} in this set is considered on the default
+     *         network.
+     * @hide
+     */
     public boolean areAllMembersOnDefaultNetwork() {
         if (isEmpty()) {
             return true;
         }
         for (NetworkIdentity ident : this) {
-            if (!ident.getDefaultNetwork()) {
+            if (!ident.isDefaultNetwork()) {
                 return false;
             }
         }
@@ -171,18 +193,20 @@
         }
     }
 
-    @Override
-    public int compareTo(NetworkIdentitySet another) {
-        if (isEmpty()) return -1;
-        if (another.isEmpty()) return 1;
+    public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) {
+        Objects.requireNonNull(left);
+        Objects.requireNonNull(right);
+        if (left.isEmpty()) return -1;
+        if (right.isEmpty()) return 1;
 
-        final NetworkIdentity ident = iterator().next();
-        final NetworkIdentity anotherIdent = another.iterator().next();
-        return ident.compareTo(anotherIdent);
+        final NetworkIdentity leftIdent = left.iterator().next();
+        final NetworkIdentity rightIdent = right.iterator().next();
+        return NetworkIdentity.compare(leftIdent, rightIdent);
     }
 
     /**
      * Method to dump this object into proto debug file.
+     * @hide
      */
     public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl
deleted file mode 100644
index cb602d79..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * 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.net;
-
-parcelable NetworkStateSnapshot;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index 352849c1..f681ba1 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -42,6 +42,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -58,7 +59,7 @@
  */
 // @NotThreadSafe
 @SystemApi
-public final class NetworkStats implements Parcelable {
+public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Entry> {
     private static final String TAG = "NetworkStats";
 
     /**
@@ -384,6 +385,95 @@
             this.operations += another.operations;
         }
 
+        /**
+         * @return interface name of this entry.
+         * @hide
+         */
+        @Nullable public String getIface() {
+            return iface;
+        }
+
+        /**
+         * @return the uid of this entry.
+         */
+        public int getUid() {
+            return uid;
+        }
+
+        /**
+         * @return the set state of this entry. Should be one of the following
+         * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+         */
+        @State public int getSet() {
+            return set;
+        }
+
+        /**
+         * @return the tag value of this entry.
+         */
+        public int getTag() {
+            return tag;
+        }
+
+        /**
+         * @return the metered state. Should be one of the following
+         * values: {link #METERED_YES}, {link #METERED_NO}.
+         */
+        @Meteredness public int getMetered() {
+            return metered;
+        }
+
+        /**
+         * @return the roaming state. Should be one of the following
+         * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
+         */
+        @Roaming public int getRoaming() {
+            return roaming;
+        }
+
+        /**
+         * @return the default network state. Should be one of the following
+         * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}.
+         */
+        @DefaultNetwork public int getDefaultNetwork() {
+            return defaultNetwork;
+        }
+
+        /**
+         * @return the number of received bytes.
+         */
+        public long getRxBytes() {
+            return rxBytes;
+        }
+
+        /**
+         * @return the number of received packets.
+         */
+        public long getRxPackets() {
+            return rxPackets;
+        }
+
+        /**
+         * @return the number of transmitted bytes.
+         */
+        public long getTxBytes() {
+            return txBytes;
+        }
+
+        /**
+         * @return the number of transmitted packets.
+         */
+        public long getTxPackets() {
+            return txPackets;
+        }
+
+        /**
+         * @return the count of network operations performed for this entry.
+         */
+        public long getOperations() {
+            return operations;
+        }
+
         @Override
         public String toString() {
             final StringBuilder builder = new StringBuilder();
@@ -590,11 +680,40 @@
     }
 
     /**
+     * Iterate over Entry objects.
+     *
+     * Return an iterator of this object that will iterate through all contained Entry objects.
+     *
+     * This iterator does not support concurrent modification and makes no guarantee of fail-fast
+     * behavior. If any method that can mutate the contents of this object is called while
+     * iteration is in progress, either inside the loop or in another thread, then behavior is
+     * undefined.
+     * The remove() method is not implemented and will throw UnsupportedOperationException.
+     * @hide
+     */
+    @SystemApi
+    @NonNull public Iterator<Entry> iterator() {
+        return new Iterator<Entry>() {
+            int mIndex = 0;
+
+            @Override
+            public boolean hasNext() {
+                return mIndex < size;
+            }
+
+            @Override
+            public Entry next() {
+                return getValues(mIndex++, null);
+            }
+        };
+    }
+
+    /**
      * Return specific stats entry.
      * @hide
      */
     @UnsupportedAppUsage
-    public Entry getValues(int i, Entry recycle) {
+    public Entry getValues(int i, @Nullable Entry recycle) {
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.iface = iface[i];
         entry.uid = uid[i];
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
index 7935d28..735c44d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.IFACE_ALL;
@@ -32,6 +33,10 @@
 
 import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.NetworkStatsHistory.Entry;
 import android.os.Binder;
 import android.service.NetworkStatsCollectionKeyProto;
 import android.service.NetworkStatsCollectionProto;
@@ -46,8 +51,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FastDataInput;
-import com.android.internal.util.FastDataOutput;
 import com.android.internal.util.FileRotator;
 import com.android.net.module.util.CollectionUtils;
 import com.android.net.module.util.NetworkStatsUtils;
@@ -58,6 +61,7 @@
 import java.io.DataInput;
 import java.io.DataInputStream;
 import java.io.DataOutput;
+import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -70,7 +74,10 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Collection of {@link NetworkStatsHistory}, stored based on combined key of
@@ -78,14 +85,12 @@
  *
  * @hide
  */
+@SystemApi(client = MODULE_LIBRARIES)
 public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer {
     private static final String TAG = NetworkStatsCollection.class.getSimpleName();
     /** File header magic number: "ANET" */
     private static final int FILE_MAGIC = 0x414E4554;
 
-    /** Default buffer size from BufferedInputStream */
-    private static final int BUFFER_SIZE = 8192;
-
     private static final int VERSION_NETWORK_INIT = 1;
 
     private static final int VERSION_UID_INIT = 1;
@@ -104,15 +109,23 @@
     private long mTotalBytes;
     private boolean mDirty;
 
+    /**
+     * Construct a {@link NetworkStatsCollection} object.
+     *
+     * @param bucketDuration duration of the buckets in this object, in milliseconds.
+     * @hide
+     */
     public NetworkStatsCollection(long bucketDuration) {
         mBucketDuration = bucketDuration;
         reset();
     }
 
+    /** @hide */
     public void clear() {
         reset();
     }
 
+    /** @hide */
     public void reset() {
         mStats.clear();
         mStartMillis = Long.MAX_VALUE;
@@ -121,6 +134,7 @@
         mDirty = false;
     }
 
+    /** @hide */
     public long getStartMillis() {
         return mStartMillis;
     }
@@ -128,6 +142,7 @@
     /**
      * Return first atomic bucket in this collection, which is more conservative
      * than {@link #mStartMillis}.
+     * @hide
      */
     public long getFirstAtomicBucketMillis() {
         if (mStartMillis == Long.MAX_VALUE) {
@@ -137,26 +152,32 @@
         }
     }
 
+    /** @hide */
     public long getEndMillis() {
         return mEndMillis;
     }
 
+    /** @hide */
     public long getTotalBytes() {
         return mTotalBytes;
     }
 
+    /** @hide */
     public boolean isDirty() {
         return mDirty;
     }
 
+    /** @hide */
     public void clearDirty() {
         mDirty = false;
     }
 
+    /** @hide */
     public boolean isEmpty() {
         return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
     }
 
+    /** @hide */
     @VisibleForTesting
     public long roundUp(long time) {
         if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
@@ -172,6 +193,7 @@
         }
     }
 
+    /** @hide */
     @VisibleForTesting
     public long roundDown(long time) {
         if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
@@ -186,10 +208,12 @@
         }
     }
 
+    /** @hide */
     public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
         return getRelevantUids(accessLevel, Binder.getCallingUid());
     }
 
+    /** @hide */
     public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
                 final int callerUid) {
         final ArrayList<Integer> uids = new ArrayList<>();
@@ -210,6 +234,7 @@
     /**
      * Combine all {@link NetworkStatsHistory} in this collection which match
      * the requested parameters.
+     * @hide
      */
     public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan,
             int uid, int set, int tag, int fields, long start, long end,
@@ -335,6 +360,7 @@
      * @param end - end of the range, timestamp in milliseconds since the epoch.
      * @param accessLevel - caller access level.
      * @param callerUid - caller UID.
+     * @hide
      */
     public NetworkStats getSummary(NetworkTemplate template, long start, long end,
             @NetworkStatsAccess.Level int accessLevel, int callerUid) {
@@ -381,6 +407,7 @@
 
     /**
      * Record given {@link android.net.NetworkStats.Entry} into this collection.
+     * @hide
      */
     public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start,
             long end, NetworkStats.Entry entry) {
@@ -391,8 +418,12 @@
 
     /**
      * Record given {@link NetworkStatsHistory} into this collection.
+     *
+     * @hide
      */
-    private void recordHistory(Key key, NetworkStatsHistory history) {
+    public void recordHistory(@NonNull Key key, @NonNull NetworkStatsHistory history) {
+        Objects.requireNonNull(key);
+        Objects.requireNonNull(history);
         if (history.size() == 0) return;
         noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes());
 
@@ -407,8 +438,11 @@
     /**
      * Record all {@link NetworkStatsHistory} contained in the given collection
      * into this collection.
+     *
+     * @hide
      */
-    public void recordCollection(NetworkStatsCollection another) {
+    public void recordCollection(@NonNull NetworkStatsCollection another) {
+        Objects.requireNonNull(another);
         for (int i = 0; i < another.mStats.size(); i++) {
             final Key key = another.mStats.keyAt(i);
             final NetworkStatsHistory value = another.mStats.valueAt(i);
@@ -437,10 +471,10 @@
         }
     }
 
+    /** @hide */
     @Override
     public void read(InputStream in) throws IOException {
-        final FastDataInput dataIn = new FastDataInput(in, BUFFER_SIZE);
-        read(dataIn);
+        read((DataInput) new DataInputStream(in));
     }
 
     private void read(DataInput in) throws IOException {
@@ -477,11 +511,11 @@
         }
     }
 
+    /** @hide */
     @Override
     public void write(OutputStream out) throws IOException {
-        final FastDataOutput dataOut = new FastDataOutput(out, BUFFER_SIZE);
-        write(dataOut);
-        dataOut.flush();
+        write((DataOutput) new DataOutputStream(out));
+        out.flush();
     }
 
     private void write(DataOutput out) throws IOException {
@@ -520,6 +554,7 @@
      * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
      *
      * @deprecated
+     * @hide
      */
     @Deprecated
     public void readLegacyNetwork(File file) throws IOException {
@@ -565,6 +600,7 @@
      * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
      *
      * @deprecated
+     * @hide
      */
     @Deprecated
     public void readLegacyUid(File file, boolean onlyTags) throws IOException {
@@ -635,6 +671,7 @@
      * Remove any {@link NetworkStatsHistory} attributed to the requested UID,
      * moving any {@link NetworkStats#TAG_NONE} series to
      * {@link TrafficStats#UID_REMOVED}.
+     * @hide
      */
     public void removeUids(int[] uids) {
         final ArrayList<Key> knownKeys = new ArrayList<>();
@@ -671,10 +708,11 @@
     private ArrayList<Key> getSortedKeys() {
         final ArrayList<Key> keys = new ArrayList<>();
         keys.addAll(mStats.keySet());
-        Collections.sort(keys);
+        Collections.sort(keys, (left, right) -> Key.compare(left, right));
         return keys;
     }
 
+    /** @hide */
     public void dump(IndentingPrintWriter pw) {
         for (Key key : getSortedKeys()) {
             pw.print("ident="); pw.print(key.ident.toString());
@@ -689,6 +727,7 @@
         }
     }
 
+    /** @hide */
     public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
@@ -712,6 +751,7 @@
         proto.end(start);
     }
 
+    /** @hide */
     public void dumpCheckin(PrintWriter pw, long start, long end) {
         dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
         dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
@@ -774,16 +814,102 @@
         return false;
     }
 
-    private static class Key implements Comparable<Key> {
+    /**
+     * Get the all historical stats of the collection {@link NetworkStatsCollection}.
+     *
+     * @return All {@link NetworkStatsHistory} in this collection.
+     */
+    @NonNull
+    public Map<Key, NetworkStatsHistory> getEntries() {
+        return new ArrayMap(mStats);
+    }
+
+    /**
+     * Builder class for {@link NetworkStatsCollection}.
+     */
+    public static final class Builder {
+        private final long mBucketDuration;
+        private final ArrayMap<Key, NetworkStatsHistory> mEntries = new ArrayMap<>();
+
+        /**
+         * Creates a new Builder with given bucket duration.
+         *
+         * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+         */
+        public Builder(long bucketDuration) {
+            mBucketDuration = bucketDuration;
+        }
+
+        /**
+         * Add association of the history with the specified key in this map.
+         *
+         * @param key The object used to identify a network, see {@link Key}.
+         * @param history {@link NetworkStatsHistory} instance associated to the given {@link Key}.
+         * @return The builder object.
+         */
+        @NonNull
+        public NetworkStatsCollection.Builder addEntry(@NonNull Key key,
+                @NonNull NetworkStatsHistory history) {
+            Objects.requireNonNull(key);
+            Objects.requireNonNull(history);
+            final List<Entry> historyEntries = history.getEntries();
+
+            final NetworkStatsHistory.Builder historyBuilder =
+                    new NetworkStatsHistory.Builder(mBucketDuration, historyEntries.size());
+            for (Entry entry : historyEntries) {
+                historyBuilder.addEntry(entry);
+            }
+
+            mEntries.put(key, historyBuilder.build());
+            return this;
+        }
+
+        /**
+         * Builds the instance of the {@link NetworkStatsCollection}.
+         *
+         * @return the built instance of {@link NetworkStatsCollection}.
+         */
+        @NonNull
+        public NetworkStatsCollection build() {
+            final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration);
+            for (int i = 0; i < mEntries.size(); i++) {
+                collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i));
+            }
+            return collection;
+        }
+    }
+
+    /**
+     * the identifier that associate with the {@link NetworkStatsHistory} object to identify
+     * a certain record in the {@link NetworkStatsCollection} object.
+     */
+    public static class Key {
+        /** @hide */
         public final NetworkIdentitySet ident;
+        /** @hide */
         public final int uid;
+        /** @hide */
         public final int set;
+        /** @hide */
         public final int tag;
 
         private final int mHashCode;
 
-        Key(NetworkIdentitySet ident, int uid, int set, int tag) {
-            this.ident = ident;
+        /**
+         * Construct a {@link Key} object.
+         *
+         * @param ident a Set of {@link NetworkIdentity} that associated with the record.
+         * @param uid Uid of the record.
+         * @param set Set of the record, see {@code NetworkStats#SET_*}.
+         * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}.
+         */
+        public Key(@NonNull Set<NetworkIdentity> ident, int uid, int set, int tag) {
+            this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag);
+        }
+
+        /** @hide */
+        public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) {
+            this.ident = Objects.requireNonNull(ident);
             this.uid = uid;
             this.set = set;
             this.tag = tag;
@@ -796,7 +922,7 @@
         }
 
         @Override
-        public boolean equals(Object obj) {
+        public boolean equals(@Nullable Object obj) {
             if (obj instanceof Key) {
                 final Key key = (Key) obj;
                 return uid == key.uid && set == key.set && tag == key.tag
@@ -805,20 +931,22 @@
             return false;
         }
 
-        @Override
-        public int compareTo(Key another) {
+        /** @hide */
+        public static int compare(@NonNull Key left, @NonNull Key right) {
+            Objects.requireNonNull(left);
+            Objects.requireNonNull(right);
             int res = 0;
-            if (ident != null && another.ident != null) {
-                res = ident.compareTo(another.ident);
+            if (left.ident != null && right.ident != null) {
+                res = NetworkIdentitySet.compare(left.ident, right.ident);
             }
             if (res == 0) {
-                res = Integer.compare(uid, another.uid);
+                res = Integer.compare(left.uid, right.uid);
             }
             if (res == 0) {
-                res = Integer.compare(set, another.set);
+                res = Integer.compare(left.set, right.set);
             }
             if (res == 0) {
-                res = Integer.compare(tag, another.tag);
+                res = Integer.compare(left.tag, right.tag);
             }
             return res;
         }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
index 428bc6d..78c1370 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.TAG_NONE;
@@ -30,6 +31,8 @@
 
 import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.os.Parcel;
@@ -50,7 +53,9 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.ProtocolException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Random;
 
 /**
@@ -64,18 +69,25 @@
  *
  * @hide
  */
-public class NetworkStatsHistory implements Parcelable {
+@SystemApi(client = MODULE_LIBRARIES)
+public final class NetworkStatsHistory implements Parcelable {
     private static final int VERSION_INIT = 1;
     private static final int VERSION_ADD_PACKETS = 2;
     private static final int VERSION_ADD_ACTIVE = 3;
 
+    /** @hide */
     public static final int FIELD_ACTIVE_TIME = 0x01;
+    /** @hide */
     public static final int FIELD_RX_BYTES = 0x02;
+    /** @hide */
     public static final int FIELD_RX_PACKETS = 0x04;
+    /** @hide */
     public static final int FIELD_TX_BYTES = 0x08;
+    /** @hide */
     public static final int FIELD_TX_PACKETS = 0x10;
+    /** @hide */
     public static final int FIELD_OPERATIONS = 0x20;
-
+    /** @hide */
     public static final int FIELD_ALL = 0xFFFFFFFF;
 
     private long bucketDuration;
@@ -89,34 +101,171 @@
     private long[] operations;
     private long totalBytes;
 
-    public static class Entry {
-        public static final long UNKNOWN = -1;
-
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long bucketDuration;
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long bucketStart;
-        public long activeTime;
-        @UnsupportedAppUsage
-        public long rxBytes;
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long rxPackets;
-        @UnsupportedAppUsage
-        public long txBytes;
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long txPackets;
-        public long operations;
+    /** @hide */
+    public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime,
+            long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets,
+            long[] operations, int bucketCount, long totalBytes) {
+        this.bucketDuration = bucketDuration;
+        this.bucketStart = bucketStart;
+        this.activeTime = activeTime;
+        this.rxBytes = rxBytes;
+        this.rxPackets = rxPackets;
+        this.txBytes = txBytes;
+        this.txPackets = txPackets;
+        this.operations = operations;
+        this.bucketCount = bucketCount;
+        this.totalBytes = totalBytes;
     }
 
+    /**
+     * An instance to represent a single record in a {@link NetworkStatsHistory} object.
+     */
+    public static final class Entry {
+        /** @hide */
+        public static final long UNKNOWN = -1;
+
+        /** @hide */
+        // TODO: Migrate all callers to get duration from the history object and remove this field.
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public long bucketDuration;
+        /** @hide */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public long bucketStart;
+        /** @hide */
+        public long activeTime;
+        /** @hide */
+        @UnsupportedAppUsage
+        public long rxBytes;
+        /** @hide */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public long rxPackets;
+        /** @hide */
+        @UnsupportedAppUsage
+        public long txBytes;
+        /** @hide */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public long txPackets;
+        /** @hide */
+        public long operations;
+        /** @hide */
+        Entry() {}
+
+        /**
+         * Construct a {@link Entry} instance to represent a single record in a
+         * {@link NetworkStatsHistory} object.
+         *
+         * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the
+         *                    Unix epoch, see {@link java.lang.System#currentTimeMillis}.
+         * @param activeTime Active time for this {@link Entry}, in milliseconds.
+         * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
+         *                represent the contents of IP packets, including IP headers.
+         * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
+         *                  represent the contents of IP packets, including IP headers.
+         * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
+         *                represent the contents of IP packets, including IP headers.
+         * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
+         *                  represent the contents of IP packets, including IP headers.
+         * @param operations count of network operations performed for this {@link Entry}. This can
+         *                   be used to derive bytes-per-operation.
+         */
+        public Entry(long bucketStart, long activeTime, long rxBytes,
+                long rxPackets, long txBytes, long txPackets, long operations) {
+            this.bucketStart = bucketStart;
+            this.activeTime = activeTime;
+            this.rxBytes = rxBytes;
+            this.rxPackets = rxPackets;
+            this.txBytes = txBytes;
+            this.txPackets = txPackets;
+            this.operations = operations;
+        }
+
+        /**
+         * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch.
+         */
+        public long getBucketStart() {
+            return bucketStart;
+        }
+
+        /**
+         * Get active time of the bucket's time interval, in milliseconds.
+         */
+        public long getActiveTime() {
+            return activeTime;
+        }
+
+        /** Get number of bytes received for this {@link Entry}. */
+        public long getRxBytes() {
+            return rxBytes;
+        }
+
+        /** Get number of packets received for this {@link Entry}. */
+        public long getRxPackets() {
+            return rxPackets;
+        }
+
+        /** Get number of bytes transmitted for this {@link Entry}. */
+        public long getTxBytes() {
+            return txBytes;
+        }
+
+        /** Get number of packets transmitted for this {@link Entry}. */
+        public long getTxPackets() {
+            return txPackets;
+        }
+
+        /** Get count of network operations performed for this {@link Entry}. */
+        public long getOperations() {
+            return operations;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o.getClass() != getClass()) return false;
+            Entry entry = (Entry) o;
+            return bucketStart == entry.bucketStart
+                    && activeTime == entry.activeTime && rxBytes == entry.rxBytes
+                    && rxPackets == entry.rxPackets && txBytes == entry.txBytes
+                    && txPackets == entry.txPackets && operations == entry.operations;
+        }
+
+        @Override
+        public int hashCode() {
+            return (int) (bucketStart * 2
+                    + activeTime * 3
+                    + rxBytes * 5
+                    + rxPackets * 7
+                    + txBytes * 11
+                    + txPackets * 13
+                    + operations * 17);
+        }
+
+        @Override
+        public String toString() {
+            return "Entry{"
+                    + "bucketStart=" + bucketStart
+                    + ", activeTime=" + activeTime
+                    + ", rxBytes=" + rxBytes
+                    + ", rxPackets=" + rxPackets
+                    + ", txBytes=" + txBytes
+                    + ", txPackets=" + txPackets
+                    + ", operations=" + operations
+                    + "}";
+        }
+    }
+
+    /** @hide */
     @UnsupportedAppUsage
     public NetworkStatsHistory(long bucketDuration) {
         this(bucketDuration, 10, FIELD_ALL);
     }
 
+    /** @hide */
     public NetworkStatsHistory(long bucketDuration, int initialSize) {
         this(bucketDuration, initialSize, FIELD_ALL);
     }
 
+    /** @hide */
     public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
         this.bucketDuration = bucketDuration;
         bucketStart = new long[initialSize];
@@ -130,11 +279,13 @@
         totalBytes = 0;
     }
 
+    /** @hide */
     public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) {
         this(bucketDuration, existing.estimateResizeBuckets(bucketDuration));
         recordEntireHistory(existing);
     }
 
+    /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public NetworkStatsHistory(Parcel in) {
         bucketDuration = in.readLong();
@@ -150,7 +301,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel out, int flags) {
+    public void writeToParcel(@NonNull Parcel out, int flags) {
         out.writeLong(bucketDuration);
         writeLongArray(out, bucketStart, bucketCount);
         writeLongArray(out, activeTime, bucketCount);
@@ -162,6 +313,7 @@
         out.writeLong(totalBytes);
     }
 
+    /** @hide */
     public NetworkStatsHistory(DataInput in) throws IOException {
         final int version = in.readInt();
         switch (version) {
@@ -204,6 +356,7 @@
         }
     }
 
+    /** @hide */
     public void writeToStream(DataOutput out) throws IOException {
         out.writeInt(VERSION_ADD_ACTIVE);
         out.writeLong(bucketDuration);
@@ -221,15 +374,18 @@
         return 0;
     }
 
+    /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public int size() {
         return bucketCount;
     }
 
+    /** @hide */
     public long getBucketDuration() {
         return bucketDuration;
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public long getStart() {
         if (bucketCount > 0) {
@@ -239,6 +395,7 @@
         }
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public long getEnd() {
         if (bucketCount > 0) {
@@ -250,6 +407,7 @@
 
     /**
      * Return total bytes represented by this history.
+     * @hide
      */
     public long getTotalBytes() {
         return totalBytes;
@@ -258,6 +416,7 @@
     /**
      * Return index of bucket that contains or is immediately before the
      * requested time.
+     * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public int getIndexBefore(long time) {
@@ -273,6 +432,7 @@
     /**
      * Return index of bucket that contains or is immediately after the
      * requested time.
+     * @hide
      */
     public int getIndexAfter(long time) {
         int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
@@ -286,6 +446,7 @@
 
     /**
      * Return specific stats entry.
+     * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public Entry getValues(int i, Entry recycle) {
@@ -301,6 +462,23 @@
         return entry;
     }
 
+    /**
+     * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance.
+     *
+     * @return
+     */
+    @NonNull
+    public List<Entry> getEntries() {
+        // TODO: Return a wrapper that uses this list instead, to prevent the returned result
+        //  from being changed.
+        final ArrayList<Entry> ret = new ArrayList<>(size());
+        for (int i = 0; i < size(); i++) {
+            ret.add(getValues(i, null /* recycle */));
+        }
+        return ret;
+    }
+
+    /** @hide */
     public void setValues(int i, Entry entry) {
         // Unwind old values
         if (rxBytes != null) totalBytes -= rxBytes[i];
@@ -322,6 +500,7 @@
     /**
      * Record that data traffic occurred in the given time range. Will
      * distribute across internal buckets, creating new buckets as needed.
+     * @hide
      */
     @Deprecated
     public void recordData(long start, long end, long rxBytes, long txBytes) {
@@ -332,6 +511,7 @@
     /**
      * Record that data traffic occurred in the given time range. Will
      * distribute across internal buckets, creating new buckets as needed.
+     * @hide
      */
     public void recordData(long start, long end, NetworkStats.Entry entry) {
         long rxBytes = entry.rxBytes;
@@ -392,6 +572,7 @@
     /**
      * Record an entire {@link NetworkStatsHistory} into this history. Usually
      * for combining together stats for external reporting.
+     * @hide
      */
     @UnsupportedAppUsage
     public void recordEntireHistory(NetworkStatsHistory input) {
@@ -402,6 +583,7 @@
      * Record given {@link NetworkStatsHistory} into this history, copying only
      * buckets that atomically occur in the inclusive time range. Doesn't
      * interpolate across partial buckets.
+     * @hide
      */
     public void recordHistory(NetworkStatsHistory input, long start, long end) {
         final NetworkStats.Entry entry = new NetworkStats.Entry(
@@ -483,6 +665,7 @@
 
     /**
      * Clear all data stored in this object.
+     * @hide
      */
     public void clear() {
         bucketStart = EmptyArray.LONG;
@@ -498,9 +681,10 @@
 
     /**
      * Remove buckets older than requested cutoff.
+     * @hide
      */
-    @Deprecated
     public void removeBucketsBefore(long cutoff) {
+        // TODO: Consider use getIndexBefore.
         int i;
         for (i = 0; i < bucketCount; i++) {
             final long curStart = bucketStart[i];
@@ -522,7 +706,9 @@
             if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
             bucketCount -= i;
 
-            // TODO: subtract removed values from totalBytes
+            totalBytes = 0;
+            if (rxBytes != null) totalBytes += CollectionUtils.total(rxBytes);
+            if (txBytes != null) totalBytes += CollectionUtils.total(txBytes);
         }
     }
 
@@ -536,6 +722,7 @@
      * @param start - start of the range, timestamp in milliseconds since the epoch.
      * @param end - end of the range, timestamp in milliseconds since the epoch.
      * @param recycle - entry instance for performance, could be null.
+     * @hide
      */
     @UnsupportedAppUsage
     public Entry getValues(long start, long end, Entry recycle) {
@@ -550,6 +737,7 @@
      * @param end - end of the range, timestamp in milliseconds since the epoch.
      * @param now - current timestamp in milliseconds since the epoch (wall clock).
      * @param recycle - entry instance for performance, could be null.
+     * @hide
      */
     @UnsupportedAppUsage
     public Entry getValues(long start, long end, long now, Entry recycle) {
@@ -613,6 +801,7 @@
 
     /**
      * @deprecated only for temporary testing
+     * @hide
      */
     @Deprecated
     public void generateRandom(long start, long end, long bytes) {
@@ -631,6 +820,7 @@
 
     /**
      * @deprecated only for temporary testing
+     * @hide
      */
     @Deprecated
     public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
@@ -660,12 +850,14 @@
         }
     }
 
+    /** @hide */
     public static long randomLong(Random r, long start, long end) {
         return (long) (start + (r.nextFloat() * (end - start)));
     }
 
     /**
      * Quickly determine if this history intersects with given window.
+     * @hide
      */
     public boolean intersects(long start, long end) {
         final long dataStart = getStart();
@@ -677,6 +869,7 @@
         return false;
     }
 
+    /** @hide */
     public void dump(IndentingPrintWriter pw, boolean fullHistory) {
         pw.print("NetworkStatsHistory: bucketDuration=");
         pw.println(bucketDuration / SECOND_IN_MILLIS);
@@ -700,6 +893,7 @@
         pw.decreaseIndent();
     }
 
+    /** @hide */
     public void dumpCheckin(PrintWriter pw) {
         pw.print("d,");
         pw.print(bucketDuration / SECOND_IN_MILLIS);
@@ -717,6 +911,7 @@
         }
     }
 
+    /** @hide */
     public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
@@ -776,6 +971,7 @@
         if (array != null) array[i] += value;
     }
 
+    /** @hide */
     public int estimateResizeBuckets(long newBucketDuration) {
         return (int) (size() * getBucketDuration() / newBucketDuration);
     }
@@ -783,6 +979,7 @@
     /**
      * Utility methods for interacting with {@link DataInputStream} and
      * {@link DataOutputStream}, mostly dealing with writing partial arrays.
+     * @hide
      */
     public static class DataStreamUtils {
         @Deprecated
@@ -857,6 +1054,7 @@
     /**
      * Utility methods for interacting with {@link Parcel} structures, mostly
      * dealing with writing partial arrays.
+     * @hide
      */
     public static class ParcelUtils {
         public static long[] readLongArray(Parcel in) {
@@ -884,4 +1082,80 @@
         }
     }
 
+    /**
+     * Builder class for {@link NetworkStatsHistory}.
+     */
+    public static final class Builder {
+        private final long mBucketDuration;
+        private final List<Long> mBucketStart;
+        private final List<Long> mActiveTime;
+        private final List<Long> mRxBytes;
+        private final List<Long> mRxPackets;
+        private final List<Long> mTxBytes;
+        private final List<Long> mTxPackets;
+        private final List<Long> mOperations;
+
+        /**
+         * Creates a new Builder with given bucket duration and initial capacity to construct
+         * {@link NetworkStatsHistory} objects.
+         *
+         * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+         * @param initialCapacity Estimated number of records.
+         */
+        public Builder(long bucketDuration, int initialCapacity) {
+            mBucketDuration = bucketDuration;
+            mBucketStart = new ArrayList<>(initialCapacity);
+            mActiveTime = new ArrayList<>(initialCapacity);
+            mRxBytes = new ArrayList<>(initialCapacity);
+            mRxPackets = new ArrayList<>(initialCapacity);
+            mTxBytes = new ArrayList<>(initialCapacity);
+            mTxPackets = new ArrayList<>(initialCapacity);
+            mOperations = new ArrayList<>(initialCapacity);
+        }
+
+        /**
+         * Add an {@link Entry} into the {@link NetworkStatsHistory} instance.
+         *
+         * @param entry The target {@link Entry} object.
+         * @return The builder object.
+         */
+        @NonNull
+        public Builder addEntry(@NonNull Entry entry) {
+            mBucketStart.add(entry.bucketStart);
+            mActiveTime.add(entry.activeTime);
+            mRxBytes.add(entry.rxBytes);
+            mRxPackets.add(entry.rxPackets);
+            mTxBytes.add(entry.txBytes);
+            mTxPackets.add(entry.txPackets);
+            mOperations.add(entry.operations);
+            return this;
+        }
+
+        private static long sum(@NonNull List<Long> list) {
+            long sum = 0;
+            for (long entry : list) {
+                sum += entry;
+            }
+            return sum;
+        }
+
+        /**
+         * Builds the instance of the {@link NetworkStatsHistory}.
+         *
+         * @return the built instance of {@link NetworkStatsHistory}.
+         */
+        @NonNull
+        public NetworkStatsHistory build() {
+            return new NetworkStatsHistory(mBucketDuration,
+                    CollectionUtils.toLongArray(mBucketStart),
+                    CollectionUtils.toLongArray(mActiveTime),
+                    CollectionUtils.toLongArray(mRxBytes),
+                    CollectionUtils.toLongArray(mRxPackets),
+                    CollectionUtils.toLongArray(mTxBytes),
+                    CollectionUtils.toLongArray(mTxPackets),
+                    CollectionUtils.toLongArray(mOperations),
+                    mBucketStart.size(),
+                    sum(mRxBytes) + sum(mTxBytes));
+        }
+    }
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
index e9084b0..9b58b01 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
@@ -41,13 +41,12 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.app.usage.NetworkStatsManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.wifi.WifiInfo;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Annotation.NetworkType;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 
@@ -58,9 +57,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -136,15 +133,6 @@
      * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
      */
     public static final int NETWORK_TYPE_ALL = -1;
-    /**
-     * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
-     * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
-     * with NR state as connected. This should not be overlapped with any of the
-     * {@code TelephonyManager.NETWORK_TYPE_*} constants.
-     *
-     * @hide
-     */
-    public static final int NETWORK_TYPE_5G_NSA = -2;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -214,7 +202,7 @@
      * @hide
      */
     public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
-            @NetworkType int ratType, int metered) {
+            int ratType, int metered) {
         if (TextUtils.isEmpty(subscriberId)) {
             return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */,
                     null /* matchSubscriberIds */,
@@ -263,7 +251,7 @@
      * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
      * given key of the wifi network.
      *
-     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
      *                  to know details about the key.
      * @hide
      */
@@ -283,7 +271,7 @@
      * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless
      * of key of the wifi network.
      *
-     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
      *                  to know details about the key.
      * @param subscriberId the IMSI associated to this wifi network.
      *
@@ -364,7 +352,7 @@
     private final int mMetered;
     private final int mRoaming;
     private final int mDefaultNetwork;
-    private final int mSubType;
+    private final int mRatType;
     /**
      * The subscriber Id match rule defines how the template should match networks with
      * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
@@ -413,18 +401,18 @@
     /** @hide */
     // TODO: Remove it after updating all of the caller.
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType,
+            String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType,
             int oemManaged) {
         this(matchRule, subscriberId, matchSubscriberIds,
                 wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
-                metered, roaming, defaultNetwork, subType, oemManaged,
+                metered, roaming, defaultNetwork, ratType, oemManaged,
                 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
     /** @hide */
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String[] matchWifiNetworkKeys, int metered, int roaming,
-            int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) {
+            int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
         Objects.requireNonNull(matchWifiNetworkKeys);
         mMatchRule = matchRule;
         mSubscriberId = subscriberId;
@@ -435,7 +423,7 @@
         mMetered = metered;
         mRoaming = roaming;
         mDefaultNetwork = defaultNetwork;
-        mSubType = subType;
+        mRatType = ratType;
         mOemManaged = oemManaged;
         mSubscriberIdMatchRule = subscriberIdMatchRule;
         checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
@@ -453,7 +441,7 @@
         mMetered = in.readInt();
         mRoaming = in.readInt();
         mDefaultNetwork = in.readInt();
-        mSubType = in.readInt();
+        mRatType = in.readInt();
         mOemManaged = in.readInt();
         mSubscriberIdMatchRule = in.readInt();
     }
@@ -467,7 +455,7 @@
         dest.writeInt(mMetered);
         dest.writeInt(mRoaming);
         dest.writeInt(mDefaultNetwork);
-        dest.writeInt(mSubType);
+        dest.writeInt(mRatType);
         dest.writeInt(mOemManaged);
         dest.writeInt(mSubscriberIdMatchRule);
     }
@@ -500,8 +488,8 @@
             builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
                     mDefaultNetwork));
         }
-        if (mSubType != NETWORK_TYPE_ALL) {
-            builder.append(", subType=").append(mSubType);
+        if (mRatType != NETWORK_TYPE_ALL) {
+            builder.append(", ratType=").append(mRatType);
         }
         if (mOemManaged != OEM_MANAGED_ALL) {
             builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
@@ -514,7 +502,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
-                mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
+                mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule);
     }
 
     @Override
@@ -526,7 +514,7 @@
                     && mMetered == other.mMetered
                     && mRoaming == other.mRoaming
                     && mDefaultNetwork == other.mDefaultNetwork
-                    && mSubType == other.mSubType
+                    && mRatType == other.mRatType
                     && mOemManaged == other.mOemManaged
                     && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
                     && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
@@ -593,7 +581,7 @@
 
     /**
      * Get the set of Wifi Network Keys of the template.
-     * See {@link WifiInfo#getCurrentNetworkKey()}.
+     * See {@link WifiInfo#getNetworkKey()}.
      */
     @NonNull
     public Set<String> getWifiNetworkKeys() {
@@ -635,7 +623,7 @@
      * Get the Radio Access Technology(RAT) type filter of the template.
      */
     public int getRatType() {
-        return mSubType;
+        return mRatType;
     }
 
     /**
@@ -652,7 +640,9 @@
      *
      * @hide
      */
-    public boolean matches(NetworkIdentity ident) {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public boolean matches(@NonNull NetworkIdentity ident) {
+        Objects.requireNonNull(ident);
         if (!matchesMetered(ident)) return false;
         if (!matchesRoaming(ident)) return false;
         if (!matchesDefaultNetwork(ident)) return false;
@@ -708,8 +698,9 @@
     }
 
     private boolean matchesCollapsedRatType(NetworkIdentity ident) {
-        return mSubType == NETWORK_TYPE_ALL
-                || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
+        return mRatType == NETWORK_TYPE_ALL
+                || NetworkStatsManager.getCollapsedRatType(mRatType)
+                == NetworkStatsManager.getCollapsedRatType(ident.mRatType);
     }
 
     /**
@@ -729,7 +720,7 @@
      * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is
      * empty.
      *
-     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
      *                  to know details about the key.
      */
     private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
@@ -753,91 +744,13 @@
     }
 
     /**
-     * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
-     * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
-     *
-     * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
-     *
-     * @hide
-     */
-    // TODO: 1. Consider move this to TelephonyManager if used by other modules.
-    //       2. Consider make this configurable.
-    //       3. Use TelephonyManager APIs when available.
-    // TODO: @SystemApi when ready.
-    public static int getCollapsedRatType(int ratType) {
-        switch (ratType) {
-            case TelephonyManager.NETWORK_TYPE_GPRS:
-            case TelephonyManager.NETWORK_TYPE_GSM:
-            case TelephonyManager.NETWORK_TYPE_EDGE:
-            case TelephonyManager.NETWORK_TYPE_IDEN:
-            case TelephonyManager.NETWORK_TYPE_CDMA:
-            case TelephonyManager.NETWORK_TYPE_1xRTT:
-                return TelephonyManager.NETWORK_TYPE_GSM;
-            case TelephonyManager.NETWORK_TYPE_EVDO_0:
-            case TelephonyManager.NETWORK_TYPE_EVDO_A:
-            case TelephonyManager.NETWORK_TYPE_EVDO_B:
-            case TelephonyManager.NETWORK_TYPE_EHRPD:
-            case TelephonyManager.NETWORK_TYPE_UMTS:
-            case TelephonyManager.NETWORK_TYPE_HSDPA:
-            case TelephonyManager.NETWORK_TYPE_HSUPA:
-            case TelephonyManager.NETWORK_TYPE_HSPA:
-            case TelephonyManager.NETWORK_TYPE_HSPAP:
-            case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
-                return TelephonyManager.NETWORK_TYPE_UMTS;
-            case TelephonyManager.NETWORK_TYPE_LTE:
-            case TelephonyManager.NETWORK_TYPE_IWLAN:
-                return TelephonyManager.NETWORK_TYPE_LTE;
-            case TelephonyManager.NETWORK_TYPE_NR:
-                return TelephonyManager.NETWORK_TYPE_NR;
-            // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
-            case NetworkTemplate.NETWORK_TYPE_5G_NSA:
-                return NetworkTemplate.NETWORK_TYPE_5G_NSA;
-            default:
-                return TelephonyManager.NETWORK_TYPE_UNKNOWN;
-        }
-    }
-
-    /**
-     * Return all supported collapsed RAT types that could be returned by
-     * {@link #getCollapsedRatType(int)}.
-     *
-     * @hide
-     */
-    // TODO: @SystemApi when ready.
-    @NonNull
-    public static final int[] getAllCollapsedRatTypes() {
-        final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
-        final HashSet<Integer> collapsedRatTypes = new HashSet<>();
-        for (final int ratType : ratTypes) {
-            collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
-        }
-        // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
-        // it is not in TelephonyManager#NETWORK_TYPE_* constants.
-        // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
-        collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA));
-        // Ensure that unknown type is returned.
-        collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
-        return toIntArray(collapsedRatTypes);
-    }
-
-    @NonNull
-    private static int[] toIntArray(@NonNull Collection<Integer> list) {
-        final int[] array = new int[list.size()];
-        int i = 0;
-        for (final Integer item : list) {
-            array[i++] = item;
-        }
-        return array;
-    }
-
-    /**
      * Check if matches Wi-Fi network template.
      */
     private boolean matchesWifi(NetworkIdentity ident) {
         switch (ident.mType) {
             case TYPE_WIFI:
                 return matchesSubscriberId(ident.mSubscriberId)
-                        && matchesWifiNetworkKey(ident.mNetworkId);
+                        && matchesWifiNetworkKey(ident.mWifiNetworkKey);
             default:
                 return false;
         }
@@ -1059,9 +972,9 @@
          * the intention of matching any Wifi Network Key.
          *
          * @param wifiNetworkKeys the list of Wifi Network Key,
-         *                        see {@link WifiInfo#getCurrentNetworkKey()}.
+         *                        see {@link WifiInfo#getNetworkKey()}.
          *                        Or an empty list to match all networks.
-         *                        Note that {@code getCurrentNetworkKey()} might get null key
+         *                        Note that {@code getNetworkKey()} might get null key
          *                        when wifi disconnects. However, the caller should never invoke
          *                        this function with a null Wifi Network Key since such statistics
          *                        never exists.
@@ -1125,7 +1038,7 @@
          * @return this builder.
          */
         @NonNull
-        public Builder setRatType(@NetworkType int ratType) {
+        public Builder setRatType(int ratType) {
             // Input will be validated with the match rule when building the template.
             mRatType = ratType;
             return this;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
index d8feb88..bc836d8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -26,13 +28,11 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.MediaPlayer;
+import android.os.Binder;
 import android.os.Build;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import com.android.server.NetworkManagementSocketTagger;
-
-import dalvik.system.SocketTagger;
+import android.os.StrictMode;
+import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -53,6 +53,11 @@
  * use {@link NetworkStatsManager} instead.
  */
 public class TrafficStats {
+    static {
+        System.loadLibrary("framework-connectivity-tiramisu-jni");
+    }
+
+    private static final String TAG = TrafficStats.class.getSimpleName();
     /**
      * The return value to indicate that the device does not support the statistic.
      */
@@ -173,8 +178,8 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
     private synchronized static INetworkStatsService getStatsService() {
         if (sStatsService == null) {
-            sStatsService = INetworkStatsService.Stub.asInterface(
-                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+            throw new IllegalStateException("TrafficStats not initialized, uid="
+                    + Binder.getCallingUid());
         }
         return sStatsService;
     }
@@ -193,6 +198,104 @@
     private static final String LOOPBACK_IFACE = "lo";
 
     /**
+     * Initialization {@link TrafficStats} with the context, to
+     * allow {@link TrafficStats} to fetch the needed binder.
+     *
+     * @param context a long-lived context, such as the application context or system
+     *                server context.
+     * @hide
+     */
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @SuppressLint("VisiblySynchronized")
+    public static synchronized void init(@NonNull final Context context) {
+        if (sStatsService != null) {
+            throw new IllegalStateException("TrafficStats is already initialized, uid="
+                    + Binder.getCallingUid());
+        }
+        final NetworkStatsManager statsManager =
+                context.getSystemService(NetworkStatsManager.class);
+        if (statsManager == null) {
+            // TODO: Currently Process.isSupplemental is not working yet, because it depends on
+            //  process to run in a certain UID range, which is not true for now. Change this
+            //  to Log.wtf once Process.isSupplemental is ready.
+            Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid());
+            return;
+        }
+        sStatsService = statsManager.getBinder();
+    }
+
+    /**
+     * Attach the socket tagger implementation to the current process, to
+     * get notified when a socket's {@link FileDescriptor} is assigned to
+     * a thread. See {@link SocketTagger#set(SocketTagger)}.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public static void attachSocketTagger() {
+        dalvik.system.SocketTagger.set(new SocketTagger());
+    }
+
+    private static class SocketTagger extends dalvik.system.SocketTagger {
+
+        // TODO: set to false
+        private static final boolean LOGD = true;
+
+        SocketTagger() {
+        }
+
+        @Override
+        public void tag(FileDescriptor fd) throws SocketException {
+            final UidTag tagInfo = sThreadUidTag.get();
+            if (LOGD) {
+                Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
+                        + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid);
+            }
+            if (tagInfo.tag == -1) {
+                StrictMode.noteUntaggedSocket();
+            }
+
+            if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+            final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid);
+            if (errno < 0) {
+                Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
+                        + tagInfo.tag + ", "
+                        + tagInfo.uid + ") failed with errno" + errno);
+            }
+        }
+
+        @Override
+        public void untag(FileDescriptor fd) throws SocketException {
+            if (LOGD) {
+                Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
+            }
+
+            final UidTag tagInfo = sThreadUidTag.get();
+            if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+
+            final int errno = native_untagSocketFd(fd);
+            if (errno < 0) {
+                Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
+            }
+        }
+    }
+
+    private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
+    private static native int native_untagSocketFd(FileDescriptor fd);
+
+    private static class UidTag {
+        public int tag = -1;
+        public int uid = -1;
+    }
+
+    private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() {
+        @Override
+        protected UidTag initialValue() {
+            return new UidTag();
+        }
+    };
+
+    /**
      * Set active tag to use when accounting {@link Socket} traffic originating
      * from the current thread. Only one active tag per thread is supported.
      * <p>
@@ -206,7 +309,7 @@
      * @see #clearThreadStatsTag()
      */
     public static void setThreadStatsTag(int tag) {
-        NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+        getAndSetThreadStatsTag(tag);
     }
 
     /**
@@ -224,7 +327,9 @@
      *         restore any existing values after a nested operation is finished
      */
     public static int getAndSetThreadStatsTag(int tag) {
-        return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+        final int old = sThreadUidTag.get().tag;
+        sThreadUidTag.get().tag = tag;
+        return old;
     }
 
     /**
@@ -265,6 +370,18 @@
     }
 
     /**
+     * Set active tag to use when accounting {@link Socket} traffic originating
+     * from the current thread. The tag used internally is well-defined to
+     * distinguish all download provider traffic.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static void setThreadStatsTagDownload() {
+        setThreadStatsTag(TAG_SYSTEM_DOWNLOAD);
+    }
+
+    /**
      * Get the active tag used when accounting {@link Socket} traffic originating
      * from the current thread. Only one active tag per thread is supported.
      * {@link #tagSocket(Socket)}.
@@ -272,7 +389,7 @@
      * @see #setThreadStatsTag(int)
      */
     public static int getThreadStatsTag() {
-        return NetworkManagementSocketTagger.getThreadSocketStatsTag();
+        return sThreadUidTag.get().tag;
     }
 
     /**
@@ -282,7 +399,7 @@
      * @see #setThreadStatsTag(int)
      */
     public static void clearThreadStatsTag() {
-        NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
+        sThreadUidTag.get().tag = -1;
     }
 
     /**
@@ -302,7 +419,7 @@
      */
     @SuppressLint("RequiresPermission")
     public static void setThreadStatsUid(int uid) {
-        NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
+        sThreadUidTag.get().uid = uid;
     }
 
     /**
@@ -313,7 +430,7 @@
      * @see #setThreadStatsUid(int)
      */
     public static int getThreadStatsUid() {
-        return NetworkManagementSocketTagger.getThreadSocketStatsUid();
+        return sThreadUidTag.get().uid;
     }
 
     /**
@@ -340,7 +457,7 @@
      */
     @SuppressLint("RequiresPermission")
     public static void clearThreadStatsUid() {
-        NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
+        setThreadStatsUid(-1);
     }
 
     /**
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
new file mode 100644
index 0000000..4e8a5b2
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.netstats;
+
+import android.net.DataUsageRequest;
+
+/**
+ * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback.
+ *
+ * @hide
+ */
+oneway interface IUsageCallback {
+    void onThresholdReached(in DataUsageRequest request);
+    void onCallbackReleased(in DataUsageRequest request);
+}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
index 0f21e55..512fbce 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
@@ -16,6 +16,9 @@
 
 package android.net.nsd;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
@@ -23,15 +26,22 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkRequest;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.Objects;
@@ -278,9 +288,180 @@
     private final SparseArray mListenerMap = new SparseArray();
     private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
     private final Object mMapLock = new Object();
+    // Map of listener key sent by client -> per-network discovery tracker
+    @GuardedBy("mPerNetworkDiscoveryMap")
+    private final ArrayMap<Integer, PerNetworkDiscoveryTracker>
+            mPerNetworkDiscoveryMap = new ArrayMap<>();
 
     private final ServiceHandler mHandler;
 
+    private class PerNetworkDiscoveryTracker {
+        final String mServiceType;
+        final int mProtocolType;
+        final DiscoveryListener mBaseListener;
+        final ArrayMap<Network, DelegatingDiscoveryListener> mPerNetworkListeners =
+                new ArrayMap<>();
+
+        final NetworkCallback mNetworkCb = new NetworkCallback() {
+            @Override
+            public void onAvailable(@NonNull Network network) {
+                final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener(
+                        network, mBaseListener);
+                mPerNetworkListeners.put(network, wrappedListener);
+                discoverServices(mServiceType, mProtocolType, network, wrappedListener);
+            }
+
+            @Override
+            public void onLost(@NonNull Network network) {
+                final DelegatingDiscoveryListener listener = mPerNetworkListeners.get(network);
+                if (listener == null) return;
+                listener.notifyAllServicesLost();
+                // Listener will be removed from map in discovery stopped callback
+                stopServiceDiscovery(listener);
+            }
+        };
+
+        // Accessed from mHandler
+        private boolean mStopRequested;
+
+        public void start(@NonNull NetworkRequest request) {
+            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+            cm.registerNetworkCallback(request, mNetworkCb, mHandler);
+            mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType));
+        }
+
+        /**
+         * Stop discovery on all networks tracked by this class.
+         *
+         * This will request all underlying listeners to stop, and the last one to stop will call
+         * onDiscoveryStopped or onStopDiscoveryFailed.
+         *
+         * Must be called on the handler thread.
+         */
+        public void requestStop() {
+            mHandler.post(() -> {
+                mStopRequested = true;
+                final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+                cm.unregisterNetworkCallback(mNetworkCb);
+                if (mPerNetworkListeners.size() == 0) {
+                    mBaseListener.onDiscoveryStopped(mServiceType);
+                    return;
+                }
+                for (int i = 0; i < mPerNetworkListeners.size(); i++) {
+                    final DelegatingDiscoveryListener listener = mPerNetworkListeners.valueAt(i);
+                    stopServiceDiscovery(listener);
+                }
+            });
+        }
+
+        private PerNetworkDiscoveryTracker(String serviceType, int protocolType,
+                DiscoveryListener baseListener) {
+            mServiceType = serviceType;
+            mProtocolType = protocolType;
+            mBaseListener = baseListener;
+        }
+
+        /**
+         * Subset of NsdServiceInfo that is tracked to generate service lost notifications when a
+         * network is lost.
+         *
+         * Service lost notifications only contain service name, type and network, so only track
+         * that information (Network is known from the listener). This also implements
+         * equals/hashCode for usage in maps.
+         */
+        private class TrackedNsdInfo {
+            private final String mServiceName;
+            private final String mServiceType;
+            TrackedNsdInfo(NsdServiceInfo info) {
+                mServiceName = info.getServiceName();
+                mServiceType = info.getServiceType();
+            }
+
+            @Override
+            public int hashCode() {
+                return Objects.hash(mServiceName, mServiceType);
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                if (!(obj instanceof TrackedNsdInfo)) return false;
+                final TrackedNsdInfo other = (TrackedNsdInfo) obj;
+                return Objects.equals(mServiceName, other.mServiceName)
+                        && Objects.equals(mServiceType, other.mServiceType);
+            }
+        }
+
+        private class DelegatingDiscoveryListener implements DiscoveryListener {
+            private final Network mNetwork;
+            private final DiscoveryListener mWrapped;
+            private final ArraySet<TrackedNsdInfo> mFoundInfo = new ArraySet<>();
+
+            private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) {
+                mNetwork = network;
+                mWrapped = listener;
+            }
+
+            void notifyAllServicesLost() {
+                for (int i = 0; i < mFoundInfo.size(); i++) {
+                    final TrackedNsdInfo trackedInfo = mFoundInfo.valueAt(i);
+                    final NsdServiceInfo serviceInfo = new NsdServiceInfo(
+                            trackedInfo.mServiceName, trackedInfo.mServiceType);
+                    serviceInfo.setNetwork(mNetwork);
+                    mWrapped.onServiceLost(serviceInfo);
+                }
+            }
+
+            @Override
+            public void onStartDiscoveryFailed(String serviceType, int errorCode) {
+                // The delegated listener is used when NsdManager takes care of starting/stopping
+                // discovery on multiple networks. Failure to start on one network is not a global
+                // failure to be reported up, as other networks may succeed: just log.
+                Log.e(TAG, "Failed to start discovery for " + serviceType + " on " + mNetwork
+                        + " with code " + errorCode);
+                mPerNetworkListeners.remove(mNetwork);
+            }
+
+            @Override
+            public void onDiscoveryStarted(String serviceType) {
+                // Wrapped listener was called upon registration, it is not called for discovery
+                // on each network
+            }
+
+            @Override
+            public void onStopDiscoveryFailed(String serviceType, int errorCode) {
+                Log.e(TAG, "Failed to stop discovery for " + serviceType + " on " + mNetwork
+                        + " with code " + errorCode);
+                mPerNetworkListeners.remove(mNetwork);
+                if (mStopRequested && mPerNetworkListeners.size() == 0) {
+                    // Do not report onStopDiscoveryFailed when some underlying listeners failed:
+                    // this does not mean that all listeners did, and onStopDiscoveryFailed is not
+                    // actionable anyway. Just report that discovery stopped.
+                    mWrapped.onDiscoveryStopped(serviceType);
+                }
+            }
+
+            @Override
+            public void onDiscoveryStopped(String serviceType) {
+                mPerNetworkListeners.remove(mNetwork);
+                if (mStopRequested && mPerNetworkListeners.size() == 0) {
+                    mWrapped.onDiscoveryStopped(serviceType);
+                }
+            }
+
+            @Override
+            public void onServiceFound(NsdServiceInfo serviceInfo) {
+                mFoundInfo.add(new TrackedNsdInfo(serviceInfo));
+                mWrapped.onServiceFound(serviceInfo);
+            }
+
+            @Override
+            public void onServiceLost(NsdServiceInfo serviceInfo) {
+                mFoundInfo.remove(new TrackedNsdInfo(serviceInfo));
+                mWrapped.onServiceLost(serviceInfo);
+            }
+        }
+    }
+
     /**
      * Create a new Nsd instance. Applications use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -634,6 +815,14 @@
     }
 
     /**
+     * Same as {@link #discoverServices(String, int, Network, DiscoveryListener)} with a null
+     * {@link Network}.
+     */
+    public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
+        discoverServices(serviceType, protocolType, (Network) null, listener);
+    }
+
+    /**
      * Initiate service discovery to browse for instances of a service type. Service discovery
      * consumes network bandwidth and will continue until the application calls
      * {@link #stopServiceDiscovery}.
@@ -657,11 +846,13 @@
      * @param serviceType The service type being discovered. Examples include "_http._tcp" for
      * http services or "_ipp._tcp" for printers
      * @param protocolType The service discovery protocol
+     * @param network Network to discover services on, or null to discover on all available networks
      * @param listener  The listener notifies of a successful discovery and is used
      * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
      * Cannot be null. Cannot be in use for an active service discovery.
      */
-    public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
+    public void discoverServices(@NonNull String serviceType, int protocolType,
+            @Nullable Network network, @NonNull DiscoveryListener listener) {
         if (TextUtils.isEmpty(serviceType)) {
             throw new IllegalArgumentException("Service type cannot be empty");
         }
@@ -669,6 +860,7 @@
 
         NsdServiceInfo s = new NsdServiceInfo();
         s.setServiceType(serviceType);
+        s.setNetwork(network);
 
         int key = putListener(listener, s);
         try {
@@ -679,6 +871,67 @@
     }
 
     /**
+     * Initiate service discovery to browse for instances of a service type. Service discovery
+     * consumes network bandwidth and will continue until the application calls
+     * {@link #stopServiceDiscovery}.
+     *
+     * <p> The function call immediately returns after sending a request to start service
+     * discovery to the framework. The application is notified of a success to initiate
+     * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
+     * through {@link DiscoveryListener#onStartDiscoveryFailed}.
+     *
+     * <p> Upon successful start, application is notified when a service is found with
+     * {@link DiscoveryListener#onServiceFound} or when a service is lost with
+     * {@link DiscoveryListener#onServiceLost}.
+     *
+     * <p> Upon failure to start, service discovery is not active and application does
+     * not need to invoke {@link #stopServiceDiscovery}
+     *
+     * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
+     * service type is no longer required, and/or whenever the application is paused or
+     * stopped.
+     *
+     * <p> During discovery, new networks may connect or existing networks may disconnect - for
+     * example if wifi is reconnected. When a service was found on a network that disconnects,
+     * {@link DiscoveryListener#onServiceLost} will be called. If a new network connects that
+     * matches the {@link NetworkRequest}, {@link DiscoveryListener#onServiceFound} will be called
+     * for services found on that network. Applications that do not want to track networks
+     * themselves are encouraged to use this method instead of other overloads of
+     * {@code discoverServices}, as they will receive proper notifications when a service becomes
+     * available or unavailable due to network changes.
+     *
+     * @param serviceType The service type being discovered. Examples include "_http._tcp" for
+     * http services or "_ipp._tcp" for printers
+     * @param protocolType The service discovery protocol
+     * @param networkRequest Request specifying networks that should be considered when discovering
+     * @param listener  The listener notifies of a successful discovery and is used
+     * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
+     * Cannot be null. Cannot be in use for an active service discovery.
+     */
+    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+    public void discoverServices(@NonNull String serviceType, int protocolType,
+            @NonNull NetworkRequest networkRequest, @NonNull DiscoveryListener listener) {
+        if (TextUtils.isEmpty(serviceType)) {
+            throw new IllegalArgumentException("Service type cannot be empty");
+        }
+        Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null");
+        checkProtocol(protocolType);
+
+        NsdServiceInfo s = new NsdServiceInfo();
+        s.setServiceType(serviceType);
+
+        final int baseListenerKey = putListener(listener, s);
+
+        final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker(
+                serviceType, protocolType, listener);
+
+        synchronized (mPerNetworkDiscoveryMap) {
+            mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo);
+            discoveryInfo.start(networkRequest);
+        }
+    }
+
+    /**
      * Stop service discovery initiated with {@link #discoverServices}.  An active service
      * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted}
      * and it stays active until the application invokes a stop service discovery. A successful
@@ -696,6 +949,14 @@
      */
     public void stopServiceDiscovery(DiscoveryListener listener) {
         int id = getListenerKey(listener);
+        // If this is a PerNetworkDiscovery request, handle it as such
+        synchronized (mPerNetworkDiscoveryMap) {
+            final PerNetworkDiscoveryTracker info = mPerNetworkDiscoveryMap.get(id);
+            if (info != null) {
+                info.requestStop();
+                return;
+            }
+        }
         try {
             mService.stopDiscovery(id);
         } catch (RemoteException e) {
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
index 0946499..8506db1 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
@@ -17,7 +17,9 @@
 package android.net.nsd;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.net.Network;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -49,6 +51,9 @@
 
     private int mPort;
 
+    @Nullable
+    private Network mNetwork;
+
     public NsdServiceInfo() {
     }
 
@@ -307,18 +312,37 @@
         return txtRecord;
     }
 
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
+    /**
+     * Get the network where the service can be found.
+     *
+     * This is never null if this {@link NsdServiceInfo} was obtained from
+     * {@link NsdManager#discoverServices} or {@link NsdManager#resolveService}.
+     */
+    @Nullable
+    public Network getNetwork() {
+        return mNetwork;
+    }
 
+    /**
+     * Set the network where the service can be found.
+     * @param network The network, or null to search for, or to announce, the service on all
+     *                connected networks.
+     */
+    public void setNetwork(@Nullable Network network) {
+        mNetwork = network;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
         sb.append("name: ").append(mServiceName)
                 .append(", type: ").append(mServiceType)
                 .append(", host: ").append(mHost)
-                .append(", port: ").append(mPort);
+                .append(", port: ").append(mPort)
+                .append(", network: ").append(mNetwork);
 
         byte[] txtRecord = getTxtRecord();
-        if (txtRecord != null) {
-            sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
-        }
+        sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
         return sb.toString();
     }
 
@@ -352,6 +376,8 @@
             }
             dest.writeString(key);
         }
+
+        dest.writeParcelable(mNetwork, 0);
     }
 
     /** Implement the Parcelable interface */
@@ -381,6 +407,7 @@
                     }
                     info.mTxtRecord.put(in.readString(), valueArray);
                 }
+                info.mNetwork = in.readParcelable(null, Network.class);
                 return info;
             }
 
diff --git a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java b/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
deleted file mode 100644
index e35f6a6..0000000
--- a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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;
-
-import android.os.StrictMode;
-import android.util.Log;
-
-import dalvik.system.SocketTagger;
-
-import java.io.FileDescriptor;
-import java.net.SocketException;
-
-/**
- * Assigns tags to sockets for traffic stats.
- */
-public final class NetworkManagementSocketTagger extends SocketTagger {
-    private static final String TAG = "NetworkManagementSocketTagger";
-    private static final boolean LOGD = false;
-
-    private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
-        @Override
-        protected SocketTags initialValue() {
-            return new SocketTags();
-        }
-    };
-
-    public static void install() {
-        SocketTagger.set(new NetworkManagementSocketTagger());
-    }
-
-    public static int setThreadSocketStatsTag(int tag) {
-        final int old = threadSocketTags.get().statsTag;
-        threadSocketTags.get().statsTag = tag;
-        return old;
-    }
-
-    public static int getThreadSocketStatsTag() {
-        return threadSocketTags.get().statsTag;
-    }
-
-    public static int setThreadSocketStatsUid(int uid) {
-        final int old = threadSocketTags.get().statsUid;
-        threadSocketTags.get().statsUid = uid;
-        return old;
-    }
-
-    public static int getThreadSocketStatsUid() {
-        return threadSocketTags.get().statsUid;
-    }
-
-    @Override
-    public void tag(FileDescriptor fd) throws SocketException {
-        final SocketTags options = threadSocketTags.get();
-        if (LOGD) {
-            Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
-                    + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
-        }
-        if (options.statsTag == -1) {
-            StrictMode.noteUntaggedSocket();
-        }
-        // TODO: skip tagging when options would be no-op
-        tagSocketFd(fd, options.statsTag, options.statsUid);
-    }
-
-    private void tagSocketFd(FileDescriptor fd, int tag, int uid) {
-        if (tag == -1 && uid == -1) return;
-
-        final int errno = native_tagSocketFd(fd, tag, uid);
-        if (errno < 0) {
-            Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
-                    + tag + ", "
-                    + uid + ") failed with errno" + errno);
-        }
-    }
-
-    @Override
-    public void untag(FileDescriptor fd) throws SocketException {
-        if (LOGD) {
-            Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
-        }
-        unTagSocketFd(fd);
-    }
-
-    private void unTagSocketFd(FileDescriptor fd) {
-        final SocketTags options = threadSocketTags.get();
-        if (options.statsTag == -1 && options.statsUid == -1) return;
-
-        final int errno = native_untagSocketFd(fd);
-        if (errno < 0) {
-            Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
-        }
-    }
-
-    public static class SocketTags {
-        public int statsTag = -1;
-        public int statsUid = -1;
-    }
-
-    public static void setKernelCounterSet(int uid, int counterSet) {
-        final int errno = native_setCounterSet(counterSet, uid);
-        if (errno < 0) {
-            Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno "
-                    + errno);
-        }
-    }
-
-    public static void resetKernelUidStats(int uid) {
-        int errno = native_deleteTagData(0, uid);
-        if (errno < 0) {
-            Log.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
-        }
-    }
-
-    /**
-     * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
-     * format like {@code 0x7fffffff00000000}.
-     */
-    public static int kernelToTag(String string) {
-        int length = string.length();
-        if (length > 10) {
-            return Long.decode(string.substring(0, length - 8)).intValue();
-        } else {
-            return 0;
-        }
-    }
-
-    private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
-    private static native int native_untagSocketFd(FileDescriptor fd);
-    private static native int native_setCounterSet(int uid, int counterSetNum);
-    private static native int native_deleteTagData(int tag, int uid);
-}
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
index 97dfb64..c3049da 100644
--- a/packages/ConnectivityT/service/Android.bp
+++ b/packages/ConnectivityT/service/Android.bp
@@ -26,6 +26,13 @@
     srcs: [
         "src/com/android/server/net/NetworkIdentity*.java",
         "src/com/android/server/net/NetworkStats*.java",
+        "src/com/android/server/net/BpfInterfaceMapUpdater.java",
+        "src/com/android/server/net/InterfaceMapValue.java",
+        "src/com/android/server/net/CookieTagMapKey.java",
+        "src/com/android/server/net/CookieTagMapValue.java",
+        "src/com/android/server/net/StatsMapKey.java",
+        "src/com/android/server/net/StatsMapValue.java",
+        "src/com/android/server/net/UidStatsMapKey.java",
     ],
     path: "src",
     visibility: [
@@ -66,6 +73,7 @@
 filegroup {
     name: "services.connectivity-ethernet-sources",
     srcs: [
+        "src/com/android/server/net/DelayedDiskWrite.java",
         "src/com/android/server/net/IpConfigStore.java",
     ],
     path: "src",
@@ -80,10 +88,45 @@
     name: "services.connectivity-tiramisu-sources",
     srcs: [
         ":services.connectivity-ethernet-sources",
-        ":services.connectivity-ipsec-sources",
         ":services.connectivity-netstats-sources",
-        ":services.connectivity-nsd-sources",
     ],
     path: "src",
     visibility: ["//frameworks/base/services/core"],
 }
+
+filegroup {
+    name: "services.connectivity-tiramisu-updatable-sources",
+    srcs: [
+        ":services.connectivity-ipsec-sources",
+        ":services.connectivity-nsd-sources",
+    ],
+    path: "src",
+    visibility: [
+        "//packages/modules/Connectivity:__subpackages__",
+    ],
+}
+
+cc_library_shared {
+    name: "libcom_android_net_module_util_jni",
+    min_sdk_version: "30",
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wthread-safety",
+    ],
+    srcs: [
+        "jni/onload.cpp",
+    ],
+    stl: "libc++_static",
+    static_libs: [
+        "libnet_utils_device_common_bpfjni",
+    ],
+    shared_libs: [
+        "liblog",
+        "libnativehelper",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+    ],
+}
diff --git a/packages/ConnectivityT/service/jni/onload.cpp b/packages/ConnectivityT/service/jni/onload.cpp
new file mode 100644
index 0000000..bca4697
--- /dev/null
+++ b/packages/ConnectivityT/service/jni/onload.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <nativehelper/JNIHelp.h>
+#include <log/log.h>
+
+namespace android {
+
+int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+    JNIEnv *env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("GetEnv failed");
+        return JNI_ERR;
+    }
+
+    if (register_com_android_net_module_util_BpfMap(env,
+            "com/android/net/module/util/BpfMap") < 0) return JNI_ERR;
+
+    return JNI_VERSION_1_6;
+}
+
+};
+
diff --git a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
index 179d945..4bc40ea 100644
--- a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
@@ -1008,16 +1008,10 @@
      *
      * @param context Binder context for this service
      */
-    private IpSecService(Context context) {
+    public IpSecService(Context context) {
         this(context, new Dependencies());
     }
 
-    static IpSecService create(Context context)
-            throws InterruptedException {
-        final IpSecService service = new IpSecService(context);
-        return service;
-    }
-
     @NonNull
     private AppOpsManager getAppOpsManager() {
         AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1054,26 +1048,6 @@
         }
     }
 
-    /** Called by system server when system is ready. */
-    public void systemReady() {
-        if (isNetdAlive()) {
-            Log.d(TAG, "IpSecService is ready");
-        } else {
-            Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
-        }
-    }
-
-    synchronized boolean isNetdAlive() {
-        try {
-            if (mNetd == null) {
-                return false;
-            }
-            return mNetd.isAlive();
-        } catch (RemoteException re) {
-            return false;
-        }
-    }
-
     /**
      * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
      * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
@@ -1896,7 +1870,6 @@
         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
 
         pw.println("IpSecService dump:");
-        pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead"));
         pw.println();
 
         pw.println("mUserResourceTracker:");
diff --git a/packages/ConnectivityT/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
index 497107d..ddf6d2c 100644
--- a/packages/ConnectivityT/service/src/com/android/server/NsdService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
@@ -19,6 +19,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
 import android.net.nsd.INsdManager;
 import android.net.nsd.INsdManagerCallback;
 import android.net.nsd.INsdServiceConnector;
@@ -44,6 +47,9 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.concurrent.CountDownLatch;
@@ -60,6 +66,7 @@
 
     private static final boolean DBG = true;
     private static final long CLEANUP_DELAY_MS = 10000;
+    private static final int IFACE_IDX_ANY = 0;
 
     private final Context mContext;
     private final NsdStateMachine mNsdStateMachine;
@@ -297,7 +304,7 @@
 
                         maybeStartDaemon();
                         id = getUniqueId();
-                        if (discoverServices(id, args.serviceInfo.getServiceType())) {
+                        if (discoverServices(id, args.serviceInfo)) {
                             if (DBG) {
                                 Log.d(TAG, "Discover " + msg.arg2 + " " + id
                                         + args.serviceInfo.getServiceType());
@@ -430,13 +437,38 @@
                 }
                 switch (code) {
                     case NativeResponseCode.SERVICE_FOUND:
-                        /* NNN uniqueId serviceName regType domain */
+                        /* NNN uniqueId serviceName regType domain interfaceIdx netId */
                         servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
+                        final int foundNetId;
+                        try {
+                            foundNetId = Integer.parseInt(cooked[6]);
+                        } catch (NumberFormatException e) {
+                            Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
+                            break;
+                        }
+                        if (foundNetId == 0L) {
+                            // Ignore services that do not have a Network: they are not usable
+                            // by apps, as they would need privileged permissions to use
+                            // interfaces that do not have an associated Network.
+                            break;
+                        }
+                        servInfo.setNetwork(new Network(foundNetId));
                         clientInfo.onServiceFound(clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_LOST:
-                        /* NNN uniqueId serviceName regType domain */
+                        /* NNN uniqueId serviceName regType domain interfaceIdx netId */
+                        final int lostNetId;
+                        try {
+                            lostNetId = Integer.parseInt(cooked[6]);
+                        } catch (NumberFormatException e) {
+                            Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
+                            break;
+                        }
                         servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
+                        // The network could be null if it was torn down when the service is lost
+                        // TODO: avoid returning null in that case, possibly by remembering found
+                        // services on the same interface index and their network at the time
+                        servInfo.setNetwork(lostNetId == 0 ? null : new Network(lostNetId));
                         clientInfo.onServiceLost(clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
@@ -461,7 +493,7 @@
                         /* NNN regId errorCode */
                         break;
                     case NativeResponseCode.SERVICE_RESOLVED:
-                        /* NNN resolveId fullName hostName port txtlen txtdata */
+                        /* NNN resolveId fullName hostName port txtlen txtdata interfaceIdx */
                         int index = 0;
                         while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
                             if (cooked[2].charAt(index) == '\\') {
@@ -473,6 +505,7 @@
                             Log.e(TAG, "Invalid service found " + raw);
                             break;
                         }
+
                         String name = cooked[2].substring(0, index);
                         String rest = cooked[2].substring(index);
                         String type = rest.replace(".local.", "");
@@ -483,12 +516,13 @@
                         clientInfo.mResolvedService.setServiceType(type);
                         clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
                         clientInfo.mResolvedService.setTxtRecords(cooked[6]);
+                        // Network will be added after SERVICE_GET_ADDR_SUCCESS
 
                         stopResolveService(id);
                         removeRequestMap(clientId, id, clientInfo);
 
                         int id2 = getUniqueId();
-                        if (getAddrInfo(id2, cooked[3])) {
+                        if (getAddrInfo(id2, cooked[3], cooked[7] /* interfaceIdx */)) {
                             storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
                         } else {
                             clientInfo.onResolveServiceFailed(
@@ -513,12 +547,31 @@
                                 clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         break;
                     case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
-                        /* NNN resolveId hostname ttl addr */
+                        /* NNN resolveId hostname ttl addr interfaceIdx netId */
+                        Network network = null;
                         try {
-                            clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
+                            final int netId = Integer.parseInt(cooked[6]);
+                            network = netId == 0L ? null : new Network(netId);
+                        } catch (NumberFormatException e) {
+                            Log.wtf(TAG, "Invalid network in GET_ADDR_SUCCESS: " + cooked[6], e);
+                        }
+
+                        InetAddress serviceHost = null;
+                        try {
+                            serviceHost = InetAddress.getByName(cooked[4]);
+                        } catch (UnknownHostException e) {
+                            Log.wtf(TAG, "Invalid host in GET_ADDR_SUCCESS", e);
+                        }
+
+                        // If the resolved service is on an interface without a network, consider it
+                        // as a failure: it would not be usable by apps as they would need
+                        // privileged permissions.
+                        if (network != null && serviceHost != null) {
+                            clientInfo.mResolvedService.setHost(serviceHost);
+                            clientInfo.mResolvedService.setNetwork(network);
                             clientInfo.onResolveServiceSucceeded(
                                     clientId, clientInfo.mResolvedService);
-                        } catch (java.net.UnknownHostException e) {
+                        } else {
                             clientInfo.onResolveServiceFailed(
                                     clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
@@ -815,8 +868,15 @@
         return mDaemon.execute("update", regId, t.size(), t.getRawData());
     }
 
-    private boolean discoverServices(int discoveryId, String serviceType) {
-        return mDaemon.execute("discover", discoveryId, serviceType);
+    private boolean discoverServices(int discoveryId, NsdServiceInfo serviceInfo) {
+        final Network network = serviceInfo.getNetwork();
+        final int discoverInterface = getNetworkInterfaceIndex(network);
+        if (network != null && discoverInterface == IFACE_IDX_ANY) {
+            Log.e(TAG, "Interface to discover service on not found");
+            return false;
+        }
+        return mDaemon.execute("discover", discoveryId, serviceInfo.getServiceType(),
+                discoverInterface);
     }
 
     private boolean stopServiceDiscovery(int discoveryId) {
@@ -824,17 +884,61 @@
     }
 
     private boolean resolveService(int resolveId, NsdServiceInfo service) {
-        String name = service.getServiceName();
-        String type = service.getServiceType();
-        return mDaemon.execute("resolve", resolveId, name, type, "local.");
+        final String name = service.getServiceName();
+        final String type = service.getServiceType();
+        final Network network = service.getNetwork();
+        final int resolveInterface = getNetworkInterfaceIndex(network);
+        if (network != null && resolveInterface == IFACE_IDX_ANY) {
+            Log.e(TAG, "Interface to resolve service on not found");
+            return false;
+        }
+        return mDaemon.execute("resolve", resolveId, name, type, "local.", resolveInterface);
+    }
+
+    /**
+     * Guess the interface to use to resolve or discover a service on a specific network.
+     *
+     * This is an imperfect guess, as for example the network may be gone or not yet fully
+     * registered. This is fine as failing is correct if the network is gone, and a client
+     * attempting to resolve/discover on a network not yet setup would have a bad time anyway; also
+     * this is to support the legacy mdnsresponder implementation, which historically resolved
+     * services on an unspecified network.
+     */
+    private int getNetworkInterfaceIndex(Network network) {
+        if (network == null) return IFACE_IDX_ANY;
+
+        final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+        if (cm == null) {
+            Log.wtf(TAG, "No ConnectivityManager for resolveService");
+            return IFACE_IDX_ANY;
+        }
+        final LinkProperties lp = cm.getLinkProperties(network);
+        if (lp == null) return IFACE_IDX_ANY;
+
+        // Only resolve on non-stacked interfaces
+        final NetworkInterface iface;
+        try {
+            iface = NetworkInterface.getByName(lp.getInterfaceName());
+        } catch (SocketException e) {
+            Log.e(TAG, "Error querying interface", e);
+            return IFACE_IDX_ANY;
+        }
+
+        if (iface == null) {
+            Log.e(TAG, "Interface not found: " + lp.getInterfaceName());
+            return IFACE_IDX_ANY;
+        }
+
+        return iface.getIndex();
     }
 
     private boolean stopResolveService(int resolveId) {
         return mDaemon.execute("stop-resolve", resolveId);
     }
 
-    private boolean getAddrInfo(int resolveId, String hostname) {
-        return mDaemon.execute("getaddrinfo", resolveId, hostname);
+    private boolean getAddrInfo(int resolveId, String hostname, String interfaceIdx) {
+        // interfaceIdx is always obtained (as string) from the service resolved callback
+        return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceIdx);
     }
 
     private boolean stopGetAddrInfo(int resolveId) {
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
new file mode 100644
index 0000000..25c88eb
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import android.content.Context;
+import android.net.INetd;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.system.ErrnoException;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
+import com.android.net.module.util.BpfMap;
+import com.android.net.module.util.IBpfMap;
+import com.android.net.module.util.InterfaceParams;
+import com.android.net.module.util.Struct.U32;
+
+/**
+ * Monitor interface added (without removed) and right interface name and its index to bpf map.
+ */
+public class BpfInterfaceMapUpdater {
+    private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName();
+    // This is current path but may be changed soon.
+    private static final String IFACE_INDEX_NAME_MAP_PATH =
+            "/sys/fs/bpf/map_netd_iface_index_name_map";
+    private final IBpfMap<U32, InterfaceMapValue> mBpfMap;
+    private final INetd mNetd;
+    private final Handler mHandler;
+    private final Dependencies mDeps;
+
+    public BpfInterfaceMapUpdater(Context ctx, Handler handler) {
+        this(ctx, handler, new Dependencies());
+    }
+
+    @VisibleForTesting
+    public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) {
+        mDeps = deps;
+        mBpfMap = deps.getInterfaceMap();
+        mNetd = deps.getINetd(ctx);
+        mHandler = handler;
+    }
+
+    /**
+     * Dependencies of BpfInerfaceMapUpdater, for injection in tests.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        /** Create BpfMap for updating interface and index mapping. */
+        public IBpfMap<U32, InterfaceMapValue> getInterfaceMap() {
+            try {
+                return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR,
+                    U32.class, InterfaceMapValue.class);
+            } catch (ErrnoException e) {
+                Log.e(TAG, "Cannot create interface map: " + e);
+                return null;
+            }
+        }
+
+        /** Get InterfaceParams for giving interface name. */
+        public InterfaceParams getInterfaceParams(String ifaceName) {
+            return InterfaceParams.getByName(ifaceName);
+        }
+
+        /** Get INetd binder object. */
+        public INetd getINetd(Context ctx) {
+            return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE));
+        }
+    }
+
+    /**
+     * Start listening interface update event.
+     * Query current interface names before listening.
+     */
+    public void start() {
+        mHandler.post(() -> {
+            if (mBpfMap == null) {
+                Log.wtf(TAG, "Fail to start: Null bpf map");
+                return;
+            }
+
+            try {
+                // TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead.
+                mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver());
+            } catch (RemoteException e) {
+                Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e);
+            }
+
+            final String[] ifaces;
+            try {
+                // TODO: use a netlink dump to get the current interface list.
+                ifaces = mNetd.interfaceGetList();
+            } catch (RemoteException | ServiceSpecificException e) {
+                Log.wtf(TAG, "Unable to query interface names by netd, " + e);
+                return;
+            }
+
+            for (String ifaceName : ifaces) {
+                addInterface(ifaceName);
+            }
+        });
+    }
+
+    private void addInterface(String ifaceName) {
+        final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName);
+        if (iface == null) {
+            Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName);
+            return;
+        }
+
+        try {
+            mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName));
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e);
+        }
+    }
+
+    private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener {
+        @Override
+        public void onInterfaceAdded(String ifName) {
+            mHandler.post(() -> addInterface(ifName));
+        }
+    }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
new file mode 100644
index 0000000..443e5b3
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Key for cookie tag map.
+ */
+public class CookieTagMapKey extends Struct {
+    @Field(order = 0, type = Type.S64)
+    public final long socketCookie;
+
+    public CookieTagMapKey(final long socketCookie) {
+        this.socketCookie = socketCookie;
+    }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
new file mode 100644
index 0000000..93b9195
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Value for cookie tag map.
+ */
+public class CookieTagMapValue extends Struct {
+    @Field(order = 0, type = Type.U32)
+    public final long uid;
+
+    @Field(order = 1, type = Type.U32)
+    public final long tag;
+
+    public CookieTagMapValue(final long uid, final long tag) {
+        this.uid = uid;
+        this.tag = tag;
+    }
+}
diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
similarity index 82%
rename from services/core/java/com/android/server/net/DelayedDiskWrite.java
rename to packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
index 8f09eb7..35dc455 100644
--- a/services/core/java/com/android/server/net/DelayedDiskWrite.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
@@ -26,21 +26,37 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
+/**
+ * This class provides APIs to do a delayed data write to a given {@link OutputStream}.
+ */
 public class DelayedDiskWrite {
+    private static final String TAG = "DelayedDiskWrite";
+
     private HandlerThread mDiskWriteHandlerThread;
     private Handler mDiskWriteHandler;
     /* Tracks multiple writes on the same thread */
     private int mWriteSequence = 0;
-    private final String TAG = "DelayedDiskWrite";
 
+    /**
+     * Used to do a delayed data write to a given {@link OutputStream}.
+     */
     public interface Writer {
-        public void onWriteCalled(DataOutputStream out) throws IOException;
+        /**
+         * write data to a given {@link OutputStream}.
+         */
+        void onWriteCalled(DataOutputStream out) throws IOException;
     }
 
+    /**
+     * Do a delayed data write to a given output stream opened from filePath.
+     */
     public void write(final String filePath, final Writer w) {
         write(filePath, w, true);
     }
 
+    /**
+     * Do a delayed data write to a given output stream opened from filePath.
+     */
     public void write(final String filePath, final Writer w, final boolean open) {
         if (TextUtils.isEmpty(filePath)) {
             throw new IllegalArgumentException("empty file path");
@@ -77,7 +93,7 @@
             if (out != null) {
                 try {
                     out.close();
-                } catch (Exception e) {}
+                } catch (Exception e) { }
             }
 
             // Quit if no more writes sent
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
new file mode 100644
index 0000000..42c0044
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * The value of bpf interface index map which is used for NetworkStatsService.
+ */
+public class InterfaceMapValue extends Struct {
+    @Field(order = 0, type = Type.ByteArray, arraysize = 16)
+    public final byte[] interfaceName;
+
+    public InterfaceMapValue(String iface) {
+        final byte[] ifaceArray = iface.getBytes();
+        interfaceName = new byte[16];
+        // All array bytes after the interface name, if any, must be 0.
+        System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length);
+    }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
index bb123a3..668d1cb 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
@@ -22,14 +22,12 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 
-import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.net.INetd;
+import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.NetworkStats;
 import android.net.UnderlyingNetworkInfo;
-import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.SystemClock;
 
@@ -70,7 +68,7 @@
 
     private final boolean mUseBpfStats;
 
-    private final INetd mNetd;
+    private final Context mContext;
 
     /**
      * Guards persistent data access in this class
@@ -158,12 +156,12 @@
         NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
     }
 
-    public NetworkStatsFactory(@NonNull INetd netd) {
-        this(new File("/proc/"), true, netd);
+    public NetworkStatsFactory(@NonNull Context ctx) {
+        this(ctx, new File("/proc/"), true);
     }
 
     @VisibleForTesting
-    public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) {
+    public NetworkStatsFactory(@NonNull Context ctx, File procRoot, boolean useBpfStats) {
         mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
         mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
         mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
@@ -172,7 +170,7 @@
             mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
             mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
         }
-        mNetd = netd;
+        mContext = ctx;
     }
 
     public NetworkStats readBpfNetworkStatsDev() throws IOException {
@@ -295,11 +293,12 @@
     }
 
     @GuardedBy("mPersistentDataLock")
-    private void requestSwapActiveStatsMapLocked() throws RemoteException {
-        // Ask netd to do a active map stats swap. When the binder call successfully returns,
+    private void requestSwapActiveStatsMapLocked() {
+        // Do a active map stats swap. When the binder call successfully returns,
         // the system server should be able to safely read and clean the inactive map
         // without race problem.
-        mNetd.trafficSwapActiveStatsMap();
+        final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+        cm.swapActiveStatsMap();
     }
 
     /**
@@ -327,7 +326,7 @@
                 if (mUseBpfStats) {
                     try {
                         requestSwapActiveStatsMapLocked();
-                    } catch (RemoteException e) {
+                    } catch (RuntimeException e) {
                         throw new IOException(e);
                     }
                     // Stats are always read from the inactive map, so they must be read after the
@@ -469,6 +468,19 @@
     }
 
     /**
+     * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
+     * format like {@code 0x7fffffff00000000}.
+     */
+    public static int kernelToTag(String string) {
+        int length = string.length();
+        if (length > 10) {
+            return Long.decode(string.substring(0, length - 8)).intValue();
+        } else {
+            return 0;
+        }
+    }
+
+    /**
      * Parse statistics from file into given {@link NetworkStats} object. Values
      * are expected to monotonically increase since device boot.
      */
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsManagerInternal.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsManagerInternal.java
deleted file mode 100644
index 0e9a9da..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsManagerInternal.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import android.annotation.NonNull;
-import android.net.NetworkStats;
-import android.net.NetworkTemplate;
-
-public abstract class NetworkStatsManagerInternal {
-    /** Return network layer usage total for traffic that matches template. */
-    public abstract long getNetworkTotalBytes(NetworkTemplate template, long start, long end);
-
-    /** Return network layer usage per-UID for traffic that matches template. */
-    public abstract NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end);
-
-    /** Mark given UID as being in foreground for stats purposes. */
-    public abstract void setUidForeground(int uid, boolean uidForeground);
-
-    /** Advise persistance threshold; may be overridden internally. */
-    public abstract void advisePersistThreshold(long thresholdBytes);
-
-    /** Force update of statistics. */
-    public abstract void forceUpdate();
-
-    /**
-     * Set the warning and limit to all registered custom network stats providers.
-     * Note that invocation of any interface will be sent to all providers.
-     */
-    public abstract void setStatsProviderWarningAndLimitAsync(@NonNull String iface, long warning,
-            long limit);
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
index b57a4f9..1953624 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
@@ -26,13 +26,12 @@
 import android.net.NetworkStatsCollection;
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.os.Bundle;
+import android.net.netstats.IUsageCallback;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Messenger;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.ArrayMap;
@@ -75,10 +74,10 @@
      *
      * @return the normalized request wrapped within {@link RequestInfo}.
      */
-    public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger,
-                IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
-        DataUsageRequest request = buildRequest(inputRequest);
-        RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid,
+    public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback,
+            int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+        DataUsageRequest request = buildRequest(inputRequest, callingUid);
+        RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
                 accessLevel);
 
         if (LOGV) Log.v(TAG, "Registering observer for " + request);
@@ -195,10 +194,12 @@
         }
     }
 
-    private DataUsageRequest buildRequest(DataUsageRequest request) {
-        // Cap the minimum threshold to a safe default to avoid too many callbacks
-        long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes);
-        if (thresholdInBytes < request.thresholdInBytes) {
+    private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) {
+        // For non-system uid, cap the minimum threshold to a safe default to avoid too
+        // many callbacks.
+        long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes
+                : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
+        if (thresholdInBytes > request.thresholdInBytes) {
             Log.w(TAG, "Threshold was too low for " + request
                     + ". Overriding to a safer default of " + thresholdInBytes + " bytes");
         }
@@ -206,11 +207,10 @@
                 request.template, thresholdInBytes);
     }
 
-    private RequestInfo buildRequestInfo(DataUsageRequest request,
-                Messenger messenger, IBinder binder, int callingUid,
-                @NetworkStatsAccess.Level int accessLevel) {
+    private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback,
+            int callingUid, @NetworkStatsAccess.Level int accessLevel) {
         if (accessLevel <= NetworkStatsAccess.Level.USER) {
-            return new UserUsageRequestInfo(this, request, messenger, binder, callingUid,
+            return new UserUsageRequestInfo(this, request, callback, callingUid,
                     accessLevel);
         } else {
             // Safety check in case a new access level is added and we forgot to update this
@@ -218,7 +218,7 @@
                 throw new IllegalArgumentException(
                         "accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
             }
-            return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid,
+            return new NetworkUsageRequestInfo(this, request, callback, callingUid,
                     accessLevel);
         }
     }
@@ -230,25 +230,23 @@
     private abstract static class RequestInfo implements IBinder.DeathRecipient {
         private final NetworkStatsObservers mStatsObserver;
         protected final DataUsageRequest mRequest;
-        private final Messenger mMessenger;
-        private final IBinder mBinder;
+        private final IUsageCallback mCallback;
         protected final int mCallingUid;
         protected final @NetworkStatsAccess.Level int mAccessLevel;
         protected NetworkStatsRecorder mRecorder;
         protected NetworkStatsCollection mCollection;
 
         RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                    Messenger messenger, IBinder binder, int callingUid,
+                IUsageCallback callback, int callingUid,
                     @NetworkStatsAccess.Level int accessLevel) {
             mStatsObserver = statsObserver;
             mRequest = request;
-            mMessenger = messenger;
-            mBinder = binder;
+            mCallback = callback;
             mCallingUid = callingUid;
             mAccessLevel = accessLevel;
 
             try {
-                mBinder.linkToDeath(this, 0);
+                mCallback.asBinder().linkToDeath(this, 0);
             } catch (RemoteException e) {
                 binderDied();
             }
@@ -257,7 +255,7 @@
         @Override
         public void binderDied() {
             if (LOGV) {
-                Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")");
+                Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")");
             }
             mStatsObserver.unregister(mRequest, Process.SYSTEM_UID);
             callCallback(NetworkStatsManager.CALLBACK_RELEASED);
@@ -270,9 +268,7 @@
         }
 
         private void unlinkDeathRecipient() {
-            if (mBinder != null) {
-                mBinder.unlinkToDeath(this, 0);
-            }
+            mCallback.asBinder().unlinkToDeath(this, 0);
         }
 
         /**
@@ -294,17 +290,19 @@
         }
 
         private void callCallback(int callbackType) {
-            Bundle bundle = new Bundle();
-            bundle.putParcelable(DataUsageRequest.PARCELABLE_KEY, mRequest);
-            Message msg = Message.obtain();
-            msg.what = callbackType;
-            msg.setData(bundle);
             try {
                 if (LOGV) {
                     Log.v(TAG, "sending notification " + callbackTypeToName(callbackType)
                             + " for " + mRequest);
                 }
-                mMessenger.send(msg);
+                switch (callbackType) {
+                    case NetworkStatsManager.CALLBACK_LIMIT_REACHED:
+                        mCallback.onThresholdReached(mRequest);
+                        break;
+                    case NetworkStatsManager.CALLBACK_RELEASED:
+                        mCallback.onCallbackReleased(mRequest);
+                        break;
+                }
             } catch (RemoteException e) {
                 // May occur naturally in the race of binder death.
                 Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
@@ -334,9 +332,9 @@
 
     private static class NetworkUsageRequestInfo extends RequestInfo {
         NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                    Messenger messenger, IBinder binder, int callingUid,
+                IUsageCallback callback, int callingUid,
                     @NetworkStatsAccess.Level int accessLevel) {
-            super(statsObserver, request, messenger, binder, callingUid, accessLevel);
+            super(statsObserver, request, callback, callingUid, accessLevel);
         }
 
         @Override
@@ -376,9 +374,9 @@
 
     private static class UserUsageRequestInfo extends RequestInfo {
         UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                    Messenger messenger, IBinder binder, int callingUid,
+                    IUsageCallback callback, int callingUid,
                     @NetworkStatsAccess.Level int accessLevel) {
-            super(statsObserver, request, messenger, binder, callingUid, accessLevel);
+            super(statsObserver, request, callback, callingUid, accessLevel);
         }
 
         @Override
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index 97281ed..b193623 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -19,12 +19,13 @@
 import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+import static android.app.usage.NetworkStatsManager.PREFIX_DEV;
 import static android.content.Intent.ACTION_SHUTDOWN;
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_UID;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.IFACE_VT;
@@ -44,25 +45,13 @@
 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
 import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.net.TrafficStats.UID_TETHERING;
 import static android.net.TrafficStats.UNSUPPORTED;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
 import static android.os.Trace.TRACE_TAG_NETWORK;
-import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
-import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
-import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
-import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
-import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
-import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
-import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
-import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
-import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
-import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
+import static android.system.OsConstants.ENOENT;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
@@ -70,9 +59,7 @@
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
 import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
-import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
-import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -89,13 +76,13 @@
 import android.database.ContentObserver;
 import android.net.DataUsageRequest;
 import android.net.INetd;
-import android.net.INetworkManagementEventObserver;
 import android.net.INetworkStatsService;
 import android.net.INetworkStatsSession;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkIdentity;
 import android.net.NetworkIdentitySet;
+import android.net.NetworkPolicyManager;
 import android.net.NetworkSpecifier;
 import android.net.NetworkStack;
 import android.net.NetworkStateSnapshot;
@@ -106,10 +93,12 @@
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.TelephonyNetworkSpecifier;
+import android.net.TetherStatsParcel;
 import android.net.TetheringManager;
 import android.net.TrafficStats;
 import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
+import android.net.netstats.IUsageCallback;
 import android.net.netstats.provider.INetworkStatsProvider;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.net.netstats.provider.NetworkStatsProvider;
@@ -117,15 +106,13 @@
 import android.os.DropBoxManager;
 import android.os.Environment;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Messenger;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -133,6 +120,7 @@
 import android.provider.Settings.Global;
 import android.service.NetworkInterfaceProto;
 import android.service.NetworkStatsServiceDumpProto;
+import android.system.ErrnoException;
 import android.telephony.PhoneStateListener;
 import android.telephony.SubscriptionPlan;
 import android.text.TextUtils;
@@ -148,13 +136,17 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FileRotator;
+import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
 import com.android.net.module.util.BestClock;
 import com.android.net.module.util.BinderUtils;
+import com.android.net.module.util.BpfMap;
 import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.IBpfMap;
+import com.android.net.module.util.LocationPermissionChecker;
 import com.android.net.module.util.NetworkStatsUtils;
 import com.android.net.module.util.PermissionUtils;
-import com.android.server.EventLogTags;
-import com.android.server.LocalServices;
+import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.U8;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -207,8 +199,31 @@
 
     private static final String TAG_NETSTATS_ERROR = "netstats_error";
 
+    /**
+     * EventLog tags used when logging into the event log. Note the values must be sync with
+     * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct
+     * name translation.
+      */
+    private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100;
+    private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101;
+
+    // TODO: Replace the hardcoded string and move it into ConnectivitySettingsManager.
+    private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED =
+            "netstats_combine_subtype_enabled";
+
+    // This is current path but may be changed soon.
+    private static final String UID_COUNTERSET_MAP_PATH =
+            "/sys/fs/bpf/map_netd_uid_counterset_map";
+    private static final String COOKIE_TAG_MAP_PATH =
+            "/sys/fs/bpf/map_netd_cookie_tag_map";
+    private static final String APP_UID_STATS_MAP_PATH =
+            "/sys/fs/bpf/map_netd_app_uid_stats_map";
+    private static final String STATS_MAP_A_PATH =
+            "/sys/fs/bpf/map_netd_stats_map_A";
+    private static final String STATS_MAP_B_PATH =
+            "/sys/fs/bpf/map_netd_stats_map_B";
+
     private final Context mContext;
-    private final INetworkManagementService mNetworkManager;
     private final NetworkStatsFactory mStatsFactory;
     private final AlarmManager mAlarmManager;
     private final Clock mClock;
@@ -223,6 +238,9 @@
     private final ContentObserver mContentObserver;
     private final ContentResolver mContentResolver;
 
+    protected INetd mNetd;
+    private final AlertObserver mAlertObserver = new AlertObserver();
+
     @VisibleForTesting
     public static final String ACTION_NETWORK_STATS_POLL =
             "com.android.server.action.NETWORK_STATS_POLL";
@@ -231,11 +249,6 @@
 
     private PendingIntent mPollIntent;
 
-    private static final String PREFIX_DEV = "dev";
-    private static final String PREFIX_XT = "xt";
-    private static final String PREFIX_UID = "uid";
-    private static final String PREFIX_UID_TAG = "uid_tag";
-
     /**
      * Settings that can be changed externally.
      */
@@ -245,9 +258,9 @@
         boolean getSampleEnabled();
         boolean getAugmentEnabled();
         /**
-         * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
-         * When disabled, mobile data is broken down by a granular subtype representative of the
-         * actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
+         * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}.
+         * When disabled, mobile data is broken down by a granular ratType representative of the
+         * actual ratType. {@see android.app.usage.NetworkStatsManager#getCollapsedRatType}.
          * Enabling this decreases the level of detail but saves performance, disk space and
          * amount of data logged.
          */
@@ -294,6 +307,9 @@
     /** Set of any ifaces associated with mobile networks since boot. */
     private volatile String[] mMobileIfaces = new String[0];
 
+    /** Set of any ifaces associated with wifi networks since boot. */
+    private volatile String[] mWifiIfaces = new String[0];
+
     /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
     @GuardedBy("mStatsLock")
     private Network[] mDefaultNetworks = new Network[0];
@@ -325,8 +341,18 @@
     @GuardedBy("mStatsLock")
     private NetworkStatsCollection mXtStatsCached;
 
-    /** Current counter sets for each UID. */
+    /**
+     * Current counter sets for each UID.
+     * TODO: maybe remove mActiveUidCounterSet and read UidCouneterSet value from mUidCounterSetMap
+     * directly ? But if mActiveUidCounterSet would be accessed very frequently, maybe keep
+     * mActiveUidCounterSet to avoid accessing kernel too frequently.
+     */
     private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
+    private final IBpfMap<U32, U8> mUidCounterSetMap;
+    private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap;
+    private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapA;
+    private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapB;
+    private final IBpfMap<UidStatsMapKey, StatsMapValue> mAppUidStatsMap;
 
     /** Data layer operation counters for splicing into other structures. */
     private NetworkStats mUidOperations = new NetworkStats(0L, 10);
@@ -354,6 +380,12 @@
     @NonNull
     private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
 
+    @NonNull
+    private final LocationPermissionChecker mLocationPermissionChecker;
+
+    @NonNull
+    private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
+
     private static @NonNull File getDefaultSystemDir() {
         return new File(Environment.getDataDirectory(), "system");
     }
@@ -405,20 +437,20 @@
         }
     }
 
-    public static NetworkStatsService create(Context context,
-                INetworkManagementService networkManager) {
+    /** Creates a new NetworkStatsService */
+    public static NetworkStatsService create(Context context) {
         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         PowerManager.WakeLock wakeLock =
                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         final INetd netd = INetd.Stub.asInterface(
                 (IBinder) context.getSystemService(Context.NETD_SERVICE));
-        final NetworkStatsService service = new NetworkStatsService(context, networkManager,
+        final NetworkStatsService service = new NetworkStatsService(context,
+                INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
                 alarmManager, wakeLock, getDefaultClock(),
-                new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd),
+                new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context),
                 new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
                 new Dependencies());
-        service.registerLocalService();
 
         return service;
     }
@@ -426,14 +458,12 @@
     // This must not be called outside of tests, even within the same package, as this constructor
     // does not register the local service. Use the create() helper above.
     @VisibleForTesting
-    NetworkStatsService(Context context, INetworkManagementService networkManager,
-            AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
-            NetworkStatsSettings settings, NetworkStatsFactory factory,
-            NetworkStatsObservers statsObservers, File systemDir, File baseDir,
-            @NonNull Dependencies deps) {
+    NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager,
+            PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings,
+            NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
+            File baseDir, @NonNull Dependencies deps) {
         mContext = Objects.requireNonNull(context, "missing Context");
-        mNetworkManager = Objects.requireNonNull(networkManager,
-                "missing INetworkManagementService");
+        mNetd = Objects.requireNonNull(netd, "missing Netd");
         mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
         mClock = Objects.requireNonNull(clock, "missing Clock");
         mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
@@ -448,10 +478,18 @@
         handlerThread.start();
         mHandler = new NetworkStatsHandler(handlerThread.getLooper());
         mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
-                new HandlerExecutor(mHandler), this);
+                (command) -> mHandler.post(command) , this);
         mContentResolver = mContext.getContentResolver();
         mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
                 mNetworkStatsSubscriptionsMonitor);
+        mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
+        mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
+        mInterfaceMapUpdater.start();
+        mUidCounterSetMap = mDeps.getUidCounterSetMap();
+        mCookieTagMap = mDeps.getCookieTagMap();
+        mStatsMapA = mDeps.getStatsMapA();
+        mStatsMapB = mDeps.getStatsMapB();
+        mAppUidStatsMap = mDeps.getAppUidStatsMap();
     }
 
     /**
@@ -499,11 +537,95 @@
                 }
             };
         }
+
+        /**
+         * @see LocationPermissionChecker
+         */
+        public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
+            return new LocationPermissionChecker(context);
+        }
+
+        /** Create BpfInterfaceMapUpdater to update bpf interface map. */
+        @NonNull
+        public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater(
+                @NonNull Context ctx, @NonNull Handler handler) {
+            return new BpfInterfaceMapUpdater(ctx, handler);
+        }
+
+        /** Get counter sets map for each UID. */
+        public IBpfMap<U32, U8> getUidCounterSetMap() {
+            try {
+                return new BpfMap<U32, U8>(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR,
+                        U32.class, U8.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create uid counter set map: " + e);
+                return null;
+            }
+        }
+
+        /** Gets the cookie tag map */
+        public IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
+            try {
+                return new BpfMap<CookieTagMapKey, CookieTagMapValue>(COOKIE_TAG_MAP_PATH,
+                        BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create cookie tag map: " + e);
+                return null;
+            }
+        }
+
+        /** Gets stats map A */
+        public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapA() {
+            try {
+                return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_A_PATH,
+                        BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create stats map A: " + e);
+                return null;
+            }
+        }
+
+        /** Gets stats map B */
+        public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapB() {
+            try {
+                return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_B_PATH,
+                        BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create stats map B: " + e);
+                return null;
+            }
+        }
+
+        /** Gets the uid stats map */
+        public IBpfMap<UidStatsMapKey, StatsMapValue> getAppUidStatsMap() {
+            try {
+                return new BpfMap<UidStatsMapKey, StatsMapValue>(APP_UID_STATS_MAP_PATH,
+                        BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class);
+            } catch (ErrnoException e) {
+                Log.wtf(TAG, "Cannot create app uid stats map: " + e);
+                return null;
+            }
+        }
     }
 
-    private void registerLocalService() {
-        LocalServices.addService(NetworkStatsManagerInternal.class,
-                new NetworkStatsManagerInternalImpl());
+    /**
+     * Observer that watches for {@link INetdUnsolicitedEventListener} alerts.
+     */
+    @VisibleForTesting
+    public class AlertObserver extends BaseNetdUnsolicitedEventListener {
+        @Override
+        public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) {
+            PermissionUtils.enforceNetworkStackPermission(mContext);
+
+            if (LIMIT_GLOBAL_ALERT.equals(alertName)) {
+                // kick off background poll to collect network stats unless there is already
+                // such a call pending; UID stats are handled during normal polling interval.
+                if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
+                    mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
+                            mSettings.getPollDelay());
+                }
+            }
+        }
     }
 
     public void systemReady() {
@@ -532,7 +654,7 @@
         // watch for tethering changes
         final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
         tetheringManager.registerTetheringEventCallback(
-                new HandlerExecutor(mHandler), mTetherListener);
+                (command) -> mHandler.post(command), mTetherListener);
 
         // listen for periodic polling events
         final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
@@ -551,9 +673,9 @@
         mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
 
         try {
-            mNetworkManager.registerObserver(mAlertObserver);
-        } catch (RemoteException e) {
-            // ignored; service lives in system_server
+            mNetd.registerUnsolicitedEventListener(mAlertObserver);
+        } catch (RemoteException | ServiceSpecificException e) {
+            Log.wtf(TAG, "Error registering event listener :", e);
         }
 
         //  schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
@@ -566,13 +688,13 @@
                 mSettings.getPollInterval(), pollIntent);
 
         mContentResolver.registerContentObserver(Settings.Global
-                .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED),
+                .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED),
                         false /* notifyForDescendants */, mContentObserver);
 
         // Post a runnable on handler thread to call onChange(). It's for getting current value of
         // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes.
         mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
-                .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED)));
+                .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED)));
 
         registerGlobalAlert();
     }
@@ -641,13 +763,13 @@
     }
 
     /**
-     * Register for a global alert that is delivered through {@link INetworkManagementEventObserver}
+     * Register for a global alert that is delivered through {@link AlertObserver}
      * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
      * been transferred.
      */
     private void registerGlobalAlert() {
         try {
-            mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
+            mNetd.bandwidthSetGlobalAlert(mGlobalAlertBytes);
         } catch (IllegalStateException e) {
             Log.w(TAG, "problem registering for global alert: " + e);
         } catch (RemoteException e) {
@@ -683,12 +805,25 @@
         return now - lastCallTime < POLL_RATE_LIMIT_MS;
     }
 
-    private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
+    private int restrictFlagsForCaller(int flags) {
+        // All non-privileged callers are not allowed to turn off POLL_ON_OPEN.
+        final boolean isPrivileged = PermissionUtils.checkAnyPermissionOf(mContext,
+                NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+                android.Manifest.permission.NETWORK_STACK);
+        if (!isPrivileged) {
+            flags |= NetworkStatsManager.FLAG_POLL_ON_OPEN;
+        }
+        // Non-system uids are rate limited for POLL_ON_OPEN.
         final int callingUid = Binder.getCallingUid();
-        final int usedFlags = isRateLimitedForPoll(callingUid)
+        flags = isRateLimitedForPoll(callingUid)
                 ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
                 : flags;
-        if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
+        return flags;
+    }
+
+    private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
+        final int restrictedFlags = restrictFlagsForCaller(flags);
+        if ((restrictedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
                 | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
             final long ident = Binder.clearCallingIdentity();
             try {
@@ -702,7 +837,7 @@
         // for its lifetime; when caller closes only weak references remain.
 
         return new INetworkStatsSession.Stub() {
-            private final int mCallingUid = callingUid;
+            private final int mCallingUid = Binder.getCallingUid();
             private final String mCallingPackage = callingPackage;
             private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
                     callingPackage);
@@ -736,26 +871,41 @@
             @Override
             public NetworkStats getDeviceSummaryForNetwork(
                     NetworkTemplate template, long start, long end) {
-                return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
-                        mCallingUid);
+                enforceTemplatePermissions(template, callingPackage);
+                return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
+                        mAccessLevel, mCallingUid);
             }
 
             @Override
             public NetworkStats getSummaryForNetwork(
                     NetworkTemplate template, long start, long end) {
-                return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
-                        mCallingUid);
+                enforceTemplatePermissions(template, callingPackage);
+                return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
+                        mAccessLevel, mCallingUid);
+            }
+
+            // TODO: Remove this after all callers are removed.
+            @Override
+            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
+                enforceTemplatePermissions(template, callingPackage);
+                return internalGetHistoryForNetwork(template, restrictedFlags, fields,
+                        mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE);
             }
 
             @Override
-            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
-                return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
-                        mCallingUid);
+            public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template,
+                    int fields, long start, long end) {
+                enforceTemplatePermissions(template, callingPackage);
+                // TODO(b/200768422): Redact returned history if the template is location
+                //  sensitive but the caller is not privileged.
+                return internalGetHistoryForNetwork(template, restrictedFlags, fields,
+                        mAccessLevel, mCallingUid, start, end);
             }
 
             @Override
             public NetworkStats getSummaryForAllUid(
                     NetworkTemplate template, long start, long end, boolean includeTags) {
+                enforceTemplatePermissions(template, callingPackage);
                 try {
                     final NetworkStats stats = getUidComplete()
                             .getSummary(template, start, end, mAccessLevel, mCallingUid);
@@ -766,8 +916,19 @@
                     }
                     return stats;
                 } catch (NullPointerException e) {
-                    // TODO: Track down and fix the cause of this crash and remove this catch block.
-                    Log.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
+                    throw e;
+                }
+            }
+
+            @Override
+            public NetworkStats getTaggedSummaryForAllUid(
+                    NetworkTemplate template, long start, long end) {
+                enforceTemplatePermissions(template, callingPackage);
+                try {
+                    final NetworkStats tagStats = getUidTagComplete()
+                            .getSummary(template, start, end, mAccessLevel, mCallingUid);
+                    return tagStats;
+                } catch (NullPointerException e) {
                     throw e;
                 }
             }
@@ -775,6 +936,7 @@
             @Override
             public NetworkStatsHistory getHistoryForUid(
                     NetworkTemplate template, int uid, int set, int tag, int fields) {
+                enforceTemplatePermissions(template, callingPackage);
                 // NOTE: We don't augment UID-level statistics
                 if (tag == TAG_NONE) {
                     return getUidComplete().getHistory(template, null, uid, set, tag, fields,
@@ -789,6 +951,9 @@
             public NetworkStatsHistory getHistoryIntervalForUid(
                     NetworkTemplate template, int uid, int set, int tag, int fields,
                     long start, long end) {
+                enforceTemplatePermissions(template, callingPackage);
+                // TODO(b/200768422): Redact returned history if the template is location
+                //  sensitive but the caller is not privileged.
                 // NOTE: We don't augment UID-level statistics
                 if (tag == TAG_NONE) {
                     return getUidComplete().getHistory(template, null, uid, set, tag, fields,
@@ -810,6 +975,26 @@
         };
     }
 
+    private void enforceTemplatePermissions(@NonNull NetworkTemplate template,
+            @NonNull String callingPackage) {
+        // For a template with wifi network keys, it is possible for a malicious
+        // client to track the user locations via querying data usage. Thus, enforce
+        // fine location permission check.
+        if (!template.getWifiNetworkKeys().isEmpty()) {
+            final boolean canAccessFineLocation = mLocationPermissionChecker
+                    .checkCallersLocationPermission(callingPackage,
+                    null /* featureId */,
+                            Binder.getCallingUid(),
+                            false /* coarseForTargetSdkLessThanQ */,
+                            null /* message */);
+            if (!canAccessFineLocation) {
+                throw new SecurityException("Access fine location is required when querying"
+                        + " with wifi network keys, make sure the app has the necessary"
+                        + "permissions and the location toggle is on.");
+            }
+        }
+    }
+
     private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
         return NetworkStatsAccess.checkAccessLevel(
                 mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
@@ -827,7 +1012,7 @@
             if (LOGD) Log.d(TAG, "Resolving plan for " + template);
             final long token = Binder.clearCallingIdentity();
             try {
-                plan = LocalServices.getService(NetworkPolicyManagerInternal.class)
+                plan = mContext.getSystemService(NetworkPolicyManager.class)
                         .getSubscriptionPlan(template);
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -846,7 +1031,7 @@
         // We've been using pure XT stats long enough that we no longer need to
         // splice DEV and XT together.
         final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
-                accessLevel, callingUid);
+                accessLevel, callingUid, start, end);
 
         final long now = System.currentTimeMillis();
         final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
@@ -863,14 +1048,14 @@
      * appropriate.
      */
     private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
-            int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
+            int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid,
+            long start, long end) {
         // We've been using pure XT stats long enough that we no longer need to
         // splice DEV and XT together.
         final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
         synchronized (mStatsLock) {
             return mXtStatsCached.getHistory(template, augmentPlan,
-                    UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
-                    accessLevel, callingUid);
+                    UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
         }
     }
 
@@ -901,8 +1086,17 @@
         }
 
         // TODO: switch to data layer stats once kernel exports
-        // for now, read network layer stats and flatten across all ifaces
-        final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
+        // for now, read network layer stats and flatten across all ifaces.
+        // This function is used to query NeworkStats for calle's uid. The only caller method
+        // TrafficStats#getDataLayerSnapshotForUid alrady claim no special permission to query
+        // its own NetworkStats.
+        final long ident = Binder.clearCallingIdentity();
+        final NetworkStats networkLayer;
+        try {
+            networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
 
         // splice in operation counts
         networkLayer.spliceOperationsFrom(mUidOperations);
@@ -921,10 +1115,15 @@
     }
 
     @Override
-    public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
+    public NetworkStats getUidStatsForTransport(int transport) {
+        enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
         try {
+            final String[] relevantIfaces =
+                    transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces;
+            // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
+            // interfaces, so this is not useful, remove it.
             final String[] ifacesToQuery =
-                    mStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
+                    mStatsFactory.augmentWithStackedInterfaces(relevantIfaces);
             return getNetworkStatsUidDetail(ifacesToQuery);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error compiling UID stats", e);
@@ -964,8 +1163,32 @@
         }
     }
 
+    private void setKernelCounterSet(int uid, int set) {
+        if (mUidCounterSetMap == null) {
+            Log.wtf(TAG, "Fail to set UidCounterSet: Null bpf map");
+            return;
+        }
+
+        if (set == SET_DEFAULT) {
+            try {
+                mUidCounterSetMap.deleteEntry(new U32(uid));
+            } catch (ErrnoException e) {
+                Log.w(TAG, "UidCounterSetMap.deleteEntry(" + uid + ") failed with errno: " + e);
+            }
+            return;
+        }
+
+        try {
+            mUidCounterSetMap.updateEntry(new U32(uid), new U8((short) set));
+        } catch (ErrnoException e) {
+            Log.w(TAG, "UidCounterSetMap.updateEntry(" + uid + ", " + set
+                    + ") failed with errno: " + e);
+        }
+    }
+
     @VisibleForTesting
-    void setUidForeground(int uid, boolean uidForeground) {
+    public void setUidForeground(int uid, boolean uidForeground) {
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         synchronized (mStatsLock) {
             final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
             final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
@@ -1001,7 +1224,7 @@
 
     @Override
     public void forceUpdate() {
-        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+        PermissionUtils.enforceNetworkStackPermission(mContext);
 
         final long token = Binder.clearCallingIdentity();
         try {
@@ -1011,7 +1234,9 @@
         }
     }
 
-    private void advisePersistThreshold(long thresholdBytes) {
+    /** Advise persistence threshold; may be overridden internally. */
+    public void advisePersistThreshold(long thresholdBytes) {
+        PermissionUtils.enforceNetworkStackPermission(mContext);
         // clamp threshold into safe range
         mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes,
                 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
@@ -1041,21 +1266,20 @@
     }
 
     @Override
-    public DataUsageRequest registerUsageCallback(String callingPackage,
-                DataUsageRequest request, Messenger messenger, IBinder binder) {
+    public DataUsageRequest registerUsageCallback(@NonNull String callingPackage,
+                @NonNull DataUsageRequest request, @NonNull IUsageCallback callback) {
         Objects.requireNonNull(callingPackage, "calling package is null");
         Objects.requireNonNull(request, "DataUsageRequest is null");
         Objects.requireNonNull(request.template, "NetworkTemplate is null");
-        Objects.requireNonNull(messenger, "messenger is null");
-        Objects.requireNonNull(binder, "binder is null");
+        Objects.requireNonNull(callback, "callback is null");
 
         int callingUid = Binder.getCallingUid();
         @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
         DataUsageRequest normalizedRequest;
         final long token = Binder.clearCallingIdentity();
         try {
-            normalizedRequest = mStatsObservers.register(request, messenger, binder,
-                    callingUid, accessLevel);
+            normalizedRequest = mStatsObservers.register(
+                    request, callback, callingUid, accessLevel);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -1226,26 +1450,6 @@
     };
 
     /**
-     * Observer that watches for {@link INetworkManagementService} alerts.
-     */
-    private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
-        @Override
-        public void limitReached(String limitName, String iface) {
-            // only someone like NMS should be calling us
-            PermissionUtils.enforceNetworkStackPermission(mContext);
-
-            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
-                // kick off background poll to collect network stats unless there is already
-                // such a call pending; UID stats are handled during normal polling interval.
-                if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
-                    mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
-                            mSettings.getPollDelay());
-                }
-            }
-        }
-    };
-
-    /**
      * Handle collapsed RAT type changed event.
      */
     @VisibleForTesting
@@ -1300,16 +1504,18 @@
 
         final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
         final ArraySet<String> mobileIfaces = new ArraySet<>();
+        final ArraySet<String> wifiIfaces = new ArraySet<>();
         for (NetworkStateSnapshot snapshot : snapshots) {
             final int displayTransport =
                     getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
             final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
+            final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport);
             final boolean isDefault = CollectionUtils.contains(
                     mDefaultNetworks, snapshot.getNetwork());
-            final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
-                    : getSubTypeForStateSnapshot(snapshot);
+            final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL
+                    : getRatTypeForStateSnapshot(snapshot);
             final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
-                    isDefault, subType);
+                    isDefault, ratType);
 
             // Traffic occurring on the base interface is always counted for
             // both total usage and UID details.
@@ -1324,12 +1530,12 @@
                 // VT is considered always metered in framework's layer. If VT is not metered
                 // per carrier's policy, modem will report 0 usage for VT calls.
                 if (snapshot.getNetworkCapabilities().hasCapability(
-                        NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) {
+                        NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
 
                     // Copy the identify from IMS one but mark it as metered.
                     NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
-                            ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
-                            ident.getRoaming(), true /* metered */,
+                            ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(),
+                            ident.isRoaming(), true /* metered */,
                             true /* onDefaultNetwork */, ident.getOemManaged());
                     final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
                     findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
@@ -1339,6 +1545,9 @@
                 if (isMobile) {
                     mobileIfaces.add(baseIface);
                 }
+                if (isWifi) {
+                    wifiIfaces.add(baseIface);
+                }
             }
 
             // Traffic occurring on stacked interfaces is usually clatd.
@@ -1380,6 +1589,9 @@
                     if (isMobile) {
                         mobileIfaces.add(iface);
                     }
+                    if (isWifi) {
+                        wifiIfaces.add(iface);
+                    }
 
                     mStatsFactory.noteStackedIface(iface, baseIface);
                 }
@@ -1387,11 +1599,16 @@
         }
 
         mMobileIfaces = mobileIfaces.toArray(new String[0]);
+        mWifiIfaces = wifiIfaces.toArray(new String[0]);
         // TODO (b/192758557): Remove debug log.
         if (CollectionUtils.contains(mMobileIfaces, null)) {
             throw new NullPointerException(
                     "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
         }
+        if (CollectionUtils.contains(mWifiIfaces, null)) {
+            throw new NullPointerException(
+                    "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces));
+        }
     }
 
     private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
@@ -1409,11 +1626,11 @@
     }
 
     /**
-     * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
+     * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through
      * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
      * transport types do not actually fill this value.
      */
-    private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
+    private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
         if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
             return 0;
         }
@@ -1610,7 +1827,7 @@
         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
 
-        EventLogTags.writeNetstatsMobileSample(
+        EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
@@ -1622,13 +1839,76 @@
         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
 
-        EventLogTags.writeNetstatsWifiSample(
+        EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
                 currentTime);
     }
 
+    // deleteKernelTagData can ignore ENOENT; otherwise we should log an error
+    private void logErrorIfNotErrNoent(final ErrnoException e, final String msg) {
+        if (e.errno != ENOENT) Log.e(TAG, msg, e);
+    }
+
+    private <K extends StatsMapKey, V extends StatsMapValue> void deleteStatsMapTagData(
+            IBpfMap<K, V> statsMap, int uid) {
+        try {
+            statsMap.forEach((key, value) -> {
+                if (key.uid == uid) {
+                    try {
+                        statsMap.deleteEntry(key);
+                    } catch (ErrnoException e) {
+                        logErrorIfNotErrNoent(e, "Failed to delete data(uid = " + key.uid + ")");
+                    }
+                }
+            });
+        } catch (ErrnoException e) {
+            Log.e(TAG, "FAILED to delete tag data from stats map", e);
+        }
+    }
+
+    /**
+     * Deletes uid tag data from CookieTagMap, StatsMapA, StatsMapB, and UidStatsMap
+     * @param uid
+     */
+    private void deleteKernelTagData(int uid) {
+        try {
+            mCookieTagMap.forEach((key, value) -> {
+                // If SkDestroyListener deletes the socket tag while this code is running,
+                // forEach will either restart iteration from the beginning or return null,
+                // depending on when the deletion happens.
+                // If it returns null, continue iteration to delete the data and in fact it would
+                // just iterate from first key because BpfMap#getNextKey would return first key
+                // if the current key is not exist.
+                if (value != null && value.uid == uid) {
+                    try {
+                        mCookieTagMap.deleteEntry(key);
+                    } catch (ErrnoException e) {
+                        logErrorIfNotErrNoent(e, "Failed to delete data(cookie = " + key + ")");
+                    }
+                }
+            });
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Failed to delete tag data from cookie tag map", e);
+        }
+
+        deleteStatsMapTagData(mStatsMapA, uid);
+        deleteStatsMapTagData(mStatsMapB, uid);
+
+        try {
+            mUidCounterSetMap.deleteEntry(new U32(uid));
+        } catch (ErrnoException e) {
+            logErrorIfNotErrNoent(e, "Failed to delete tag data from uid counter set map");
+        }
+
+        try {
+            mAppUidStatsMap.deleteEntry(new UidStatsMapKey(uid));
+        } catch (ErrnoException e) {
+            logErrorIfNotErrNoent(e, "Failed to delete tag data from app uid stats map");
+        }
+    }
+
     /**
      * Clean up {@link #mUidRecorder} after UID is removed.
      */
@@ -1644,7 +1924,7 @@
 
         // Clear kernel stats associated with UID
         for (int uid : uids) {
-            resetKernelUidStats(uid);
+            deleteKernelTagData(uid);
         }
     }
 
@@ -1668,52 +1948,19 @@
         removeUidsLocked(CollectionUtils.toIntArray(uids));
     }
 
-    private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal {
-        @Override
-        public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
-            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes");
-            try {
-                return NetworkStatsService.this.getNetworkTotalBytes(template, start, end);
-            } finally {
-                Trace.traceEnd(TRACE_TAG_NETWORK);
-            }
+    /**
+     * Set the warning and limit to all registered custom network stats providers.
+     * Note that invocation of any interface will be sent to all providers.
+     */
+    public void setStatsProviderWarningAndLimitAsync(
+            @NonNull String iface, long warning, long limit) {
+        PermissionUtils.enforceNetworkStackPermission(mContext);
+        if (LOGV) {
+            Log.v(TAG, "setStatsProviderWarningAndLimitAsync("
+                    + iface + "," + warning + "," + limit + ")");
         }
-
-        @Override
-        public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
-            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes");
-            try {
-                return NetworkStatsService.this.getNetworkUidBytes(template, start, end);
-            } finally {
-                Trace.traceEnd(TRACE_TAG_NETWORK);
-            }
-        }
-
-        @Override
-        public void setUidForeground(int uid, boolean uidForeground) {
-            NetworkStatsService.this.setUidForeground(uid, uidForeground);
-        }
-
-        @Override
-        public void advisePersistThreshold(long thresholdBytes) {
-            NetworkStatsService.this.advisePersistThreshold(thresholdBytes);
-        }
-
-        @Override
-        public void forceUpdate() {
-            NetworkStatsService.this.forceUpdate();
-        }
-
-        @Override
-        public void setStatsProviderWarningAndLimitAsync(
-                @NonNull String iface, long warning, long limit) {
-            if (LOGV) {
-                Log.v(TAG, "setStatsProviderWarningAndLimitAsync("
-                        + iface + "," + warning + "," + limit + ")");
-            }
-            invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
-                    warning, limit));
-        }
+        invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
+                warning, limit));
     }
 
     @Override
@@ -1956,13 +2203,29 @@
      */
     // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
     //  tethering stats.
-    private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
+    private @NonNull NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
+         // We only need to return per-UID stats. Per-device stats are already counted by
+        // interface counters.
+        if (how != STATS_PER_UID) {
+            return new NetworkStats(SystemClock.elapsedRealtime(), 0);
+        }
+
+        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
         try {
-            return mNetworkManager.getNetworkStatsTethering(how);
+            final TetherStatsParcel[] tetherStatsParcels = mNetd.tetherGetStats();
+            for (TetherStatsParcel tetherStats : tetherStatsParcels) {
+                try {
+                    stats.combineValues(new NetworkStats.Entry(tetherStats.iface, UID_TETHERING,
+                            SET_DEFAULT, TAG_NONE, tetherStats.rxBytes, tetherStats.rxPackets,
+                            tetherStats.txBytes, tetherStats.txPackets, 0L));
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw new IllegalStateException("invalid tethering stats " + e);
+                }
+            }
         } catch (IllegalStateException e) {
             Log.wtf(TAG, "problem reading network stats", e);
-            return new NetworkStats(0L, 10);
         }
+        return stats;
     }
 
     // TODO: It is copied from ConnectivityService, consider refactor these check permission
@@ -2001,10 +2264,12 @@
                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
         Objects.requireNonNull(provider, "provider is null");
         Objects.requireNonNull(tag, "tag is null");
+        final NetworkPolicyManager netPolicyManager = mContext
+                .getSystemService(NetworkPolicyManager.class);
         try {
             NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
                     tag, provider, mStatsProviderSem, mAlertObserver,
-                    mStatsProviderCbList);
+                    mStatsProviderCbList, netPolicyManager);
             mStatsProviderCbList.add(callback);
             Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
                     + getCallingUid() + "/" + getCallingPid());
@@ -2044,8 +2309,9 @@
 
         @NonNull final INetworkStatsProvider mProvider;
         @NonNull private final Semaphore mSemaphore;
-        @NonNull final INetworkManagementEventObserver mAlertObserver;
+        @NonNull final AlertObserver mAlertObserver;
         @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
+        @NonNull final NetworkPolicyManager mNetworkPolicyManager;
 
         @NonNull private final Object mProviderStatsLock = new Object();
 
@@ -2058,8 +2324,9 @@
         NetworkStatsProviderCallbackImpl(
                 @NonNull String tag, @NonNull INetworkStatsProvider provider,
                 @NonNull Semaphore semaphore,
-                @NonNull INetworkManagementEventObserver alertObserver,
-                @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList)
+                @NonNull AlertObserver alertObserver,
+                @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList,
+                @NonNull NetworkPolicyManager networkPolicyManager)
                 throws RemoteException {
             mTag = tag;
             mProvider = provider;
@@ -2067,6 +2334,7 @@
             mSemaphore = semaphore;
             mAlertObserver = alertObserver;
             mStatsProviderCbList = cbList;
+            mNetworkPolicyManager = networkPolicyManager;
         }
 
         @NonNull
@@ -2106,15 +2374,14 @@
             // This binder object can only have been obtained by a process that holds
             // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
             BinderUtils.withCleanCallingIdentity(() ->
-                    mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
+                    mAlertObserver.onQuotaLimitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
         }
 
         @Override
         public void notifyWarningOrLimitReached() {
             Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
             BinderUtils.withCleanCallingIdentity(() ->
-                    LocalServices.getService(NetworkPolicyManagerInternal.class)
-                            .onStatsProviderWarningOrLimitReached(mTag));
+                    mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached());
         }
 
         @Override
@@ -2173,24 +2440,11 @@
      * {@link android.provider.Settings.Global}.
      */
     private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
-        private final ContentResolver mResolver;
-
-        public DefaultNetworkStatsSettings(Context context) {
-            mResolver = Objects.requireNonNull(context.getContentResolver());
-            // TODO: adjust these timings for production builds
-        }
-
-        private long getGlobalLong(String name, long def) {
-            return Settings.Global.getLong(mResolver, name, def);
-        }
-        private boolean getGlobalBoolean(String name, boolean def) {
-            final int defInt = def ? 1 : 0;
-            return Settings.Global.getInt(mResolver, name, defInt) != 0;
-        }
+        DefaultNetworkStatsSettings() {}
 
         @Override
         public long getPollInterval() {
-            return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
+            return 30 * MINUTE_IN_MILLIS;
         }
         @Override
         public long getPollDelay() {
@@ -2198,25 +2452,23 @@
         }
         @Override
         public long getGlobalAlertBytes(long def) {
-            return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
+            return def;
         }
         @Override
         public boolean getSampleEnabled() {
-            return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
+            return true;
         }
         @Override
         public boolean getAugmentEnabled() {
-            return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
+            return true;
         }
         @Override
         public boolean getCombineSubtypeEnabled() {
-            return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false);
+            return false;
         }
         @Override
         public Config getDevConfig() {
-            return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
-                    getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
-                    getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
+            return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
         }
         @Override
         public Config getXtConfig() {
@@ -2224,31 +2476,27 @@
         }
         @Override
         public Config getUidConfig() {
-            return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
-                    getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
-                    getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
+            return new Config(2 * HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
         }
         @Override
         public Config getUidTagConfig() {
-            return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
-                    getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
-                    getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
+            return new Config(2 * HOUR_IN_MILLIS, 5 * DAY_IN_MILLIS, 15 * DAY_IN_MILLIS);
         }
         @Override
         public long getDevPersistBytes(long def) {
-            return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
+            return def;
         }
         @Override
         public long getXtPersistBytes(long def) {
-            return getDevPersistBytes(def);
+            return def;
         }
         @Override
         public long getUidPersistBytes(long def) {
-            return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
+            return def;
         }
         @Override
         public long getUidTagPersistBytes(long def) {
-            return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
+            return def;
         }
     }
 
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index 4875f1c..5bba0b1 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -16,15 +16,14 @@
 
 package com.android.server.net;
 
-import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA;
-import static android.net.NetworkTemplate.getCollapsedRatType;
+import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA;
+import static android.app.usage.NetworkStatsManager.getCollapsedRatType;
 import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
 import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
 import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
 
 import android.annotation.NonNull;
 import android.content.Context;
-import android.telephony.Annotation;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyDisplayInfo;
@@ -57,10 +56,9 @@
          *
          * @param subscriberId IMSI of the subscription.
          * @param collapsedRatType collapsed RAT type.
-         *                         @see android.net.NetworkTemplate#getCollapsedRatType(int).
+         *                     @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int).
          */
-        void onCollapsedRatTypeChanged(@NonNull String subscriberId,
-                @Annotation.NetworkType int collapsedRatType);
+        void onCollapsedRatTypeChanged(@NonNull String subscriberId, int collapsedRatType);
     }
     private final Delegate mDelegate;
 
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
new file mode 100644
index 0000000..ea8d836
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Key for both stats maps.
+ */
+public class StatsMapKey extends Struct {
+    @Field(order = 0, type = Type.U32)
+    public final long uid;
+
+    @Field(order = 1, type = Type.U32)
+    public final long tag;
+
+    @Field(order = 2, type = Type.U32)
+    public final long counterSet;
+
+    @Field(order = 3, type = Type.U32)
+    public final long ifaceIndex;
+
+    public StatsMapKey(final long uid, final long tag, final long counterSet,
+            final long ifaceIndex) {
+        this.uid = uid;
+        this.tag = tag;
+        this.counterSet = counterSet;
+        this.ifaceIndex = ifaceIndex;
+    }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
new file mode 100644
index 0000000..48f26ce
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Value used for both stats maps and uid stats map.
+ */
+public class StatsMapValue extends Struct {
+    @Field(order = 0, type = Type.U63)
+    public final long rxPackets;
+
+    @Field(order = 1, type = Type.U63)
+    public final long rxBytes;
+
+    @Field(order = 2, type = Type.U63)
+    public final long txPackets;
+
+    @Field(order = 3, type = Type.U63)
+    public final long txBytes;
+
+    public StatsMapValue(final long rxPackets, final long rxBytes, final long txPackets,
+            final long txBytes) {
+        this.rxPackets = rxPackets;
+        this.rxBytes = rxBytes;
+        this.txPackets = txPackets;
+        this.txBytes = txBytes;
+    }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
new file mode 100644
index 0000000..2849f94
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Key for uid stats map.
+ */
+public class UidStatsMapKey extends Struct {
+    @Field(order = 0, type = Type.U32)
+    public final long uid;
+
+    public UidStatsMapKey(final long uid) {
+        this.uid = uid;
+    }
+}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
index 72230b4..4117d0f 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -177,7 +177,7 @@
                 ret = 0;
                 break;
             case SparseChunk.FILL:
-                ret = mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3];
+                ret = Byte.toUnsignedInt(mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3]);
                 break;
             default:
                 throw new IOException("Unsupported Chunk:" + mCur.toString());
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index a3eb0ecc..ce58ff6 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -236,7 +236,8 @@
                 root.flags |= Root.FLAG_REMOVABLE_USB;
             }
 
-            if (volume.getType() != VolumeInfo.TYPE_EMULATED) {
+            if (volume.getType() != VolumeInfo.TYPE_EMULATED
+                    && volume.getType() != VolumeInfo.TYPE_STUB) {
                 root.flags |= Root.FLAG_SUPPORTS_EJECT;
             }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index f5aa652..b4e84dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -27,9 +27,7 @@
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkTemplate;
-import android.net.wifi.WifiInfo;
 import android.os.AsyncTask;
-import android.text.TextUtils;
 import android.util.RecurrenceRule;
 
 import com.google.android.collect.Lists;
@@ -124,7 +122,7 @@
         if (policy != null) {
             return policy;
         } else {
-            return getPolicy(buildUnquotedNetworkTemplate(template));
+            return getPolicy(template);
         }
     }
 
@@ -207,21 +205,4 @@
         policy.clearSnooze();
         writeAsync();
     }
-
-    /**
-     * Build a revised {@link NetworkTemplate} that matches the same rule, but
-     * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
-     * around legacy bugs.
-     */
-    private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
-        if (template == null) return null;
-        final String networkId = template.getNetworkId();
-        final String strippedNetworkId = WifiInfo.sanitizeSsid(networkId);
-        if (!TextUtils.equals(strippedNetworkId, networkId)) {
-            return new NetworkTemplate(
-                    template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
-        } else {
-            return null;
-        }
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 99e3160..df19c67 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -173,8 +173,10 @@
     }
 
     public BluetoothDevice getActiveDevice() {
-        if (mService == null) return null;
-        return mService.getActiveDevice();
+        if (mBluetoothAdapter == null) return null;
+        final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+                .getActiveDevices(BluetoothProfile.A2DP);
+        return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
     }
 
     @Override
@@ -221,7 +223,7 @@
     }
 
     public boolean supportsHighQualityAudio(BluetoothDevice device) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         if (bluetoothDevice == null) {
             return false;
         }
@@ -234,7 +236,7 @@
      */
     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         if (bluetoothDevice == null) {
             return false;
         }
@@ -260,7 +262,7 @@
     }
 
     public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         if (bluetoothDevice == null) {
             return;
         }
@@ -286,7 +288,7 @@
      */
     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
         if (bluetoothDevice == null || !supportsHighQualityAudio(device)
                 || getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ddee433..233e798 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -500,6 +500,17 @@
     }
 
     /**
+     * Get identity address from remote device
+     * @return {@link BluetoothDevice#getIdentityAddress()} if
+     * {@link BluetoothDevice#getIdentityAddress()} is not null otherwise return
+     * {@link BluetoothDevice#getAddress()}
+     */
+    public String getIdentityAddress() {
+        final String identityAddress = mDevice.getIdentityAddress();
+        return TextUtils.isEmpty(identityAddress) ? getAddress() : identityAddress;
+    }
+
+    /**
      * Get name from remote device
      * @return {@link BluetoothDevice#getAlias()} if
      * {@link BluetoothDevice#getAlias()} is not null otherwise return
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 9dd329e..b44d914 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -132,10 +132,12 @@
     }
 
     public BluetoothDevice getActiveDevice() {
-        if (mService == null) {
+        if (mBluetoothAdapter == null) {
             return null;
         }
-        return mService.getActiveDevice();
+        final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+                .getActiveDevices(BluetoothProfile.HEADSET);
+        return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
     }
 
     public boolean isAudioOn() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index a1fba4a..ff1368a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -168,8 +168,10 @@
     }
 
     public List<BluetoothDevice> getActiveDevices() {
-        if (mService == null) return new ArrayList<>();
-        return mService.getActiveDevices();
+        if (mBluetoothAdapter == null) {
+            return new ArrayList<>();
+        }
+        return mBluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index 209507a..db6d41e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -21,12 +21,12 @@
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
 
-import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
@@ -177,10 +177,10 @@
     }
 
     public List<BluetoothDevice> getActiveDevices() {
-        if (mService == null) {
+        if (mBluetoothAdapter == null) {
             return new ArrayList<>();
         }
-        return mService.getActiveDevices();
+        return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS b/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS
new file mode 100644
index 0000000..98f4123
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS
@@ -0,0 +1,3 @@
+# Default reviewers for this and subdirectories.
+alexflo@google.com
+chrisgollner@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index b4c95e6..2c2be03 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -39,6 +39,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
 import java.util.zip.GZIPInputStream;
 
 /**
@@ -54,6 +56,7 @@
     private static final String TAG_FILE_NAME = "file-name";
     private static final String TAG_FILE_CONTENT = "file-content";
     private static final String ATTR_CONTENT_ID = "contentId";
+    private static final String ATTR_LIBRARY_NAME = "lib";
 
     private static final String HTML_HEAD_STRING =
             "<html><head>\n"
@@ -67,8 +70,12 @@
             + "</style>\n"
             + "</head>"
             + "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n"
-            + "<div class=\"toc\">\n"
-            + "<ul>";
+            + "<div class=\"toc\">\n";
+    private static final String LIBRARY_HEAD_STRING =
+            "<strong>Libraries</strong>\n<ul class=\"libraries\">";
+    private static final String LIBRARY_TAIL_STRING = "</ul>\n<strong>Files</strong>";
+
+    private static final String FILES_HEAD_STRING = "<ul class=\"files\">";
 
     private static final String HTML_MIDDLE_STRING =
             "</ul>\n"
@@ -81,12 +88,14 @@
     private final List<File> mXmlFiles;
 
     /*
-     * A map from a file name to a content id (MD5 sum of file content) for its license.
-     * For example, "/system/priv-app/TeleService/TeleService.apk" maps to
+     * A map from a file name to a library name (may be empty) to a content id (MD5 sum of file
+     * content) for its license.
+     * For example, "/system/priv-app/TeleService/TeleService.apk" maps to "service/Telephony" to
      * "9645f39e9db895a4aa6e02cb57294595". Here "9645f39e9db895a4aa6e02cb57294595" is a MD5 sum
      * of the content of packages/services/Telephony/MODULE_LICENSE_APACHE2.
      */
-    private final Map<String, Set<String>> mFileNameToContentIdMap = new HashMap();
+    private final Map<String, Map<String, Set<String>>> mFileNameToLibraryToContentIdMap =
+            new HashMap();
 
     /*
      * A map from a content id (MD5 sum of file content) to a license file content.
@@ -98,7 +107,7 @@
 
     static class ContentIdAndFileNames {
         final String mContentId;
-        final List<String> mFileNameList = new ArrayList();
+        final Map<String, List<String>> mLibraryToFileNameMap = new TreeMap();
 
         ContentIdAndFileNames(String contentId) {
             mContentId = contentId;
@@ -120,7 +129,7 @@
             parse(xmlFile);
         }
 
-        if (mFileNameToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) {
+        if (mFileNameToLibraryToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) {
             return false;
         }
 
@@ -128,7 +137,7 @@
         try {
             writer = new PrintWriter(outputFile);
 
-            generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer,
+            generateHtml(mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap, writer,
                 noticeHeader);
 
             writer.flush();
@@ -157,7 +166,7 @@
                 in = new FileReader(xmlFile);
             }
 
-            parse(in, mFileNameToContentIdMap, mContentIdToFileContentMap);
+            parse(in, mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap);
 
             in.close();
         } catch (XmlPullParserException | IOException e) {
@@ -180,7 +189,8 @@
      *
      *     <licenses>
      *     <file-name contentId="content_id_of_license1">file1</file-name>
-     *     <file-name contentId="content_id_of_license2">file2</file-name>
+     *     <file-name contentId="content_id_of_license2" lib="name of library">file2</file-name>
+     *     <file-name contentId="content_id_of_license2" lib="another library">file2</file-name>
      *     ...
      *     <file-content contentId="content_id_of_license1">license1 file contents</file-content>
      *     <file-content contentId="content_id_of_license2">license2 file contents</file-content>
@@ -188,10 +198,12 @@
      *     </licenses>
      */
     @VisibleForTesting
-    static void parse(InputStreamReader in, Map<String, Set<String>> outFileNameToContentIdMap,
+    static void parse(InputStreamReader in,
+            Map<String, Map<String, Set<String>>> outFileNameToLibraryToContentIdMap,
             Map<String, String> outContentIdToFileContentMap)
                     throws XmlPullParserException, IOException {
-        Map<String, Set<String>> fileNameToContentIdMap = new HashMap<String, Set<String>>();
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap =
+                new HashMap<String, Map<String, Set<String>>>();
         Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
 
         XmlPullParser parser = Xml.newPullParser();
@@ -205,12 +217,15 @@
             if (state == XmlPullParser.START_TAG) {
                 if (TAG_FILE_NAME.equals(parser.getName())) {
                     String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID);
+                    String libraryName = parser.getAttributeValue("", ATTR_LIBRARY_NAME);
                     if (!TextUtils.isEmpty(contentId)) {
                         String fileName = readText(parser).trim();
                         if (!TextUtils.isEmpty(fileName)) {
-                            Set<String> contentIds =
-                                    fileNameToContentIdMap.computeIfAbsent(
-                                            fileName, k -> new HashSet<>());
+                            Map<String, Set<String>> libs =
+                                    fileNameToLibraryToContentIdMap.computeIfAbsent(
+                                            fileName, k -> new HashMap<>());
+                            Set<String> contentIds = libs.computeIfAbsent(
+                                            libraryName, k -> new HashSet<>());
                             contentIds.add(contentId);
                         }
                     }
@@ -229,11 +244,17 @@
 
             state = parser.next();
         }
-        for (Map.Entry<String, Set<String>> entry : fileNameToContentIdMap.entrySet()) {
-            outFileNameToContentIdMap.merge(
-                    entry.getKey(), entry.getValue(), (s1, s2) -> {
-                        s1.addAll(s2);
-                        return s1;
+        for (Map.Entry<String, Map<String, Set<String>>> mapEntry :
+                fileNameToLibraryToContentIdMap.entrySet()) {
+            outFileNameToLibraryToContentIdMap.merge(
+                    mapEntry.getKey(), mapEntry.getValue(), (m1, m2) -> {
+                        for (Map.Entry<String, Set<String>> entry : m2.entrySet()) {
+                            m1.merge(entry.getKey(), entry.getValue(), (s1, s2) -> {
+                                s1.addAll(s2);
+                                return s1;
+                            });
+                        }
+                        return m1;
                     });
         }
         outContentIdToFileContentMap.putAll(contentIdToFileContentMap);
@@ -251,13 +272,28 @@
     }
 
     @VisibleForTesting
-    static void generateHtml(Map<String, Set<String>> fileNameToContentIdMap,
+    static void generateHtml(Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap,
             Map<String, String> contentIdToFileContentMap, PrintWriter writer,
             String noticeHeader) {
         List<String> fileNameList = new ArrayList();
-        fileNameList.addAll(fileNameToContentIdMap.keySet());
+        fileNameList.addAll(fileNameToLibraryToContentIdMap.keySet());
         Collections.sort(fileNameList);
 
+        SortedMap<String, Set<String>> libraryToContentIdMap = new TreeMap();
+        for (Map<String, Set<String>> libraryToContentValue :
+                fileNameToLibraryToContentIdMap.values()) {
+            for (Map.Entry<String, Set<String>> entry : libraryToContentValue.entrySet()) {
+                if (TextUtils.isEmpty(entry.getKey())) {
+                    continue;
+                }
+                libraryToContentIdMap.merge(
+                        entry.getKey(), entry.getValue(), (s1, s2) -> {
+                            s1.addAll(s2);
+                            return s1;
+                        });
+            }
+        }
+
         writer.println(HTML_HEAD_STRING);
 
         if (!TextUtils.isEmpty(noticeHeader)) {
@@ -268,21 +304,56 @@
         Map<String, Integer> contentIdToOrderMap = new HashMap();
         List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList();
 
+        if (!libraryToContentIdMap.isEmpty()) {
+            writer.println(LIBRARY_HEAD_STRING);
+            for (Map.Entry<String, Set<String>> entry: libraryToContentIdMap.entrySet()) {
+                String libraryName = entry.getKey();
+                for (String contentId : entry.getValue()) {
+                    // Assigns an id to a newly referred license file content.
+                    if (!contentIdToOrderMap.containsKey(contentId)) {
+                        contentIdToOrderMap.put(contentId, count);
+
+                        // An index in contentIdAndFileNamesList is the order of each element.
+                        contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
+                        count++;
+                    }
+                    int id = contentIdToOrderMap.get(contentId);
+                    writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, libraryName);
+                }
+            }
+            writer.println(LIBRARY_TAIL_STRING);
+        }
+
         // Prints all the file list with a link to its license file content.
         for (String fileName : fileNameList) {
-            for (String contentId : fileNameToContentIdMap.get(fileName)) {
-                // Assigns an id to a newly referred license file content.
-                if (!contentIdToOrderMap.containsKey(contentId)) {
-                    contentIdToOrderMap.put(contentId, count);
-
-                    // An index in contentIdAndFileNamesList is the order of each element.
-                    contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
-                    count++;
+            for (Map.Entry<String, Set<String>> libToContentId :
+                    fileNameToLibraryToContentIdMap.get(fileName).entrySet()) {
+                String libraryName = libToContentId.getKey();
+                if (libraryName == null) {
+                    libraryName = "";
                 }
+                for (String contentId : libToContentId.getValue()) {
+                    // Assigns an id to a newly referred license file content.
+                    if (!contentIdToOrderMap.containsKey(contentId)) {
+                        contentIdToOrderMap.put(contentId, count);
 
-                int id = contentIdToOrderMap.get(contentId);
-                contentIdAndFileNamesList.get(id).mFileNameList.add(fileName);
-                writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName);
+                        // An index in contentIdAndFileNamesList is the order of each element.
+                        contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
+                        count++;
+                    }
+
+                    int id = contentIdToOrderMap.get(contentId);
+                    ContentIdAndFileNames elem = contentIdAndFileNamesList.get(id);
+                    List<String> files = elem.mLibraryToFileNameMap.computeIfAbsent(
+                            libraryName, k -> new ArrayList());
+                    files.add(fileName);
+                    if (TextUtils.isEmpty(libraryName)) {
+                        writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName);
+                    } else {
+                        writer.format("<li><a href=\"#id%d\">%s - %s</a></li>\n",
+                                id, fileName, libraryName);
+                    }
+                }
             }
         }
 
@@ -292,19 +363,27 @@
         // Prints all contents of the license files in order of id.
         for (ContentIdAndFileNames contentIdAndFileNames : contentIdAndFileNamesList) {
             writer.format("<tr id=\"id%d\"><td class=\"same-license\">\n", count);
-            writer.println("<div class=\"label\">Notices for file(s):</div>");
-            writer.println("<div class=\"file-list\">");
-            for (String fileName : contentIdAndFileNames.mFileNameList) {
-                writer.format("%s <br/>\n", fileName);
+            for (Map.Entry<String, List<String>> libraryFiles :
+                    contentIdAndFileNames.mLibraryToFileNameMap.entrySet()) {
+                String libraryName = libraryFiles.getKey();
+                if (TextUtils.isEmpty(libraryName)) {
+                    writer.println("<div class=\"label\">Notices for file(s):</div>");
+                } else {
+                    writer.format("<div class=\"label\"><strong>%s</strong> used by:</div>\n",
+                            libraryName);
+                }
+                writer.println("<div class=\"file-list\">");
+                for (String fileName : libraryFiles.getValue()) {
+                    writer.format("%s <br/>\n", fileName);
+                }
+                writer.println("</div><!-- file-list -->");
+                count++;
             }
-            writer.println("</div><!-- file-list -->");
             writer.println("<pre class=\"license-text\">");
             writer.println(contentIdToFileContentMap.get(
                     contentIdAndFileNames.mContentId));
             writer.println("</pre><!-- license-text -->");
             writer.println("</td></tr><!-- same-license -->");
-
-            count++;
         }
 
         writer.println(HTML_REAR_STRING);
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
new file mode 100644
index 0000000..ab9b5dc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
@@ -0,0 +1,4 @@
+# Default reviewers for this and subdirectories.
+bonianchen@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java
index e30aac5..a69c59c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java
@@ -16,12 +16,18 @@
 
 package com.android.settingslib.net;
 
-import android.net.NetworkStatsHistory;
+import android.app.usage.NetworkStats;
+
+import java.util.List;
 
 public class ChartData {
-    public NetworkStatsHistory network;
+    // Collect the data usage history of the network from the given {@link NetworkTemplate}.
+    public List<NetworkStats.Bucket> network;
 
-    public NetworkStatsHistory detail;
-    public NetworkStatsHistory detailDefault;
-    public NetworkStatsHistory detailForeground;
+    // Collect the detail datausage history (foreground + Background).
+    public List<NetworkStats.Bucket> detail;
+    // Collect background datausage history.
+    public List<NetworkStats.Bucket> detailDefault;
+    // Collect foreground datausage history.
+    public List<NetworkStats.Bucket> detailForeground;
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
index 60d22a0..573922f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
@@ -19,20 +19,21 @@
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
-import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
-import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 
+import android.annotation.NonNull;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
 import android.content.AsyncTaskLoader;
 import android.content.Context;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
 import android.os.RemoteException;
 
 import com.android.settingslib.AppItem;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Framework loader is deprecated, use the compat version instead.
  *
@@ -42,26 +43,20 @@
 public class ChartDataLoader extends AsyncTaskLoader<ChartData> {
     private static final String KEY_TEMPLATE = "template";
     private static final String KEY_APP = "app";
-    private static final String KEY_FIELDS = "fields";
 
-    private final INetworkStatsSession mSession;
+    private final NetworkStatsManager mNetworkStatsManager;
     private final Bundle mArgs;
 
     public static Bundle buildArgs(NetworkTemplate template, AppItem app) {
-        return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES);
-    }
-
-    public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) {
         final Bundle args = new Bundle();
         args.putParcelable(KEY_TEMPLATE, template);
         args.putParcelable(KEY_APP, app);
-        args.putInt(KEY_FIELDS, fields);
         return args;
     }
 
-    public ChartDataLoader(Context context, INetworkStatsSession session, Bundle args) {
+    public ChartDataLoader(Context context, NetworkStatsManager statsManager, Bundle args) {
         super(context);
-        mSession = session;
+        mNetworkStatsManager = statsManager;
         mArgs = args;
     }
 
@@ -75,10 +70,9 @@
     public ChartData loadInBackground() {
         final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
         final AppItem app = mArgs.getParcelable(KEY_APP);
-        final int fields = mArgs.getInt(KEY_FIELDS);
 
         try {
-            return loadInBackground(template, app, fields);
+            return loadInBackground(template, app);
         } catch (RemoteException e) {
             // since we can't do much without history, and we don't want to
             // leave with half-baked UI, we bail hard.
@@ -86,10 +80,22 @@
         }
     }
 
-    private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields)
+    @NonNull
+    private List<NetworkStats.Bucket> convertToBuckets(@NonNull NetworkStats stats) {
+        final List<NetworkStats.Bucket> ret = new ArrayList<>();
+        while (stats.hasNextBucket()) {
+            final NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+            stats.getNextBucket(bucket);
+            ret.add(bucket);
+        }
+        return ret;
+    }
+
+    private ChartData loadInBackground(NetworkTemplate template, AppItem app)
             throws RemoteException {
         final ChartData data = new ChartData();
-        data.network = mSession.getHistoryForNetwork(template, fields);
+        data.network = convertToBuckets(mNetworkStatsManager.queryDetailsForDevice(
+                template, Long.MIN_VALUE, Long.MAX_VALUE));
 
         if (app != null) {
             // load stats for current uid and template
@@ -103,13 +109,13 @@
             }
 
             if (size > 0) {
-                data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration());
-                data.detail.recordEntireHistory(data.detailDefault);
-                data.detail.recordEntireHistory(data.detailForeground);
+                data.detail = new ArrayList<>();
+                data.detail.addAll(data.detailDefault);
+                data.detail.addAll(data.detailForeground);
             } else {
-                data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS);
-                data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS);
-                data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS);
+                data.detailDefault = new ArrayList<>();
+                data.detailForeground = new ArrayList<>();
+                data.detail = new ArrayList<>();
             }
         }
 
@@ -129,17 +135,17 @@
     }
 
     /**
-     * Collect {@link NetworkStatsHistory} for the requested UID, combining with
-     * an existing {@link NetworkStatsHistory} if provided.
+     * Collect {@link List<NetworkStats.Bucket>} for the requested UID, combining with
+     * an existing {@link List<NetworkStats.Bucket>} if provided.
      */
-    private NetworkStatsHistory collectHistoryForUid(
-            NetworkTemplate template, int uid, int set, NetworkStatsHistory existing)
-            throws RemoteException {
-        final NetworkStatsHistory history = mSession.getHistoryForUid(
-                template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
+    private List<NetworkStats.Bucket> collectHistoryForUid(
+            NetworkTemplate template, int uid, int set, List<NetworkStats.Bucket> existing) {
+        final List<NetworkStats.Bucket> history = convertToBuckets(
+                mNetworkStatsManager.queryDetailsForUidTagState(template,
+                        Long.MIN_VALUE, Long.MAX_VALUE, uid, TAG_NONE, set));
 
         if (existing != null) {
-            existing.recordEntireHistory(history);
+            existing.addAll(history);
             return existing;
         } else {
             return history;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index cff45c6..30c6645 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -16,7 +16,6 @@
 
 package com.android.settingslib.net;
 
-import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.telephony.TelephonyManager.SIM_STATE_READY;
 import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
 import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
@@ -49,6 +48,7 @@
     private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
     private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
             PERIOD_BUILDER, Locale.getDefault());
+    private static final long MB_IN_BYTES = 1024 * 1024;
 
     private final Context mContext;
     private final NetworkPolicyManager mPolicyManager;
@@ -237,10 +237,8 @@
         final int matchRule = networkTemplate.getMatchRule();
         switch (matchRule) {
             case NetworkTemplate.MATCH_MOBILE:
-            case NetworkTemplate.MATCH_MOBILE_WILDCARD:
                 return ConnectivityManager.TYPE_MOBILE;
             case NetworkTemplate.MATCH_WIFI:
-            case NetworkTemplate.MATCH_WIFI_WILDCARD:
                 return  ConnectivityManager.TYPE_WIFI;
             case NetworkTemplate.MATCH_ETHERNET:
                 return  ConnectivityManager.TYPE_ETHERNET;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index afd44d5..386a47a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -63,14 +63,32 @@
     private static NetworkTemplate getNormalizedMobileTemplate(
             TelephonyManager telephonyManager, int subId) {
         final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId);
-        final String[] mergedSubscriberIds = telephonyManager
-                .createForSubscriptionId(subId).getMergedImsisFromGroup();
+        final Set<String> mergedSubscriberIds = Set.of(telephonyManager
+                .createForSubscriptionId(subId).getMergedImsisFromGroup());
         if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
             Log.i(TAG, "mergedSubscriberIds is null.");
             return mobileTemplate;
         }
 
-        return NetworkTemplate.normalize(mobileTemplate, mergedSubscriberIds);
+        return normalizeMobileTemplate(mobileTemplate, mergedSubscriberIds);
+    }
+
+    private static NetworkTemplate normalizeMobileTemplate(
+            NetworkTemplate template, Set<String> mergedSet) {
+        if (template.getSubscriberIds().isEmpty()) return template;
+        // The input template should have at most 1 subscriberId.
+        final String subscriberId = template.getSubscriberIds().iterator().next();
+
+        if (mergedSet.contains(subscriberId)) {
+            // Requested template subscriber is part of the merge group; return
+            // a template that matches all merged subscribers.
+            return new NetworkTemplate.Builder(template.getMatchRule())
+                    .setSubscriberIds(mergedSet)
+                    .setWifiNetworkKeys(template.getWifiNetworkKeys())
+                    .setMeteredness(NetworkStats.METERED_YES).build();
+        }
+
+        return template;
     }
 
     private static NetworkTemplate getMobileTemplateForSubId(
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
index 43c05b8..504390c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
@@ -53,8 +53,9 @@
             long totalUsage = 0L;
             long totalForeground = 0L;
             for (int uid : mUids) {
-                final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid(
-                        mNetworkTemplate, start, end, uid);
+                final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState(
+                        mNetworkTemplate, start, end, uid, NetworkStats.Bucket.TAG_NONE,
+                        NetworkStats.Bucket.STATE_ALL);
                 final long usage = getTotalUsage(stats);
                 if (usage > 0L) {
                     totalUsage += usage;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
index 3e95b01..5e9ac5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
@@ -16,23 +16,16 @@
 
 package com.android.settingslib.net;
 
-import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
-import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
-
+import android.annotation.NonNull;
 import android.app.usage.NetworkStats;
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.text.format.DateUtils;
 import android.util.Pair;
+import android.util.Range;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.loader.content.AsyncTaskLoader;
@@ -52,8 +45,6 @@
     protected final NetworkTemplate mNetworkTemplate;
     private final NetworkPolicy mPolicy;
     private final ArrayList<Long> mCycles;
-    @VisibleForTesting
-    final INetworkStatsService mNetworkStatsService;
 
     protected NetworkCycleDataLoader(Builder<?> builder) {
         super(builder.mContext);
@@ -61,8 +52,6 @@
         mCycles = builder.mCycles;
         mNetworkStatsManager = (NetworkStatsManager)
             builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
-        mNetworkStatsService = INetworkStatsService.Stub.asInterface(
-            ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
         final NetworkPolicyEditor policyEditor =
             new NetworkPolicyEditor(NetworkPolicyManager.from(builder.mContext));
         policyEditor.read();
@@ -112,23 +101,20 @@
 
     @VisibleForTesting
     void loadFourWeeksData() {
+        if (mNetworkTemplate == null) return;
+        final NetworkStats stats = mNetworkStatsManager.queryDetailsForDevice(
+                mNetworkTemplate, Long.MIN_VALUE, Long.MAX_VALUE);
         try {
-            final INetworkStatsSession networkSession = mNetworkStatsService.openSession();
-            final NetworkStatsHistory networkHistory = networkSession.getHistoryForNetwork(
-                mNetworkTemplate, FIELD_RX_BYTES | FIELD_TX_BYTES);
-            final long historyStart = networkHistory.getStart();
-            final long historyEnd = networkHistory.getEnd();
+            final Range<Long> historyTimeRange = getTimeRangeOf(stats);
 
-            long cycleEnd = historyEnd;
-            while (cycleEnd > historyStart) {
+            long cycleEnd = historyTimeRange.getUpper();
+            while (cycleEnd > historyTimeRange.getLower()) {
                 final long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4);
                 recordUsage(cycleStart, cycleEnd);
                 cycleEnd = cycleStart;
             }
-
-            TrafficStats.closeQuietly(networkSession);
-        } catch (RemoteException e) {
-            throw new RuntimeException(e);
+        } catch (IllegalArgumentException e) {
+            // Empty history, ignore.
         }
     }
 
@@ -169,6 +155,32 @@
         return bytes;
     }
 
+    @NonNull
+    @VisibleForTesting
+    Range getTimeRangeOf(@NonNull NetworkStats stats) {
+        long start = Long.MAX_VALUE;
+        long end = Long.MIN_VALUE;
+        while (hasNextBucket(stats)) {
+            final NetworkStats.Bucket bucket = getNextBucket(stats);
+            start = Math.min(start, bucket.getStartTimeStamp());
+            end = Math.max(end, bucket.getEndTimeStamp());
+        }
+        return new Range(start, end);
+    }
+
+    @VisibleForTesting
+    boolean hasNextBucket(@NonNull NetworkStats stats) {
+        return stats.hasNextBucket();
+    }
+
+    @NonNull
+    @VisibleForTesting
+    NetworkStats.Bucket getNextBucket(@NonNull NetworkStats stats) {
+        NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+        stats.getNextBucket(bucket);
+        return bucket;
+    }
+
     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
     public ArrayList<Long> getCycles() {
         return mCycles;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/OWNERS b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
new file mode 100644
index 0000000..ab9b5dc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
@@ -0,0 +1,4 @@
+# Default reviewers for this and subdirectories.
+bonianchen@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
index 649aeff..8da6032 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
@@ -16,13 +16,12 @@
 
 package com.android.settingslib.net;
 
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
 import android.content.AsyncTaskLoader;
 import android.content.Context;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStats;
 import android.net.NetworkTemplate;
 import android.os.Bundle;
-import android.os.RemoteException;
 
 /**
  * Framework loader is deprecated, use the compat version instead.
@@ -35,7 +34,7 @@
     private static final String KEY_START = "start";
     private static final String KEY_END = "end";
 
-    private final INetworkStatsSession mSession;
+    private final NetworkStatsManager mNetworkStatsManager;
     private final Bundle mArgs;
 
     public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
@@ -46,9 +45,9 @@
         return args;
     }
 
-    public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) {
+    public SummaryForAllUidLoader(Context context, Bundle args) {
         super(context);
-        mSession = session;
+        mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
         mArgs = args;
     }
 
@@ -63,12 +62,7 @@
         final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
         final long start = mArgs.getLong(KEY_START);
         final long end = mArgs.getLong(KEY_END);
-
-        try {
-            return mSession.getSummaryForAllUid(template, start, end, false);
-        } catch (RemoteException e) {
-            return null;
-        }
+        return mNetworkStatsManager.querySummary(template, start, end);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index 02326ea..623eb33 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.net;
 
 import android.app.AppGlobals;
+import android.app.usage.NetworkStats;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
@@ -116,13 +117,13 @@
                 detail.label = res.getString(R.string.process_kernel_label);
                 detail.icon = pm.getDefaultActivityIcon();
                 return detail;
-            case TrafficStats.UID_REMOVED:
+            case NetworkStats.Bucket.UID_REMOVED:
                 detail.label = res.getString(UserManager.supportsMultipleUsers()
                         ? R.string.data_usage_uninstalled_apps_users
                         : R.string.data_usage_uninstalled_apps);
                 detail.icon = pm.getDefaultActivityIcon();
                 return detail;
-            case TrafficStats.UID_TETHERING:
+            case NetworkStats.Bucket.UID_TETHERING:
                 final TetheringManager tm = mContext.getSystemService(TetheringManager.class);
                 detail.label = res.getString(Utils.getTetheringLabel(tm));
                 detail.icon = pm.getDefaultActivityIcon();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index f167721..bb6b293 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -60,6 +60,8 @@
     private BluetoothDevice mDevice;
     @Mock
     private BluetoothA2dp mBluetoothA2dp;
+    @Mock
+    private BluetoothAdapter mBluetoothAdapter;
     private BluetoothProfile.ServiceListener mServiceListener;
 
     private A2dpProfile mProfile;
@@ -72,7 +74,8 @@
         mProfile = new A2dpProfile(mContext, mDeviceManager, mProfileManager);
         mServiceListener = mShadowBluetoothAdapter.getServiceListener();
         mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
-        when(mBluetoothA2dp.getActiveDevice()).thenReturn(mDevice);
+        when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+                .thenReturn(Arrays.asList(mDevice));
     }
 
     @Test
@@ -203,9 +206,8 @@
 
         when(config.isMandatoryCodec()).thenReturn(false);
         when(config.getCodecType()).thenReturn(4);
-        when(config.getCodecName()).thenReturn("LDAC");
         assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(
-                String.format(KNOWN_CODEC_LABEL, config.getCodecName()));
+                String.format(KNOWN_CODEC_LABEL, "LDAC"));
     }
 
     @Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index d53a3e8..298ee90 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -28,6 +28,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
+import android.os.Parcel;
 import android.os.ParcelUuid;
 
 import org.junit.Before;
@@ -60,9 +61,9 @@
     private final static Map<Integer, ParcelUuid> CAP_GROUP2 =
             Map.of(2, BluetoothUuid.CAP);
     private final BluetoothClass DEVICE_CLASS_1 =
-        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
     private final BluetoothClass DEVICE_CLASS_2 =
-        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
     @Mock
     private LocalBluetoothProfileManager mLocalProfileManager;
     @Mock
@@ -92,6 +93,16 @@
     private HearingAidDeviceManager mHearingAidDeviceManager;
     private Context mContext;
 
+    private BluetoothClass createBtClass(int deviceClass) {
+        Parcel p = Parcel.obtain();
+        p.writeInt(deviceClass);
+        p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+        BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+        p.recycle();
+        return bluetoothClass;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index 7be176a..a8e6075 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -28,6 +28,7 @@
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
+import android.os.Parcel;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +49,7 @@
     private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
     private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
     private final BluetoothClass DEVICE_CLASS =
-            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
     @Mock
     private LocalBluetoothProfileManager mLocalProfileManager;
     @Mock
@@ -67,6 +68,16 @@
     private HearingAidDeviceManager mHearingAidDeviceManager;
     private Context mContext;
 
+    private BluetoothClass createBtClass(int deviceClass) {
+        Parcel p = Parcel.obtain();
+        p.writeInt(deviceClass);
+        p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+        BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+        p.recycle();
+        return bluetoothClass;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index e87461f..e348865 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -36,7 +36,7 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class LicenseHtmlGeneratorFromXmlTest {
-    private static final String VALILD_XML_STRING =
+    private static final String VALID_OLD_XML_STRING =
             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
             + "<licenses>\n"
             + "<file-name contentId=\"0\">/file0</file-name>\n"
@@ -44,7 +44,15 @@
             + "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n"
             + "</licenses>";
 
-    private static final String INVALILD_XML_STRING =
+    private static final String VALID_NEW_XML_STRING =
+            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+            + "<licenses>\n"
+            + "<file-name contentId=\"0\" lib=\"libA\">/file0</file-name>\n"
+            + "<file-name contentId=\"0\" lib=\"libB\">/file1</file-name>\n"
+            + "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n"
+            + "</licenses>";
+
+    private static final String INVALID_XML_STRING =
             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
             + "<licenses2>\n"
             + "<file-name contentId=\"0\">/file0</file-name>\n"
@@ -64,13 +72,13 @@
             + "</style>\n"
             + "</head>"
             + "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n"
-            + "<div class=\"toc\">\n"
-            + "<ul>\n";
+            + "<div class=\"toc\">\n";
 
     private static final String HTML_CUSTOM_HEADING = "Custom heading";
 
-    private static final String HTML_BODY_STRING =
-            "<li><a href=\"#id0\">/file0</a></li>\n"
+    private static final String HTML_OLD_BODY_STRING =
+            "<ul class=\"files\">\n"
+            + "<li><a href=\"#id0\">/file0</a></li>\n"
             + "<li><a href=\"#id1\">/file0</a></li>\n"
             + "<li><a href=\"#id0\">/file1</a></li>\n"
             + "</ul>\n"
@@ -97,66 +105,181 @@
             + "</td></tr><!-- same-license -->\n"
             + "</table></body></html>\n";
 
-    private static final String EXPECTED_HTML_STRING = HTML_HEAD_STRING + HTML_BODY_STRING;
+    private static final String HTML_NEW_BODY_STRING =
+            "<strong>Libraries</strong>\n"
+            + "<ul class=\"libraries\">\n"
+            + "<li><a href=\"#id0\">libA</a></li>\n"
+            + "<li><a href=\"#id1\">libB</a></li>\n"
+            + "</ul>\n"
+            + "<strong>Files</strong>\n"
+            + "<ul class=\"files\">\n"
+            + "<li><a href=\"#id0\">/file0 - libA</a></li>\n"
+            + "<li><a href=\"#id1\">/file0 - libB</a></li>\n"
+            + "<li><a href=\"#id0\">/file1 - libA</a></li>\n"
+            + "</ul>\n"
+            + "</div><!-- table of contents -->\n"
+            + "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n"
+            + "<tr id=\"id0\"><td class=\"same-license\">\n"
+            + "<div class=\"label\">Notices for file(s):</div>\n"
+            + "<div class=\"file-list\">\n"
+            + "/file0 <br/>\n"
+            + "/file1 <br/>\n"
+            + "</div><!-- file-list -->\n"
+            + "<pre class=\"license-text\">\n"
+            + "license content #0\n"
+            + "</pre><!-- license-text -->\n"
+            + "</td></tr><!-- same-license -->\n"
+            + "<tr id=\"id1\"><td class=\"same-license\">\n"
+            + "<div class=\"label\">Notices for file(s):</div>\n"
+            + "<div class=\"file-list\">\n"
+            + "/file0 <br/>\n"
+            + "</div><!-- file-list -->\n"
+            + "<pre class=\"license-text\">\n"
+            + "license content #1\n"
+            + "</pre><!-- license-text -->\n"
+            + "</td></tr><!-- same-license -->\n"
+            + "</table></body></html>\n";
 
-    private static final String EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING =
-            HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_BODY_STRING;
+    private static final String EXPECTED_OLD_HTML_STRING = HTML_HEAD_STRING + HTML_OLD_BODY_STRING;
+
+    private static final String EXPECTED_NEW_HTML_STRING = HTML_HEAD_STRING + HTML_NEW_BODY_STRING;
+
+    private static final String EXPECTED_OLD_HTML_STRING_WITH_CUSTOM_HEADING =
+            HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_OLD_BODY_STRING;
+
+    private static final String EXPECTED_NEW_HTML_STRING_WITH_CUSTOM_HEADING =
+            HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_NEW_BODY_STRING;
 
     @Test
     public void testParseValidXmlStream() throws XmlPullParserException, IOException {
-        Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
         Map<String, String> contentIdToFileContentMap = new HashMap<>();
 
         LicenseHtmlGeneratorFromXml.parse(
-                new InputStreamReader(new ByteArrayInputStream(VALILD_XML_STRING.getBytes())),
-                fileNameToContentIdMap, contentIdToFileContentMap);
-        assertThat(fileNameToContentIdMap.size()).isEqualTo(2);
-        assertThat(fileNameToContentIdMap.get("/file0")).containsExactly("0");
-        assertThat(fileNameToContentIdMap.get("/file1")).containsExactly("0");
+                new InputStreamReader(new ByteArrayInputStream(VALID_OLD_XML_STRING.getBytes())),
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap);
+        assertThat(fileNameToLibraryToContentIdMap.size()).isEqualTo(1);
+        assertThat(fileNameToLibraryToContentIdMap.get("").size()).isEqualTo(2);
+        assertThat(fileNameToLibraryToContentIdMap.get("").get("/file0")).containsExactly("0");
+        assertThat(fileNameToLibraryToContentIdMap.get("").get("/file1")).containsExactly("0");
+        assertThat(contentIdToFileContentMap.size()).isEqualTo(1);
+        assertThat(contentIdToFileContentMap.get("0")).isEqualTo("license content #0");
+    }
+
+    @Test
+    public void testParseNewValidXmlStream() throws XmlPullParserException, IOException {
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
+        Map<String, String> contentIdToFileContentMap = new HashMap<>();
+
+        LicenseHtmlGeneratorFromXml.parse(
+                new InputStreamReader(new ByteArrayInputStream(VALID_NEW_XML_STRING.getBytes())),
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap);
+        assertThat(fileNameToLibraryToContentIdMap.size()).isEqualTo(2);
+        assertThat(fileNameToLibraryToContentIdMap.get("libA").size()).isEqualTo(1);
+        assertThat(fileNameToLibraryToContentIdMap.get("libB").size()).isEqualTo(1);
+        assertThat(fileNameToLibraryToContentIdMap.get("libA").get("/file0")).containsExactly("0");
+        assertThat(fileNameToLibraryToContentIdMap.get("libB").get("/file1")).containsExactly("0");
         assertThat(contentIdToFileContentMap.size()).isEqualTo(1);
         assertThat(contentIdToFileContentMap.get("0")).isEqualTo("license content #0");
     }
 
     @Test(expected = XmlPullParserException.class)
     public void testParseInvalidXmlStream() throws XmlPullParserException, IOException {
-        Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
         Map<String, String> contentIdToFileContentMap = new HashMap<>();
 
         LicenseHtmlGeneratorFromXml.parse(
-                new InputStreamReader(new ByteArrayInputStream(INVALILD_XML_STRING.getBytes())),
-                fileNameToContentIdMap, contentIdToFileContentMap);
+                new InputStreamReader(new ByteArrayInputStream(INVALID_XML_STRING.getBytes())),
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap);
     }
 
     @Test
     public void testGenerateHtml() {
-        Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
         Map<String, String> contentIdToFileContentMap = new HashMap<>();
+        Map<String, Set<String>> toBoth = new HashMap<>();
+        Map<String, Set<String>> toOne = new HashMap<>();
 
-        fileNameToContentIdMap.put("/file0", new HashSet<String>(Arrays.asList("0", "1")));
-        fileNameToContentIdMap.put("/file1", new HashSet<String>(Arrays.asList("0")));
+        toBoth.put("", new HashSet<String>(Arrays.asList("0", "1")));
+        toOne.put("", new HashSet<String>(Arrays.asList("0")));
+
+        fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+        fileNameToLibraryToContentIdMap.put("/file1", toOne);
         contentIdToFileContentMap.put("0", "license content #0");
         contentIdToFileContentMap.put("1", "license content #1");
 
         StringWriter output = new StringWriter();
         LicenseHtmlGeneratorFromXml.generateHtml(
-                fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output), "");
-        assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING);
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+                new PrintWriter(output), "");
+        assertThat(output.toString()).isEqualTo(EXPECTED_OLD_HTML_STRING);
+    }
+
+    @Test
+    public void testGenerateNewHtml() {
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
+        Map<String, String> contentIdToFileContentMap = new HashMap<>();
+        Map<String, Set<String>> toBoth = new HashMap<>();
+        Map<String, Set<String>> toOne = new HashMap<>();
+
+        toBoth.put("libA", new HashSet<String>(Arrays.asList("0")));
+        toBoth.put("libB", new HashSet<String>(Arrays.asList("1")));
+        toOne.put("libA", new HashSet<String>(Arrays.asList("0")));
+
+        fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+        fileNameToLibraryToContentIdMap.put("/file1", toOne);
+        contentIdToFileContentMap.put("0", "license content #0");
+        contentIdToFileContentMap.put("1", "license content #1");
+
+        StringWriter output = new StringWriter();
+        LicenseHtmlGeneratorFromXml.generateHtml(
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+                new PrintWriter(output), "");
+        assertThat(output.toString()).isEqualTo(EXPECTED_NEW_HTML_STRING);
     }
 
     @Test
     public void testGenerateHtmlWithCustomHeading() {
-        Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
         Map<String, String> contentIdToFileContentMap = new HashMap<>();
+        Map<String, Set<String>> toBoth = new HashMap<>();
+        Map<String, Set<String>> toOne = new HashMap<>();
 
-        fileNameToContentIdMap.put("/file0", new HashSet<String>(Arrays.asList("0", "1")));
-        fileNameToContentIdMap.put("/file1", new HashSet<String>(Arrays.asList("0")));
+        toBoth.put("", new HashSet<String>(Arrays.asList("0", "1")));
+        toOne.put("", new HashSet<String>(Arrays.asList("0")));
+
+        fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+        fileNameToLibraryToContentIdMap.put("/file1", toOne);
         contentIdToFileContentMap.put("0", "license content #0");
         contentIdToFileContentMap.put("1", "license content #1");
 
         StringWriter output = new StringWriter();
         LicenseHtmlGeneratorFromXml.generateHtml(
-                fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output),
-                HTML_CUSTOM_HEADING);
-        assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING);
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+                new PrintWriter(output), HTML_CUSTOM_HEADING);
+        assertThat(output.toString()).isEqualTo(EXPECTED_OLD_HTML_STRING_WITH_CUSTOM_HEADING);
+    }
+
+    @Test
+    public void testGenerateNewHtmlWithCustomHeading() {
+        Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
+        Map<String, String> contentIdToFileContentMap = new HashMap<>();
+        Map<String, Set<String>> toBoth = new HashMap<>();
+        Map<String, Set<String>> toOne = new HashMap<>();
+
+        toBoth.put("libA", new HashSet<String>(Arrays.asList("0")));
+        toBoth.put("libB", new HashSet<String>(Arrays.asList("1")));
+        toOne.put("libA", new HashSet<String>(Arrays.asList("0")));
+
+        fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+        fileNameToLibraryToContentIdMap.put("/file1", toOne);
+        contentIdToFileContentMap.put("0", "license content #0");
+        contentIdToFileContentMap.put("1", "license content #1");
+
+        StringWriter output = new StringWriter();
+        LicenseHtmlGeneratorFromXml.generateHtml(
+                fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+                new PrintWriter(output), HTML_CUSTOM_HEADING);
+        assertThat(output.toString()).isEqualTo(EXPECTED_NEW_HTML_STRING_WITH_CUSTOM_HEADING);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 6f7f73a..c122a37 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -31,6 +31,7 @@
 import android.content.Context;
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2Manager;
+import android.os.Parcel;
 
 import com.android.settingslib.bluetooth.A2dpProfile;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -65,9 +66,9 @@
     private static final String ROUTER_ID_3 = "RouterId_3";
     private static final String TEST_PACKAGE_NAME = "com.test.playmusic";
     private final BluetoothClass mHeadreeClass =
-            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
     private final BluetoothClass mCarkitClass =
-            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
+            createBtClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
 
     @Mock
     private BluetoothDevice mDevice1;
@@ -118,6 +119,16 @@
     private List<MediaDevice> mMediaDevices = new ArrayList<>();
     private PhoneMediaDevice mPhoneMediaDevice;
 
+    private BluetoothClass createBtClass(int deviceClass) {
+        Parcel p = Parcel.obtain();
+        p.writeInt(deviceClass);
+        p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+        BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+        p.recycle();
+        return bluetoothClass;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index b0a647e..95f7ef4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -81,8 +81,8 @@
         when(mSubscriptionManager.isActiveSubscriptionId(SUB_ID)).thenReturn(false);
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
     }
 
     @Test
@@ -94,8 +94,8 @@
                 .thenReturn(new String[] {SUBSCRIBER_ID});
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
     }
 
     @Test
@@ -107,7 +107,7 @@
                 .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isTrue();
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
index 5b0f659..2f3da83 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.net;
 
+import static android.app.usage.NetworkStats.Bucket.STATE_ALL;
 import static android.app.usage.NetworkStats.Bucket.STATE_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
 
@@ -83,7 +84,6 @@
 
         mLoader.recordUsage(start, end);
 
-        verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, uid);
         verify(mNetworkStatsManager).queryDetailsForUidTagState(
                 mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
     }
@@ -116,9 +116,12 @@
 
         mLoader.recordUsage(start, end);
 
-        verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 1);
-        verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 2);
-        verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 3);
+        verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 1,
+                TAG_NONE, STATE_ALL);
+        verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 2,
+                TAG_NONE, STATE_ALL);
+        verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 3,
+                TAG_NONE, STATE_ALL);
     }
 
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
index 74b9151..c79440e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -16,24 +16,24 @@
 
 package com.android.settingslib.net;
 
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.nullable;
+import static android.app.usage.NetworkStats.Bucket.UID_ALL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.annotation.NonNull;
+import android.app.usage.NetworkStats;
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.os.RemoteException;
 import android.text.format.DateUtils;
 import android.util.Range;
 
@@ -49,6 +49,8 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
 
 @RunWith(RobolectricTestRunner.class)
 public class NetworkCycleDataLoaderTest {
@@ -63,8 +65,6 @@
     private NetworkPolicy mPolicy;
     @Mock
     private Iterator<Range<ZonedDateTime>> mIterator;
-    @Mock
-    private INetworkStatsService mNetworkStatsService;
 
     private NetworkCycleDataTestLoader mLoader;
 
@@ -132,20 +132,24 @@
         verify(mLoader).recordUsage(nowInMs, nowInMs);
     }
 
+    private NetworkStats.Bucket makeMockBucket(int uid, long rxBytes, long txBytes,
+            long start, long end) {
+        NetworkStats.Bucket ret = mock(NetworkStats.Bucket.class);
+        when(ret.getUid()).thenReturn(uid);
+        when(ret.getRxBytes()).thenReturn(rxBytes);
+        when(ret.getTxBytes()).thenReturn(txBytes);
+        when(ret.getStartTimeStamp()).thenReturn(start);
+        when(ret.getEndTimeStamp()).thenReturn(end);
+        return ret;
+    }
+
     @Test
-    public void loadFourWeeksData_shouldRecordUsageForLast4Weeks() throws RemoteException {
+    public void loadFourWeeksData_shouldRecordUsageForLast4Weeks() {
         mLoader = spy(new NetworkCycleDataTestLoader(mContext));
-        ReflectionHelpers.setField(mLoader, "mNetworkStatsService", mNetworkStatsService);
-        final INetworkStatsSession networkSession = mock(INetworkStatsSession.class);
-        when(mNetworkStatsService.openSession()).thenReturn(networkSession);
-        final NetworkStatsHistory networkHistory = mock(NetworkStatsHistory.class);
-        when(networkSession.getHistoryForNetwork(nullable(NetworkTemplate.class), anyInt()))
-            .thenReturn(networkHistory);
         final long now = System.currentTimeMillis();
         final long fourWeeksAgo = now - (DateUtils.WEEK_IN_MILLIS * 4);
         final long twoDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 2);
-        when(networkHistory.getStart()).thenReturn(twoDaysAgo);
-        when(networkHistory.getEnd()).thenReturn(now);
+        mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, twoDaysAgo, now));
 
         mLoader.loadFourWeeksData();
 
@@ -173,10 +177,31 @@
         verify(mLoader).recordUsage(thirtyDaysAgo, twentyDaysAgo);
     }
 
+    @Test
+    public void getTimeRangeOf() {
+        mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+        // If empty, new Range(MAX_VALUE, MIN_VALUE) will be constructed. Hence, the function
+        // should throw.
+        assertThrows(IllegalArgumentException.class,
+                () -> mLoader.getTimeRangeOf(mock(NetworkStats.class)));
+
+        mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 0, 10));
+        // Feed the function with unused NetworkStats. The actual data injection is
+        // done by addBucket.
+        assertEquals(new Range(0L, 10L), mLoader.getTimeRangeOf(mock(NetworkStats.class)));
+
+        mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 0, 10));
+        mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 30, 40));
+        mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 10, 25));
+        assertEquals(new Range(0L, 40L), mLoader.getTimeRangeOf(mock(NetworkStats.class)));
+    }
+
     public class NetworkCycleDataTestLoader extends NetworkCycleDataLoader<List<NetworkCycleData>> {
+        private final Queue<NetworkStats.Bucket> mMockedBuckets = new LinkedBlockingQueue<>();
 
         private NetworkCycleDataTestLoader(Context context) {
-            super(NetworkCycleDataLoader.builder(mContext));
+            super(NetworkCycleDataLoader.builder(mContext)
+                    .setNetworkTemplate(mock(NetworkTemplate.class)));
             mContext = context;
         }
 
@@ -188,5 +213,19 @@
         List<NetworkCycleData> getCycleUsage() {
             return null;
         }
+
+        public void addBucket(NetworkStats.Bucket bucket) {
+            mMockedBuckets.add(bucket);
+        }
+
+        @Override
+        public boolean hasNextBucket(@NonNull NetworkStats unused) {
+            return !mMockedBuckets.isEmpty();
+        }
+
+        @Override
+        public NetworkStats.Bucket getNextBucket(@NonNull NetworkStats unused) {
+            return mMockedBuckets.remove();
+        }
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
index 3b7fbc7..c7e96bc 100644
--- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
@@ -69,7 +69,7 @@
     }
 
     @Implementation
-    protected boolean removeActiveDevice(@BluetoothAdapter.ActiveDeviceUse int profiles) {
+    protected boolean removeActiveDevice(int profiles) {
         if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
                 && profiles != ACTIVE_DEVICE_ALL) {
             return false;
@@ -78,8 +78,7 @@
     }
 
     @Implementation
-    protected boolean setActiveDevice(BluetoothDevice device,
-            @BluetoothAdapter.ActiveDeviceUse int profiles) {
+    protected boolean setActiveDevice(BluetoothDevice device, int profiles) {
         if (device == null) {
             return false;
         }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 618a37e..8b27522 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -190,6 +190,9 @@
     <uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
     <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" />
     <uses-permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS" />
+    <!-- Permission required for processes that don't own the focused window to switch
+         touch mode state -->
+    <uses-permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE" />
     <!-- Permission required to test onPermissionsChangedListener -->
     <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" />
     <uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" />
@@ -245,6 +248,7 @@
     <uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
     <uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
     <uses-permission android:name="android.permission.MANAGE_SMARTSPACE" />
+    <uses-permission android:name="android.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION" />
     <uses-permission android:name="android.permission.MANAGE_UI_TRANSLATION" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
@@ -340,6 +344,9 @@
     <!-- Permission required for CTS test - CrossProfileAppsHostSideTest -->
     <uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/>
 
+    <!-- Permission required for CTS test - CrossProfileAppsHostSideTest -->
+    <uses-permission android:name="android.permission.START_CROSS_PROFILE_ACTIVITIES"/>
+
     <!-- permissions required for CTS test - PhoneStateListenerTest -->
     <uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" />
 
@@ -500,6 +507,11 @@
     <!-- Permission needed for CTS test - WifiManagerTest -->
     <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
     <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+    <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
+    <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
+    <!-- Permission needed for CTS test - ConcurrencyTest#testP2pExternalApprover
+         P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. -->
+    <uses-permission android:name="android.permission.MANAGE_WIFI_AUTO_JOIN" />
 
     <!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
     <uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
@@ -524,6 +536,11 @@
     <!-- Permission required for CTS test - PeopleManagerTest -->
     <uses-permission android:name="android.permission.READ_PEOPLE_DATA" />
 
+    <!-- Permissions required for CTS test - TrustTestCases -->
+    <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" />
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.TRUST_LISTENER" />
+
     <!-- Permission required for CTS test - CtsGameManagerTestCases -->
     <uses-permission android:name="android.permission.MANAGE_GAME_MODE" />
 
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index e1da744..8323e32 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -11,8 +11,10 @@
 awickham@google.com
 beverlyt@google.com
 brockman@google.com
+brzezinski@google.com
 brycelee@google.com
 ccassidy@google.com
+chrisgollner@google.com
 cinek@google.com
 cwren@google.com
 dupin@google.com
@@ -43,6 +45,8 @@
 mrcasey@google.com
 mrenouf@google.com
 nesciosquid@google.com
+nickchameyev@google.com
+nicomazz@google.com
 ogunwale@google.com
 peanutbutter@google.com
 pinyaoting@google.com
@@ -67,6 +71,7 @@
 yurilin@google.com
 xuqiu@google.com
 zakcohen@google.com
+jernej@google.com
 
 #Android Auto
 hseog@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index d3d6e03..6f30ac3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,6 +18,7 @@
 
 import android.annotation.MainThread
 import android.app.Dialog
+import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
@@ -88,7 +89,7 @@
         bouncerOrRun(createAction(cvh.cws.ci.controlId, {
             cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
             if (cvh.usePanel()) {
-                showDetail(cvh, control.getAppIntent().getIntent())
+                showDetail(cvh, control.getAppIntent())
             } else {
                 cvh.action(CommandAction(templateId))
             }
@@ -116,7 +117,7 @@
             // Long press snould only be called when there is valid control state, otherwise ignore
             cvh.cws.control?.let {
                 cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
-                showDetail(cvh, it.getAppIntent().getIntent())
+                showDetail(cvh, it.getAppIntent())
             }
         }, false /* blockable */))
     }
@@ -167,10 +168,10 @@
         bgExecutor.execute { vibrator.vibrate(effect) }
     }
 
-    private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
+    private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
         bgExecutor.execute {
             val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
-                intent,
+                pendingIntent.getIntent(),
                 PackageManager.MATCH_DEFAULT_ONLY
             )
 
@@ -178,7 +179,7 @@
                 // make sure the intent is valid before attempting to open the dialog
                 if (activities.isNotEmpty() && taskViewFactory.isPresent) {
                     taskViewFactory.get().create(context, uiExecutor, {
-                        dialog = DetailDialog(activityContext, it, intent, cvh).also {
+                        dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also {
                             it.setOnDismissListener { _ -> dialog = null }
                             it.show()
                         }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 8a47a36..4758ab0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -43,7 +43,7 @@
 class DetailDialog(
     val activityContext: Context?,
     val taskView: TaskView,
-    val intent: Intent,
+    val pendingIntent: PendingIntent,
     val cvh: ControlViewHolder
 ) : Dialog(
     activityContext ?: cvh.context,
@@ -59,6 +59,14 @@
 
     var detailTaskId = INVALID_TASK_ID
 
+    private val fillInIntent = Intent().apply {
+        putExtra(EXTRA_USE_PANEL, true)
+
+        // Apply flags to make behaviour match documentLaunchMode=always.
+        addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+        addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+    }
+
     fun removeDetailTask() {
         if (detailTaskId == INVALID_TASK_ID) return
         ActivityTaskManager.getInstance().removeTask(detailTaskId)
@@ -67,13 +75,6 @@
 
     val stateCallback = object : TaskView.Listener {
         override fun onInitialized() {
-            val launchIntent = Intent(intent)
-            launchIntent.putExtra(EXTRA_USE_PANEL, true)
-
-            // Apply flags to make behaviour match documentLaunchMode=always.
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-
             val options = activityContext?.let {
                 ActivityOptions.makeCustomAnimation(
                     it,
@@ -82,9 +83,8 @@
                 )
             } ?: ActivityOptions.makeBasic()
             taskView.startActivity(
-                PendingIntent.getActivity(context, 0, launchIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
-                null /* fillInIntent */,
+                pendingIntent,
+                fillInIntent,
                 options,
                 getTaskViewBounds()
             )
@@ -97,6 +97,9 @@
 
         override fun onTaskCreated(taskId: Int, name: ComponentName?) {
             detailTaskId = taskId
+            requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
+                setAlpha(1f)
+            }
         }
 
         override fun onReleased() {
@@ -121,6 +124,7 @@
 
         requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
             addView(taskView)
+            setAlpha(0f)
         }
 
         requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -134,7 +138,7 @@
                 removeDetailTask()
                 dismiss()
                 context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
-                v.context.startActivity(intent)
+                pendingIntent.send()
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
index c50365f..71c5fad 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
@@ -15,7 +15,8 @@
 class SensorUseDialog(
     context: Context,
     val sensor: Int,
-    val clickListener: DialogInterface.OnClickListener
+    val clickListener: DialogInterface.OnClickListener,
+    val dismissListener: DialogInterface.OnDismissListener
 ) : SystemUIDialog(context) {
 
     // TODO move to onCreate (b/200815309)
@@ -69,6 +70,8 @@
                 context.getString(com.android.internal.R.string
                         .cancel), clickListener)
 
+        setOnDismissListener(dismissListener)
+
         setCancelable(false)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index b0071d9..dae375a 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -50,7 +50,7 @@
     private val keyguardStateController: KeyguardStateController,
     private val keyguardDismissUtil: KeyguardDismissUtil,
     @Background private val bgHandler: Handler
-) : Activity(), DialogInterface.OnClickListener {
+) : Activity(), DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
 
     companion object {
         private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName
@@ -120,7 +120,7 @@
             }
         }
 
-        mDialog = SensorUseDialog(this, sensor, this)
+        mDialog = SensorUseDialog(this, sensor, this, this)
         mDialog!!.show()
     }
 
@@ -212,4 +212,8 @@
                     .suppressSensorPrivacyReminders(sensor, suppressed)
         }
     }
+
+    override fun onDismiss(dialog: DialogInterface?) {
+        finish()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index e58ea7b..eddc347 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -234,7 +234,7 @@
                 ApplicationInfo appInfo =
                         pm.getApplicationInfo(
                                 pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
-                if (appInfo.isInstantApp()) {
+                if (appInfo != null && appInfo.isInstantApp()) {
                     postInstantAppNotif(
                             pkg,
                             info.userId,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
new file mode 100644
index 0000000..87b9172
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.systemui.controls.ui
+
+import android.app.PendingIntent
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.wm.shell.TaskView
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class DetailDialogTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var taskView: TaskView
+    @Mock
+    private lateinit var controlViewHolder: ControlViewHolder
+    @Mock
+    private lateinit var pendingIntent: PendingIntent
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun testPendingIntentIsUnModified() {
+        // GIVEN the dialog is created with a PendingIntent
+        val dialog = createDialog(pendingIntent)
+
+        // WHEN the TaskView is initialized
+        dialog.stateCallback.onInitialized()
+
+        // THEN the PendingIntent used to call startActivity is unmodified by systemui
+        verify(taskView).startActivity(eq(pendingIntent), any(), any(), any())
+    }
+
+    private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
+        return DetailDialog(
+            mContext,
+            taskView,
+            pendingIntent,
+            controlViewHolder
+        )
+    }
+}
diff --git a/services/Android.bp b/services/Android.bp
index 841edc7..536dc5d 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -42,7 +42,9 @@
         SYSTEM_OPTIMIZE_JAVA: {
             optimize: {
                 enabled: true,
-                optimize: true,
+                // TODO(b/210510433): Enable optimizations after improving
+                // retracing infra.
+                optimize: false,
                 shrink: true,
                 proguard_flags_files: ["proguard.flags"],
             },
@@ -74,6 +76,7 @@
         ":services.appwidget-sources",
         ":services.autofill-sources",
         ":services.backup-sources",
+        ":services.bluetooth-sources", // TODO(b/214988855) : Remove once apex/service-bluetooth jar is ready
         ":backuplib-sources",
         ":services.companion-sources",
         ":services.contentcapture-sources",
@@ -175,6 +178,10 @@
     name: "libandroid_servers",
     defaults: ["libservices.core-libs"],
     whole_static_libs: ["libservices.core"],
+    required: [
+        // TODO: remove after NetworkStatsService is moved to the mainline module.
+        "libcom_android_net_module_util_jni",
+    ],
 }
 
 platform_compat_config {
diff --git a/services/autofill/OWNERS b/services/autofill/OWNERS
index c52751d..edfb211 100644
--- a/services/autofill/OWNERS
+++ b/services/autofill/OWNERS
@@ -1 +1 @@
-include /core/java/android/service/autofill/OWNERS
+include /core/java/android/view/autofill/OWNERS
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 30de4b4..f6d05fa 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -1569,7 +1569,7 @@
         }
 
         @Override
-        public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {
+        public void onDeviceDisconnected(BluetoothDevice device, int reason) {
             Slog.d(LOG_TAG, device.getAddress() + " disconnected w/ reason: (" + reason + ") "
                     + BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
             CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress());
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 7a4f1de..9d19008 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -93,6 +93,7 @@
     defaults: ["platform_service_defaults"],
     srcs: [
         ":statslog-art-java-gen",
+        ":services.bluetooth-sources", // TODO(b/214988855) : Remove once apex is ready
         ":services.core-sources",
         ":services.core.protologsrc",
         ":dumpstate_aidl",
@@ -165,6 +166,9 @@
         "overlayable_policy_aidl-java",
         "SurfaceFlingerProperties",
         "com.android.sysprop.watchdog",
+        // This is used for services.connectivity-tiramisu-sources.
+        // TODO: delete when NetworkStatsService is moved to the mainline module.
+        "net-utils-device-common-bpf",
     ],
     javac_shard_size: 50,
 }
diff --git a/services/core/java/android/app/usage/OWNERS b/services/core/java/android/app/usage/OWNERS
new file mode 100644
index 0000000..3a55514
--- /dev/null
+++ b/services/core/java/android/app/usage/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/app/usage/OWNERS
diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
deleted file mode 100644
index 380b1f3..0000000
--- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.annotation.RequiresPermission;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * The BluetoothAirplaneModeListener handles system airplane mode change callback and checks
- * whether we need to inform BluetoothManagerService on this change.
- *
- * The information of airplane mode turns on would not be passed to the BluetoothManagerService
- * when Bluetooth is on and Bluetooth is in one of the following situations:
- *   1. Bluetooth A2DP is connected.
- *   2. Bluetooth Hearing Aid profile is connected.
- *   3. Bluetooth LE Audio is connected
- */
-class BluetoothAirplaneModeListener {
-    private static final String TAG = "BluetoothAirplaneModeListener";
-    @VisibleForTesting static final String TOAST_COUNT = "bluetooth_airplane_toast_count";
-
-    private static final int MSG_AIRPLANE_MODE_CHANGED = 0;
-
-    @VisibleForTesting static final int MAX_TOAST_COUNT = 10; // 10 times
-
-    private final BluetoothManagerService mBluetoothManager;
-    private final BluetoothAirplaneModeHandler mHandler;
-    private BluetoothModeChangeHelper mAirplaneHelper;
-
-    @VisibleForTesting int mToastCount = 0;
-
-    BluetoothAirplaneModeListener(BluetoothManagerService service, Looper looper, Context context) {
-        mBluetoothManager = service;
-
-        mHandler = new BluetoothAirplaneModeHandler(looper);
-        context.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
-                mAirplaneModeObserver);
-    }
-
-    private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
-        @Override
-        public void onChange(boolean unused) {
-            // Post from system main thread to android_io thread.
-            Message msg = mHandler.obtainMessage(MSG_AIRPLANE_MODE_CHANGED);
-            mHandler.sendMessage(msg);
-        }
-    };
-
-    private class BluetoothAirplaneModeHandler extends Handler {
-        BluetoothAirplaneModeHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_AIRPLANE_MODE_CHANGED:
-                    handleAirplaneModeChange();
-                    break;
-                default:
-                    Log.e(TAG, "Invalid message: " + msg.what);
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Call after boot complete
-     */
-    @VisibleForTesting
-    void start(BluetoothModeChangeHelper helper) {
-        Log.i(TAG, "start");
-        mAirplaneHelper = helper;
-        mToastCount = mAirplaneHelper.getSettingsInt(TOAST_COUNT);
-    }
-
-    @VisibleForTesting
-    boolean shouldPopToast() {
-        if (mToastCount >= MAX_TOAST_COUNT) {
-            return false;
-        }
-        mToastCount++;
-        mAirplaneHelper.setSettingsInt(TOAST_COUNT, mToastCount);
-        return true;
-    }
-
-    @VisibleForTesting
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    void handleAirplaneModeChange() {
-        if (shouldSkipAirplaneModeChange()) {
-            Log.i(TAG, "Ignore airplane mode change");
-            // Airplane mode enabled when Bluetooth is being used for audio/headering aid.
-            // Bluetooth is not disabled in such case, only state is changed to
-            // BLUETOOTH_ON_AIRPLANE mode.
-            mAirplaneHelper.setSettingsInt(Settings.Global.BLUETOOTH_ON,
-                    BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
-            if (shouldPopToast()) {
-                mAirplaneHelper.showToastMessage();
-            }
-            return;
-        }
-        if (mAirplaneHelper != null) {
-            mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
-        }
-    }
-
-    @VisibleForTesting
-    boolean shouldSkipAirplaneModeChange() {
-        if (mAirplaneHelper == null) {
-            return false;
-        }
-        if (!mAirplaneHelper.isBluetoothOn() || !mAirplaneHelper.isAirplaneModeOn()
-                || !mAirplaneHelper.isMediaProfileConnected()) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java b/services/core/java/com/android/server/BluetoothDeviceConfigListener.java
deleted file mode 100644
index 611a37d..0000000
--- a/services/core/java/com/android/server/BluetoothDeviceConfigListener.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.provider.DeviceConfig;
-import android.util.Slog;
-
-import java.util.ArrayList;
-
-/**
- * The BluetoothDeviceConfigListener handles system device config change callback and checks
- * whether we need to inform BluetoothManagerService on this change.
- *
- * The information of device config change would not be passed to the BluetoothManagerService
- * when Bluetooth is on and Bluetooth is in one of the following situations:
- *   1. Bluetooth A2DP is connected.
- *   2. Bluetooth Hearing Aid profile is connected.
- */
-class BluetoothDeviceConfigListener {
-    private static final String TAG = "BluetoothDeviceConfigListener";
-
-    private final BluetoothManagerService mService;
-    private final boolean mLogDebug;
-
-    BluetoothDeviceConfigListener(BluetoothManagerService service, boolean logDebug) {
-        mService = service;
-        mLogDebug = logDebug;
-        DeviceConfig.addOnPropertiesChangedListener(
-                DeviceConfig.NAMESPACE_BLUETOOTH,
-                (Runnable r) -> r.run(),
-                mDeviceConfigChangedListener);
-    }
-
-    private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener =
-            new DeviceConfig.OnPropertiesChangedListener() {
-                @Override
-                public void onPropertiesChanged(DeviceConfig.Properties properties) {
-                    if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) {
-                        return;
-                    }
-                    if (mLogDebug) {
-                        ArrayList<String> flags = new ArrayList<>();
-                        for (String name : properties.getKeyset()) {
-                            flags.add(name + "='" + properties.getString(name, "") + "'");
-                        }
-                        Slog.d(TAG, "onPropertiesChanged: " + String.join(",", flags));
-                    }
-                    boolean foundInit = false;
-                    for (String name : properties.getKeyset()) {
-                        if (name.startsWith("INIT_")) {
-                            foundInit = true;
-                            break;
-                        }
-                    }
-                    if (!foundInit) {
-                        return;
-                    }
-                    mService.onInitFlagsChanged();
-                }
-            };
-
-}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
deleted file mode 100644
index c8b4f11..0000000
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ /dev/null
@@ -1,2960 +0,0 @@
-/*
- * 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 com.android.server;
-
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.content.PermissionChecker.PERMISSION_HARD_DENIED;
-import static android.content.PermissionChecker.PID_UNKNOWN;
-import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
-import static android.os.UserHandle.USER_SYSTEM;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.AppOpsManager;
-import android.app.BroadcastOptions;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHearingAid;
-import android.bluetooth.BluetoothLeAudio;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProtoEnums;
-import android.bluetooth.IBluetooth;
-import android.bluetooth.IBluetoothCallback;
-import android.bluetooth.IBluetoothGatt;
-import android.bluetooth.IBluetoothHeadset;
-import android.bluetooth.IBluetoothManager;
-import android.bluetooth.IBluetoothManagerCallback;
-import android.bluetooth.IBluetoothProfileServiceConnection;
-import android.bluetooth.IBluetoothStateChangeCallback;
-import android.bluetooth.IBluetoothLeCallControl;
-import android.content.ActivityNotFoundException;
-import android.content.AttributionSource;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.PermissionChecker;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerExemptionManager;
-import android.os.Process;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.pm.UserManagerInternal;
-import com.android.server.pm.UserManagerInternal.UserRestrictionsListener;
-import com.android.server.pm.UserRestrictionsUtils;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Locale;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-class BluetoothManagerService extends IBluetoothManager.Stub {
-    private static final String TAG = "BluetoothManagerService";
-    private static final boolean DBG = true;
-
-    private static final String BLUETOOTH_PRIVILEGED =
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED;
-
-    private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
-    private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
-    private static final String SECURE_SETTINGS_BLUETOOTH_NAME = "bluetooth_name";
-
-    private static final int ACTIVE_LOG_MAX_SIZE = 20;
-    private static final int CRASH_LOG_MAX_SIZE = 100;
-
-    private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
-    //Maximum msec to wait for service restart
-    private static final int SERVICE_RESTART_TIME_MS = 400;
-    //Maximum msec to wait for restart due to error
-    private static final int ERROR_RESTART_TIME_MS = 3000;
-    //Maximum msec to delay MESSAGE_USER_SWITCHED
-    private static final int USER_SWITCHED_TIME_MS = 200;
-    // Delay for the addProxy function in msec
-    private static final int ADD_PROXY_DELAY_MS = 100;
-    // Delay for retrying enable and disable in msec
-    private static final int ENABLE_DISABLE_DELAY_MS = 300;
-    private static final int DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300;
-    private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400;
-
-    private static final int MESSAGE_ENABLE = 1;
-    private static final int MESSAGE_DISABLE = 2;
-    private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3;
-    private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4;
-    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
-    private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
-    private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
-    private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
-    private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
-    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
-    private static final int MESSAGE_TIMEOUT_BIND = 100;
-    private static final int MESSAGE_TIMEOUT_UNBIND = 101;
-    private static final int MESSAGE_GET_NAME_AND_ADDRESS = 200;
-    private static final int MESSAGE_USER_SWITCHED = 300;
-    private static final int MESSAGE_USER_UNLOCKED = 301;
-    private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
-    private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
-    private static final int MESSAGE_RESTORE_USER_SETTING = 500;
-    private static final int MESSAGE_INIT_FLAGS_CHANGED = 600;
-
-    private static final int RESTORE_SETTING_TO_ON = 1;
-    private static final int RESTORE_SETTING_TO_OFF = 0;
-
-    private static final int MAX_ERROR_RESTART_RETRIES = 6;
-    private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10;
-
-    // Bluetooth persisted setting is off
-    private static final int BLUETOOTH_OFF = 0;
-    // Bluetooth persisted setting is on
-    // and Airplane mode won't affect Bluetooth state at start up
-    private static final int BLUETOOTH_ON_BLUETOOTH = 1;
-    // Bluetooth persisted setting is on
-    // but Airplane mode will affect Bluetooth state at start up
-    // and Airplane mode will have higher priority.
-    @VisibleForTesting
-    static final int BLUETOOTH_ON_AIRPLANE = 2;
-
-    private static final int SERVICE_IBLUETOOTH = 1;
-    private static final int SERVICE_IBLUETOOTHGATT = 2;
-
-    private final Context mContext;
-
-    // Locks are not provided for mName and mAddress.
-    // They are accessed in handler or broadcast receiver, same thread context.
-    private String mAddress;
-    private String mName;
-    private final ContentResolver mContentResolver;
-    private final int mUserId;
-    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
-    private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
-    private IBinder mBluetoothBinder;
-    private IBluetooth mBluetooth;
-    private IBluetoothGatt mBluetoothGatt;
-    private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
-    private boolean mBinding;
-    private boolean mUnbinding;
-
-    private BluetoothModeChangeHelper mBluetoothModeChangeHelper;
-
-    private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
-
-    private BluetoothDeviceConfigListener mBluetoothDeviceConfigListener;
-
-    // used inside handler thread
-    private boolean mQuietEnable = false;
-    private boolean mEnable;
-
-    private static CharSequence timeToLog(long timestamp) {
-        return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
-    }
-
-    /**
-     * Used for tracking apps that enabled / disabled Bluetooth.
-     */
-    private class ActiveLog {
-        private int mReason;
-        private String mPackageName;
-        private boolean mEnable;
-        private long mTimestamp;
-
-        ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
-            mReason = reason;
-            mPackageName = packageName;
-            mEnable = enable;
-            mTimestamp = timestamp;
-        }
-
-        public String toString() {
-            return timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ")
-                    + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
-        }
-
-        void dump(ProtoOutputStream proto) {
-            proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp);
-            proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable);
-            proto.write(BluetoothManagerServiceDumpProto.ActiveLog.PACKAGE_NAME, mPackageName);
-            proto.write(BluetoothManagerServiceDumpProto.ActiveLog.REASON, mReason);
-        }
-    }
-
-    private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
-    private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
-    private int mCrashes;
-    private long mLastEnabledTime;
-
-    // configuration from external IBinder call which is used to
-    // synchronize with broadcast receiver.
-    private boolean mQuietEnableExternal;
-    private boolean mEnableExternal;
-
-    // Map of apps registered to keep BLE scanning on.
-    private Map<IBinder, ClientDeathRecipient> mBleApps =
-            new ConcurrentHashMap<IBinder, ClientDeathRecipient>();
-
-    private int mState;
-    private final BluetoothHandler mHandler;
-    private int mErrorRecoveryRetryCounter;
-    private final int mSystemUiUid;
-
-    private boolean mIsHearingAidProfileSupported;
-
-    private AppOpsManager mAppOps;
-
-    // Save a ProfileServiceConnections object for each of the bound
-    // bluetooth profile services
-    private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
-
-    private final boolean mWirelessConsentRequired;
-
-    private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
-        @Override
-        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
-            Message msg =
-                    mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
-            mHandler.sendMessage(msg);
-        }
-    };
-
-    private final UserRestrictionsListener mUserRestrictionsListener =
-            new UserRestrictionsListener() {
-                @Override
-                public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
-                        Bundle prevRestrictions) {
-
-                    if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
-                            UserManager.DISALLOW_BLUETOOTH_SHARING)) {
-                        updateOppLauncherComponentState(userId,
-                                newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING));
-                    }
-
-                    // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
-                    if (userId == USER_SYSTEM
-                            && UserRestrictionsUtils.restrictionsChanged(prevRestrictions,
-                            newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
-                        if (userId == USER_SYSTEM && newRestrictions.getBoolean(
-                                UserManager.DISALLOW_BLUETOOTH)) {
-                            updateOppLauncherComponentState(userId, true); // Sharing disallowed
-                            sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
-                                    mContext.getPackageName());
-                        } else {
-                            updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
-                                    UserManager.DISALLOW_BLUETOOTH_SHARING));
-                        }
-                    }
-                }
-            };
-
-    @VisibleForTesting
-    public void onInitFlagsChanged() {
-        mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
-        mHandler.sendEmptyMessageDelayed(
-                MESSAGE_INIT_FLAGS_CHANGED,
-                DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS);
-    }
-
-    public boolean onFactoryReset(AttributionSource attributionSource) {
-        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
-                "Need BLUETOOTH_PRIVILEGED permission");
-
-        // Wait for stable state if bluetooth is temporary state.
-        int state = getState();
-        if (state == BluetoothAdapter.STATE_BLE_TURNING_ON
-                || state == BluetoothAdapter.STATE_TURNING_ON
-                || state == BluetoothAdapter.STATE_TURNING_OFF) {
-            if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) {
-                return false;
-            }
-        }
-
-        // Clear registered LE apps to force shut-off Bluetooth
-        clearBleApps();
-        state = getState();
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth == null) {
-                return false;
-            }
-            if (state == BluetoothAdapter.STATE_BLE_ON) {
-                addActiveLog(
-                        BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
-                        mContext.getPackageName(), false);
-                mBluetooth.onBrEdrDown(attributionSource);
-                return true;
-            } else if (state == BluetoothAdapter.STATE_ON) {
-                addActiveLog(
-                        BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
-                        mContext.getPackageName(), false);
-                mBluetooth.disable(attributionSource);
-                return true;
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to shutdown Bluetooth", e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-        return false;
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void onAirplaneModeChanged() {
-        synchronized (this) {
-            if (isBluetoothPersistedStateOn()) {
-                if (isAirplaneModeOn()) {
-                    persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE);
-                } else {
-                    persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-                }
-            }
-
-            int st = BluetoothAdapter.STATE_OFF;
-            try {
-                mBluetoothLock.readLock().lock();
-                if (mBluetooth != null) {
-                    st = mBluetooth.getState();
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to call getState", e);
-                return;
-            } finally {
-                mBluetoothLock.readLock().unlock();
-            }
-
-            Slog.d(TAG,
-                    "Airplane Mode change - current state:  " + BluetoothAdapter.nameForState(
-                            st) + ", isAirplaneModeOn()=" + isAirplaneModeOn());
-
-            if (isAirplaneModeOn()) {
-                // Clear registered LE apps to force shut-off
-                clearBleApps();
-
-                // If state is BLE_ON make sure we trigger disableBLE
-                if (st == BluetoothAdapter.STATE_BLE_ON) {
-                    try {
-                        mBluetoothLock.readLock().lock();
-                        if (mBluetooth != null) {
-                            addActiveLog(
-                                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
-                                    mContext.getPackageName(), false);
-                            mBluetooth.onBrEdrDown(mContext.getAttributionSource());
-                            mEnable = false;
-                            mEnableExternal = false;
-                        }
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to call onBrEdrDown", e);
-                    } finally {
-                        mBluetoothLock.readLock().unlock();
-                    }
-                } else if (st == BluetoothAdapter.STATE_ON) {
-                    sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
-                            mContext.getPackageName());
-                }
-            } else if (mEnableExternal) {
-                sendEnableMsg(mQuietEnableExternal,
-                        BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
-                        mContext.getPackageName());
-            }
-        }
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
-                String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
-                if (DBG) {
-                    Slog.d(TAG, "Bluetooth Adapter name changed to " + newName + " by "
-                            + mContext.getPackageName());
-                }
-                if (newName != null) {
-                    storeNameAndAddress(newName, null);
-                }
-            } else if (BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) {
-                String newAddress = intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS);
-                if (newAddress != null) {
-                    if (DBG) {
-                        Slog.d(TAG, "Bluetooth Adapter address changed to " + newAddress);
-                    }
-                    storeNameAndAddress(null, newAddress);
-                } else {
-                    if (DBG) {
-                        Slog.e(TAG, "No Bluetooth Adapter address parameter found");
-                    }
-                }
-            } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
-                final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
-                if (Settings.Global.BLUETOOTH_ON.equals(name)) {
-                    // The Bluetooth On state may be changed during system restore.
-                    final String prevValue =
-                            intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
-                    final String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
-
-                    if (DBG) {
-                        Slog.d(TAG,
-                                "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" + prevValue
-                                        + ", newValue=" + newValue);
-                    }
-
-                    if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
-                        Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
-                                newValue.equals("0") ? RESTORE_SETTING_TO_OFF
-                                        : RESTORE_SETTING_TO_ON, 0);
-                        mHandler.sendMessage(msg);
-                    }
-                }
-            } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action)
-                    || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)
-                    || BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED.equals(action)) {
-                final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
-                        BluetoothProfile.STATE_CONNECTED);
-                if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)
-                        && state == BluetoothProfile.STATE_DISCONNECTED
-                        && !mBluetoothModeChangeHelper.isMediaProfileConnected()) {
-                    Slog.i(TAG, "Device disconnected, reactivating pending flag changes");
-                    onInitFlagsChanged();
-                }
-            }
-        }
-    };
-
-    BluetoothManagerService(Context context) {
-        mHandler = new BluetoothHandler(IoThread.get().getLooper());
-
-        mContext = context;
-
-        mWirelessConsentRequired = context.getResources()
-                .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);
-
-        mCrashes = 0;
-        mBluetooth = null;
-        mBluetoothBinder = null;
-        mBluetoothGatt = null;
-        mBinding = false;
-        mUnbinding = false;
-        mEnable = false;
-        mState = BluetoothAdapter.STATE_OFF;
-        mQuietEnableExternal = false;
-        mEnableExternal = false;
-        mAddress = null;
-        mName = null;
-        mErrorRecoveryRetryCounter = 0;
-        mContentResolver = context.getContentResolver();
-        mUserId = mContentResolver.getUserId();
-        // Observe BLE scan only mode settings change.
-        registerForBleScanModeChange();
-        mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
-        mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
-
-        mIsHearingAidProfileSupported = context.getResources()
-                .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported);
-
-        // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
-        String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
-        if (!TextUtils.isEmpty(value)) {
-            boolean isHearingAidEnabled = Boolean.parseBoolean(value);
-            Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
-            FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
-            if (isHearingAidEnabled && !mIsHearingAidProfileSupported) {
-                // Overwrite to enable support by FeatureFlag
-                mIsHearingAidProfileSupported = true;
-            }
-        }
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
-        filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
-        filter.addAction(Intent.ACTION_SETTING_RESTORED);
-        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
-        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
-        mContext.registerReceiver(mReceiver, filter);
-
-        loadStoredNameAndAddress();
-        if (isBluetoothPersistedStateOn()) {
-            if (DBG) {
-                Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
-            }
-            mEnableExternal = true;
-        }
-
-        String airplaneModeRadios =
-                Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
-        if (airplaneModeRadios == null || airplaneModeRadios.contains(
-                Settings.Global.RADIO_BLUETOOTH)) {
-            mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
-                    this, IoThread.get().getLooper(), context);
-        }
-
-        int systemUiUid = -1;
-        // Check if device is configured with no home screen, which implies no SystemUI.
-        boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
-        if (!noHome) {
-            PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
-            systemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
-                    MATCH_SYSTEM_ONLY, USER_SYSTEM);
-        }
-        if (systemUiUid >= 0) {
-            Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
-        } else {
-            // Some platforms, such as wearables do not have a system ui.
-            Slog.w(TAG, "Unable to resolve SystemUI's UID.");
-        }
-        mSystemUiUid = systemUiUid;
-    }
-
-    /**
-     *  Returns true if airplane mode is currently on
-     */
-    private boolean isAirplaneModeOn() {
-        return Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
-    }
-
-    private boolean supportBluetoothPersistedState() {
-        return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
-    }
-
-    /**
-     *  Returns true if the Bluetooth saved state is "on"
-     */
-    private boolean isBluetoothPersistedStateOn() {
-        if (!supportBluetoothPersistedState()) {
-            return false;
-        }
-        int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
-        if (DBG) {
-            Slog.d(TAG, "Bluetooth persisted state: " + state);
-        }
-        return state != BLUETOOTH_OFF;
-    }
-
-    private boolean isBluetoothPersistedStateOnAirplane() {
-        if (!supportBluetoothPersistedState()) {
-            return false;
-        }
-        int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
-        if (DBG) {
-            Slog.d(TAG, "Bluetooth persisted state: " + state);
-        }
-        return state == BLUETOOTH_ON_AIRPLANE;
-    }
-
-    /**
-     *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
-     */
-    private boolean isBluetoothPersistedStateOnBluetooth() {
-        if (!supportBluetoothPersistedState()) {
-            return false;
-        }
-        return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
-                BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
-    }
-
-    /**
-     *  Save the Bluetooth on/off state
-     */
-    private void persistBluetoothSetting(int value) {
-        if (DBG) {
-            Slog.d(TAG, "Persisting Bluetooth Setting: " + value);
-        }
-        // waive WRITE_SECURE_SETTINGS permission check
-        final long callingIdentity = Binder.clearCallingIdentity();
-        try {
-            Settings.Global.putInt(mContext.getContentResolver(),
-                    Settings.Global.BLUETOOTH_ON, value);
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-    }
-
-    /**
-     * Returns true if the Bluetooth Adapter's name and address is
-     * locally cached
-     * @return
-     */
-    private boolean isNameAndAddressSet() {
-        return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0;
-    }
-
-    /**
-     * Retrieve the Bluetooth Adapter's name and address and save it in
-     * in the local cache
-     */
-    private void loadStoredNameAndAddress() {
-        if (DBG) {
-            Slog.d(TAG, "Loading stored name and address");
-        }
-        if (mContext.getResources()
-                .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation)
-                && Settings.Secure.getIntForUser(mContentResolver,
-                SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0, mUserId)
-                == 0) {
-            // if the valid flag is not set, don't load the address and name
-            if (DBG) {
-                Slog.d(TAG, "invalid bluetooth name and address stored");
-            }
-            return;
-        }
-        mName = Settings.Secure.getStringForUser(
-                mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, mUserId);
-        mAddress = Settings.Secure.getStringForUser(
-                mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, mUserId);
-        if (DBG) {
-            Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
-        }
-    }
-
-    /**
-     * Save the Bluetooth name and address in the persistent store.
-     * Only non-null values will be saved.
-     * @param name
-     * @param address
-     */
-    private void storeNameAndAddress(String name, String address) {
-        if (name != null) {
-            Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name,
-                    mUserId);
-            mName = name;
-            if (DBG) {
-                Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getStringForUser(
-                        mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME,
-                        mUserId));
-            }
-        }
-
-        if (address != null) {
-            Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS,
-                    address, mUserId);
-            mAddress = address;
-            if (DBG) {
-                Slog.d(TAG,
-                        "Stored Bluetoothaddress: " + Settings.Secure.getStringForUser(
-                                mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS,
-                                mUserId));
-            }
-        }
-
-        if ((name != null) && (address != null)) {
-            Settings.Secure.putIntForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1,
-                    mUserId);
-        }
-    }
-
-    public IBluetooth registerAdapter(IBluetoothManagerCallback callback) {
-        if (callback == null) {
-            Slog.w(TAG, "Callback is null in registerAdapter");
-            return null;
-        }
-        synchronized (mCallbacks) {
-            mCallbacks.register(callback);
-        }
-        return mBluetooth;
-    }
-
-    public void unregisterAdapter(IBluetoothManagerCallback callback) {
-        if (callback == null) {
-            Slog.w(TAG, "Callback is null in unregisterAdapter");
-            return;
-        }
-        synchronized (mCallbacks) {
-            mCallbacks.unregister(callback);
-        }
-    }
-
-    public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
-        if (callback == null) {
-            Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
-            return;
-        }
-        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
-        msg.obj = callback;
-        mHandler.sendMessage(msg);
-    }
-
-    public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
-        if (callback == null) {
-            Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
-            return;
-        }
-        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
-        msg.obj = callback;
-        mHandler.sendMessage(msg);
-    }
-
-    public boolean isEnabled() {
-        return getState() == BluetoothAdapter.STATE_ON;
-    }
-
-    public int getState() {
-        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
-            Slog.w(TAG, "getState(): report OFF for non-active and non system user");
-            return BluetoothAdapter.STATE_OFF;
-        }
-
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth != null) {
-                return mBluetooth.getState();
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "getState()", e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-        return BluetoothAdapter.STATE_OFF;
-    }
-
-    class ClientDeathRecipient implements IBinder.DeathRecipient {
-        private String mPackageName;
-
-        ClientDeathRecipient(String packageName) {
-            mPackageName = packageName;
-        }
-
-        public void binderDied() {
-            if (DBG) {
-                Slog.d(TAG, "Binder is dead - unregister " + mPackageName);
-            }
-
-            for (Map.Entry<IBinder, ClientDeathRecipient> entry : mBleApps.entrySet()) {
-                IBinder token = entry.getKey();
-                ClientDeathRecipient deathRec = entry.getValue();
-                if (deathRec.equals(this)) {
-                    updateBleAppCount(token, false, mPackageName);
-                    break;
-                }
-            }
-        }
-
-        public String getPackageName() {
-            return mPackageName;
-        }
-    }
-
-    @Override
-    public boolean isBleScanAlwaysAvailable() {
-        if (isAirplaneModeOn() && !mEnable) {
-            return false;
-        }
-        try {
-            return Settings.Global.getInt(mContentResolver,
-                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
-        } catch (SettingNotFoundException e) {
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isHearingAidProfileSupported() {
-        return mIsHearingAidProfileSupported;
-    }
-
-    private boolean isDeviceProvisioned() {
-        return Settings.Global.getInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED,
-                0) != 0;
-    }
-
-    // Monitor change of BLE scan only mode settings.
-    private void registerForProvisioningStateChange() {
-        ContentObserver contentObserver = new ContentObserver(null) {
-            @Override
-            public void onChange(boolean selfChange) {
-                if (!isDeviceProvisioned()) {
-                    if (DBG) {
-                        Slog.d(TAG, "DEVICE_PROVISIONED setting changed, but device is not "
-                                + "provisioned");
-                    }
-                    return;
-                }
-                if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)) {
-                    Slog.i(TAG, "Device provisioned, reactivating pending flag changes");
-                    onInitFlagsChanged();
-                }
-            }
-        };
-
-        mContentResolver.registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), false,
-                contentObserver);
-    }
-
-    // Monitor change of BLE scan only mode settings.
-    private void registerForBleScanModeChange() {
-        ContentObserver contentObserver = new ContentObserver(null) {
-            @Override
-            public void onChange(boolean selfChange) {
-                if (isBleScanAlwaysAvailable()) {
-                    // Nothing to do
-                    return;
-                }
-                // BLE scan is not available.
-                disableBleScanMode();
-                clearBleApps();
-                try {
-                    mBluetoothLock.readLock().lock();
-                    if (mBluetooth != null) {
-                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
-                                mContext.getPackageName(), false);
-                        mBluetooth.onBrEdrDown(mContext.getAttributionSource());
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "error when disabling bluetooth", e);
-                } finally {
-                    mBluetoothLock.readLock().unlock();
-                }
-            }
-        };
-
-        mContentResolver.registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE), false,
-                contentObserver);
-    }
-
-    // Disable ble scan only mode.
-    private void disableBleScanMode() {
-        try {
-            mBluetoothLock.writeLock().lock();
-            if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
-                if (DBG) {
-                    Slog.d(TAG, "Reseting the mEnable flag for clean disable");
-                }
-                mEnable = false;
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "getState()", e);
-        } finally {
-            mBluetoothLock.writeLock().unlock();
-        }
-    }
-
-    private int updateBleAppCount(IBinder token, boolean enable, String packageName) {
-        ClientDeathRecipient r = mBleApps.get(token);
-        if (r == null && enable) {
-            ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName);
-            try {
-                token.linkToDeath(deathRec, 0);
-            } catch (RemoteException ex) {
-                throw new IllegalArgumentException("BLE app (" + packageName + ") already dead!");
-            }
-            mBleApps.put(token, deathRec);
-            if (DBG) {
-                Slog.d(TAG, "Registered for death of " + packageName);
-            }
-        } else if (!enable && r != null) {
-            // Unregister death recipient as the app goes away.
-            token.unlinkToDeath(r, 0);
-            mBleApps.remove(token);
-            if (DBG) {
-                Slog.d(TAG, "Unregistered for death of " + packageName);
-            }
-        }
-        int appCount = mBleApps.size();
-        if (DBG) {
-            Slog.d(TAG, appCount + " registered Ble Apps");
-        }
-        return appCount;
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private boolean checkBluetoothPermissions(AttributionSource attributionSource, String message,
-            boolean requireForeground) {
-        if (isBluetoothDisallowed()) {
-            if (DBG) {
-                Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed");
-            }
-            return false;
-        }
-        // Check if packageName belongs to callingUid
-        final int callingUid = Binder.getCallingUid();
-        final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
-        if (!isCallerSystem) {
-            checkPackage(callingUid, attributionSource.getPackageName());
-
-            if (requireForeground && !checkIfCallerIsForegroundUser()) {
-                Slog.w(TAG, "Not allowed for non-active and non system user");
-                return false;
-            }
-
-            if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, message)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public boolean enableBle(AttributionSource attributionSource, IBinder token)
-            throws RemoteException {
-        final String packageName = attributionSource.getPackageName();
-        if (!checkBluetoothPermissions(attributionSource, "enableBle", false)) {
-            if (DBG) {
-                Slog.d(TAG, "enableBle(): bluetooth disallowed");
-            }
-            return false;
-        }
-
-        if (DBG) {
-            Slog.d(TAG, "enableBle(" + packageName + "):  mBluetooth =" + mBluetooth
-                    + " mBinding = " + mBinding + " mState = "
-                    + BluetoothAdapter.nameForState(mState));
-        }
-        updateBleAppCount(token, true, packageName);
-
-        if (mState == BluetoothAdapter.STATE_ON
-                || mState == BluetoothAdapter.STATE_BLE_ON
-                || mState == BluetoothAdapter.STATE_TURNING_ON
-                || 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, true);
-        }
-        return true;
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public boolean disableBle(AttributionSource attributionSource, IBinder token)
-            throws RemoteException {
-        final String packageName = attributionSource.getPackageName();
-        if (!checkBluetoothPermissions(attributionSource, "disableBle", false)) {
-            if (DBG) {
-                Slog.d(TAG, "disableBLE(): bluetooth disallowed");
-            }
-            return false;
-        }
-
-        if (DBG) {
-            Slog.d(TAG, "disableBle(" + packageName + "):  mBluetooth =" + mBluetooth
-                    + " mBinding = " + mBinding + " mState = "
-                    + BluetoothAdapter.nameForState(mState));
-        }
-
-        if (mState == BluetoothAdapter.STATE_OFF) {
-            Slog.d(TAG, "disableBLE(): Already disabled");
-            return false;
-        }
-        updateBleAppCount(token, false, packageName);
-
-        if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) {
-            if (mEnable) {
-                disableBleScanMode();
-            }
-            if (!mEnableExternal) {
-                addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
-                        packageName, false);
-                sendBrEdrDownCallback(attributionSource);
-            }
-        }
-        return true;
-    }
-
-    // Clear all apps using BLE scan only mode.
-    private void clearBleApps() {
-        mBleApps.clear();
-    }
-
-    /** @hide */
-    public boolean isBleAppPresent() {
-        if (DBG) {
-            Slog.d(TAG, "isBleAppPresent() count: " + mBleApps.size());
-        }
-        return mBleApps.size() > 0;
-    }
-
-    /**
-     * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on,
-     * call IBluetooth.onBrEdrDown() to disable if Bluetooth should be off.
-     */
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    private void continueFromBleOnState() {
-        if (DBG) {
-            Slog.d(TAG, "continueFromBleOnState()");
-        }
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth == null) {
-                Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
-                return;
-            }
-            if (!mEnableExternal && !isBleAppPresent()) {
-                Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now");
-                mEnable = false;
-                mBluetooth.onBrEdrDown(mContext.getAttributionSource());
-                return;
-            }
-            if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
-                // This triggers transition to STATE_ON
-                mBluetooth.onLeServiceUp(mContext.getAttributionSource());
-                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to call onServiceUp", e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-    }
-
-    /**
-     * Inform BluetoothAdapter instances that BREDR part is down
-     * and turn off all service and stack if no LE app needs it
-     */
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    private void sendBrEdrDownCallback(AttributionSource attributionSource) {
-        if (DBG) {
-            Slog.d(TAG, "Calling sendBrEdrDownCallback callbacks");
-        }
-
-        if (mBluetooth == null) {
-            Slog.w(TAG, "Bluetooth handle is null");
-            return;
-        }
-
-        if (isBleAppPresent()) {
-            // Need to stay at BLE ON. Disconnect all Gatt connections
-            try {
-                mBluetoothGatt.unregAll(attributionSource);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to disconnect all apps.", e);
-            }
-        } else {
-            try {
-                mBluetoothLock.readLock().lock();
-                if (mBluetooth != null) {
-                    mBluetooth.onBrEdrDown(attributionSource);
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
-            } finally {
-                mBluetoothLock.readLock().unlock();
-            }
-        }
-
-    }
-
-    public boolean enableNoAutoConnect(AttributionSource attributionSource) {
-        final String packageName = attributionSource.getPackageName();
-        if (!checkBluetoothPermissions(attributionSource, "enableNoAutoConnect", false)) {
-            if (DBG) {
-                Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
-            }
-            return false;
-        }
-
-        if (DBG) {
-            Slog.d(TAG, "enableNoAutoConnect():  mBluetooth =" + mBluetooth + " mBinding = "
-                    + mBinding);
-        }
-
-        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
-        if (callingAppId != Process.NFC_UID) {
-            throw new SecurityException("no permission to enable Bluetooth quietly");
-        }
-
-        synchronized (mReceiver) {
-            mQuietEnableExternal = true;
-            mEnableExternal = true;
-            sendEnableMsg(true,
-                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
-        }
-        return true;
-    }
-
-    public boolean enable(AttributionSource attributionSource) throws RemoteException {
-        final String packageName = attributionSource.getPackageName();
-        if (!checkBluetoothPermissions(attributionSource, "enable", true)) {
-            if (DBG) {
-                Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
-            }
-            return false;
-        }
-
-        final int callingUid = Binder.getCallingUid();
-        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
-        if (!callerSystem && !isEnabled() && mWirelessConsentRequired
-                && startConsentUiIfNeeded(packageName,
-                callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
-            return false;
-        }
-
-        if (DBG) {
-            Slog.d(TAG, "enable(" + packageName + "):  mBluetooth =" + mBluetooth + " mBinding = "
-                    + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
-        }
-
-        synchronized (mReceiver) {
-            mQuietEnableExternal = false;
-            mEnableExternal = true;
-            // waive WRITE_SECURE_SETTINGS permission check
-            sendEnableMsg(false,
-                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
-        }
-        if (DBG) {
-            Slog.d(TAG, "enable returning");
-        }
-        return true;
-    }
-
-    public boolean disable(AttributionSource attributionSource, boolean persist)
-            throws RemoteException {
-        if (!persist) {
-            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
-                    "Need BLUETOOTH_PRIVILEGED permission");
-        }
-
-        final String packageName = attributionSource.getPackageName();
-        if (!checkBluetoothPermissions(attributionSource, "disable", true)) {
-            if (DBG) {
-                Slog.d(TAG, "disable(): not disabling - bluetooth disallowed");
-            }
-            return false;
-        }
-
-        final int callingUid = Binder.getCallingUid();
-        final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;
-        if (!callerSystem && isEnabled() && mWirelessConsentRequired
-                && startConsentUiIfNeeded(packageName,
-                callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
-            return false;
-        }
-
-        if (DBG) {
-            Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding);
-        }
-
-        synchronized (mReceiver) {
-            if (!isBluetoothPersistedStateOnAirplane()) {
-                if (persist) {
-                    persistBluetoothSetting(BLUETOOTH_OFF);
-                }
-                mEnableExternal = false;
-            }
-            sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
-                    packageName);
-        }
-        return true;
-    }
-
-    private boolean startConsentUiIfNeeded(String packageName,
-            int callingUid, String intentAction) throws RemoteException {
-        if (checkBluetoothPermissionWhenWirelessConsentRequired()) {
-            return false;
-        }
-        try {
-            // Validate the package only if we are going to use it
-            ApplicationInfo applicationInfo = mContext.getPackageManager()
-                    .getApplicationInfoAsUser(packageName,
-                            PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                            UserHandle.getUserId(callingUid));
-            if (applicationInfo.uid != callingUid) {
-                throw new SecurityException("Package " + packageName
-                        + " not in uid " + callingUid);
-            }
-
-            Intent intent = new Intent(intentAction);
-            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
-            intent.setFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            try {
-                mContext.startActivity(intent);
-            } catch (ActivityNotFoundException e) {
-                // Shouldn't happen
-                Slog.e(TAG, "Intent to handle action " + intentAction + " missing");
-                return false;
-            }
-            return true;
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new RemoteException(e.getMessage());
-        }
-    }
-
-    /**
-     * Check if AppOpsManager is available and the packageName belongs to uid
-     *
-     * A null package belongs to any uid
-     */
-    private void checkPackage(int uid, String packageName) {
-        if (mAppOps == null) {
-            Slog.w(TAG, "checkPackage(): called before system boot up, uid "
-                    + uid + ", packageName " + packageName);
-            throw new IllegalStateException("System has not boot yet");
-        }
-        if (packageName == null) {
-            Slog.w(TAG, "checkPackage(): called with null packageName from " + uid);
-            return;
-        }
-        try {
-            mAppOps.checkPackage(uid, packageName);
-        } catch (SecurityException e) {
-            Slog.w(TAG, "checkPackage(): " + packageName + " does not belong to uid " + uid);
-            throw new SecurityException(e.getMessage());
-        }
-    }
-
-    /**
-     * Check if the caller must still pass permission check or if the caller is exempted
-     * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check.
-     *
-     * Commands from some callers may be exempted from triggering the consent UI when
-     * enabling bluetooth. This exemption is checked via the
-     * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip
-     * the consent UI where it may otherwise be required.
-     *
-     * @hide
-     */
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    private boolean checkBluetoothPermissionWhenWirelessConsentRequired() {
-        int result = mContext.checkCallingPermission(
-                android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED);
-        return result == PackageManager.PERMISSION_GRANTED;
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void unbindAndFinish() {
-        if (DBG) {
-            Slog.d(TAG, "unbindAndFinish(): " + mBluetooth + " mBinding = " + mBinding
-                    + " mUnbinding = " + mUnbinding);
-        }
-
-        try {
-            mBluetoothLock.writeLock().lock();
-            if (mUnbinding) {
-                return;
-            }
-            mUnbinding = true;
-            mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
-            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE);
-            if (mBluetooth != null) {
-                //Unregister callback object
-                try {
-                    mBluetooth.unregisterCallback(mBluetoothCallback,
-                            mContext.getAttributionSource());
-                } catch (RemoteException re) {
-                    Slog.e(TAG, "Unable to unregister BluetoothCallback", re);
-                }
-                mBluetoothBinder = null;
-                mBluetooth = null;
-                mContext.unbindService(mConnection);
-                mUnbinding = false;
-                mBinding = false;
-            } else {
-                mUnbinding = false;
-            }
-            mBluetoothGatt = null;
-        } finally {
-            mBluetoothLock.writeLock().unlock();
-        }
-    }
-
-    public IBluetoothGatt getBluetoothGatt() {
-        // sync protection
-        return mBluetoothGatt;
-    }
-
-    @Override
-    public boolean bindBluetoothProfileService(int bluetoothProfile,
-            IBluetoothProfileServiceConnection proxy) {
-        if (mState != BluetoothAdapter.STATE_ON) {
-            if (DBG) {
-                Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile
-                        + ", while Bluetooth was disabled");
-            }
-            return false;
-        }
-        synchronized (mProfileServices) {
-            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
-            if (psc == null) {
-                if (DBG) {
-                    Slog.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: "
-                            + bluetoothProfile);
-                }
-
-                Intent intent;
-                if (bluetoothProfile == BluetoothProfile.HEADSET) {
-                    intent = new Intent(IBluetoothHeadset.class.getName());
-                } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) {
-                    intent = new Intent(IBluetoothLeCallControl.class.getName());
-                } else {
-                    return false;
-                }
-
-                psc = new ProfileServiceConnections(intent);
-                if (!psc.bindService()) {
-                    return false;
-                }
-
-                mProfileServices.put(new Integer(bluetoothProfile), psc);
-            }
-        }
-
-        // Introducing a delay to give the client app time to prepare
-        Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
-        addProxyMsg.arg1 = bluetoothProfile;
-        addProxyMsg.obj = proxy;
-        mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
-        return true;
-    }
-
-    @Override
-    public void unbindBluetoothProfileService(int bluetoothProfile,
-            IBluetoothProfileServiceConnection proxy) {
-        synchronized (mProfileServices) {
-            Integer profile = new Integer(bluetoothProfile);
-            ProfileServiceConnections psc = mProfileServices.get(profile);
-            if (psc == null) {
-                return;
-            }
-            psc.removeProxy(proxy);
-            if (psc.isEmpty()) {
-                // All prxoies are disconnected, unbind with the service.
-                try {
-                    mContext.unbindService(psc);
-                } catch (IllegalArgumentException e) {
-                    Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
-                }
-                mProfileServices.remove(profile);
-            }
-        }
-    }
-
-    private void unbindAllBluetoothProfileServices() {
-        synchronized (mProfileServices) {
-            for (Integer i : mProfileServices.keySet()) {
-                ProfileServiceConnections psc = mProfileServices.get(i);
-                try {
-                    mContext.unbindService(psc);
-                } catch (IllegalArgumentException e) {
-                    Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
-                }
-                psc.removeAllProxies();
-            }
-            mProfileServices.clear();
-        }
-    }
-
-    /**
-     * Send enable message and set adapter name and address. Called when the boot phase becomes
-     * PHASE_SYSTEM_SERVICES_READY.
-     */
-    public void handleOnBootPhase() {
-        if (DBG) {
-            Slog.d(TAG, "Bluetooth boot completed");
-        }
-        mAppOps = mContext.getSystemService(AppOpsManager.class);
-        UserManagerInternal userManagerInternal =
-                LocalServices.getService(UserManagerInternal.class);
-        userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
-        final boolean isBluetoothDisallowed = isBluetoothDisallowed();
-        if (isBluetoothDisallowed) {
-            return;
-        }
-        final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
-        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
-            if (DBG) {
-                Slog.d(TAG, "Auto-enabling Bluetooth.");
-            }
-            sendEnableMsg(mQuietEnableExternal,
-                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
-                    mContext.getPackageName());
-        } else if (!isNameAndAddressSet()) {
-            if (DBG) {
-                Slog.d(TAG, "Getting adapter name and address");
-            }
-            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
-            mHandler.sendMessage(getMsg);
-        }
-
-        mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext);
-        if (mBluetoothAirplaneModeListener != null) {
-            mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper);
-        }
-        registerForProvisioningStateChange();
-        mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this, DBG);
-    }
-
-    /**
-     * Called when switching to a different foreground user.
-     */
-    public void handleOnSwitchUser(int userHandle) {
-        if (DBG) {
-            Slog.d(TAG, "User " + userHandle + " switched");
-        }
-        mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
-    }
-
-    /**
-     * Called when user is unlocked.
-     */
-    public void handleOnUnlockUser(int userHandle) {
-        if (DBG) {
-            Slog.d(TAG, "User " + userHandle + " unlocked");
-        }
-        mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
-    }
-
-    /**
-     * This class manages the clients connected to a given ProfileService
-     * and maintains the connection with that service.
-     */
-    private final class ProfileServiceConnections
-            implements ServiceConnection, IBinder.DeathRecipient {
-        final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
-                new RemoteCallbackList<IBluetoothProfileServiceConnection>();
-        IBinder mService;
-        ComponentName mClassName;
-        Intent mIntent;
-        boolean mInvokingProxyCallbacks = false;
-
-        ProfileServiceConnections(Intent intent) {
-            mService = null;
-            mClassName = null;
-            mIntent = intent;
-        }
-
-        private boolean bindService() {
-            int state = BluetoothAdapter.STATE_OFF;
-            try {
-                mBluetoothLock.readLock().lock();
-                if (mBluetooth != null) {
-                    state = mBluetooth.getState();
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to call getState", e);
-                return false;
-            } finally {
-                mBluetoothLock.readLock().unlock();
-            }
-
-            if (state != BluetoothAdapter.STATE_ON) {
-                if (DBG) {
-                    Slog.d(TAG, "Unable to bindService while Bluetooth is disabled");
-                }
-                return false;
-            }
-
-            if (mIntent != null && mService == null && doBind(mIntent, this, 0,
-                    UserHandle.CURRENT_OR_SELF)) {
-                Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
-                msg.obj = this;
-                mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
-                return true;
-            }
-            Slog.w(TAG, "Unable to bind with intent: " + mIntent);
-            return false;
-        }
-
-        private void addProxy(IBluetoothProfileServiceConnection proxy) {
-            mProxies.register(proxy);
-            if (mService != null) {
-                try {
-                    proxy.onServiceConnected(mClassName, mService);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to connect to proxy", e);
-                }
-            } else {
-                if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
-                    Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
-                    msg.obj = this;
-                    mHandler.sendMessage(msg);
-                }
-            }
-        }
-
-        private void removeProxy(IBluetoothProfileServiceConnection proxy) {
-            if (proxy != null) {
-                if (mProxies.unregister(proxy)) {
-                    try {
-                        proxy.onServiceDisconnected(mClassName);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to disconnect proxy", e);
-                    }
-                }
-            } else {
-                Slog.w(TAG, "Trying to remove a null proxy");
-            }
-        }
-
-        private void removeAllProxies() {
-            onServiceDisconnected(mClassName);
-            mProxies.kill();
-        }
-
-        private boolean isEmpty() {
-            return mProxies.getRegisteredCallbackCount() == 0;
-        }
-
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder service) {
-            // remove timeout message
-            mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
-            mService = service;
-            mClassName = className;
-            try {
-                mService.linkToDeath(this, 0);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to linkToDeath", e);
-            }
-
-            if (mInvokingProxyCallbacks) {
-                Slog.e(TAG, "Proxy callbacks already in progress.");
-                return;
-            }
-            mInvokingProxyCallbacks = true;
-
-            final int n = mProxies.beginBroadcast();
-            try {
-                for (int i = 0; i < n; i++) {
-                    try {
-                        mProxies.getBroadcastItem(i).onServiceConnected(className, service);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to connect to proxy", e);
-                    }
-                }
-            } finally {
-                mProxies.finishBroadcast();
-                mInvokingProxyCallbacks = false;
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            if (mService == null) {
-                return;
-            }
-            try {
-                mService.unlinkToDeath(this, 0);
-            } catch (NoSuchElementException e) {
-                Log.e(TAG, "error unlinking to death", e);
-            }
-            mService = null;
-            mClassName = null;
-
-            if (mInvokingProxyCallbacks) {
-                Slog.e(TAG, "Proxy callbacks already in progress.");
-                return;
-            }
-            mInvokingProxyCallbacks = true;
-
-            final int n = mProxies.beginBroadcast();
-            try {
-                for (int i = 0; i < n; i++) {
-                    try {
-                        mProxies.getBroadcastItem(i).onServiceDisconnected(className);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to disconnect from proxy", e);
-                    }
-                }
-            } finally {
-                mProxies.finishBroadcast();
-                mInvokingProxyCallbacks = false;
-            }
-        }
-
-        @Override
-        public void binderDied() {
-            if (DBG) {
-                Slog.w(TAG, "Profile service for profile: " + mClassName + " died.");
-            }
-            onServiceDisconnected(mClassName);
-            // Trigger rebind
-            Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
-            msg.obj = this;
-            mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
-        }
-    }
-
-    private void sendBluetoothStateCallback(boolean isUp) {
-        try {
-            int n = mStateChangeCallbacks.beginBroadcast();
-            if (DBG) {
-                Slog.d(TAG, "Broadcasting onBluetoothStateChange(" + isUp + ") to " + n
-                        + " receivers.");
-            }
-            for (int i = 0; i < n; i++) {
-                try {
-                    mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i, e);
-                }
-            }
-        } finally {
-            mStateChangeCallbacks.finishBroadcast();
-        }
-    }
-
-    /**
-     * Inform BluetoothAdapter instances that Adapter service is up
-     */
-    private void sendBluetoothServiceUpCallback() {
-        synchronized (mCallbacks) {
-            try {
-                int n = mCallbacks.beginBroadcast();
-                Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
-                for (int i = 0; i < n; i++) {
-                    try {
-                        mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
-                    }
-                }
-            } finally {
-                mCallbacks.finishBroadcast();
-            }
-        }
-    }
-
-    /**
-     * Inform BluetoothAdapter instances that Adapter service is down
-     */
-    private void sendBluetoothServiceDownCallback() {
-        synchronized (mCallbacks) {
-            try {
-                int n = mCallbacks.beginBroadcast();
-                Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
-                for (int i = 0; i < n; i++) {
-                    try {
-                        mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
-                    }
-                }
-            } finally {
-                mCallbacks.finishBroadcast();
-            }
-        }
-    }
-
-    public String getAddress(AttributionSource attributionSource) {
-        if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getAddress")) {
-            return null;
-        }
-
-        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
-            Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
-            return null;
-        }
-
-        if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
-                != PackageManager.PERMISSION_GRANTED) {
-            return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
-        }
-
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth != null) {
-                return mBluetooth.getAddressWithAttribution(attributionSource);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG,
-                    "getAddress(): Unable to retrieve address remotely. Returning cached address",
-                    e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-
-        // mAddress is accessed from outside.
-        // It is alright without a lock. Here, bluetooth is off, no other thread is
-        // changing mAddress
-        return mAddress;
-    }
-
-    public String getName(AttributionSource attributionSource) {
-        if (!checkConnectPermissionForDataDelivery(mContext, attributionSource, "getName")) {
-            return null;
-        }
-
-        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
-            Slog.w(TAG, "getName(): not allowed for non-active and non system user");
-            return null;
-        }
-
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth != null) {
-                return mBluetooth.getName(attributionSource);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-
-        // mName is accessed from outside.
-        // It alright without a lock. Here, bluetooth is off, no other thread is
-        // changing mName
-        return mName;
-    }
-
-    private class BluetoothServiceConnection implements ServiceConnection {
-        public void onServiceConnected(ComponentName componentName, IBinder service) {
-            String name = componentName.getClassName();
-            if (DBG) {
-                Slog.d(TAG, "BluetoothServiceConnection: " + name);
-            }
-            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
-            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
-                msg.arg1 = SERVICE_IBLUETOOTH;
-            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
-                msg.arg1 = SERVICE_IBLUETOOTHGATT;
-            } else {
-                Slog.e(TAG, "Unknown service connected: " + name);
-                return;
-            }
-            msg.obj = service;
-            mHandler.sendMessage(msg);
-        }
-
-        public void onServiceDisconnected(ComponentName componentName) {
-            // Called if we unexpectedly disconnect.
-            String name = componentName.getClassName();
-            if (DBG) {
-                Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
-            }
-            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
-            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
-                msg.arg1 = SERVICE_IBLUETOOTH;
-            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
-                msg.arg1 = SERVICE_IBLUETOOTHGATT;
-            } else {
-                Slog.e(TAG, "Unknown service disconnected: " + name);
-                return;
-            }
-            mHandler.sendMessage(msg);
-        }
-    }
-
-    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
-
-    private class BluetoothHandler extends Handler {
-        boolean mGetNameAddressOnly = false;
-        private int mWaitForEnableRetry;
-        private int mWaitForDisableRetry;
-
-        BluetoothHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MESSAGE_GET_NAME_AND_ADDRESS:
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
-                    }
-                    try {
-                        mBluetoothLock.writeLock().lock();
-                        if ((mBluetooth == null) && (!mBinding)) {
-                            if (DBG) {
-                                Slog.d(TAG, "Binding to service to get name and address");
-                            }
-                            mGetNameAddressOnly = true;
-                            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
-                            mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
-                            Intent i = new Intent(IBluetooth.class.getName());
-                            if (!doBind(i, mConnection,
-                                    Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
-                                    UserHandle.CURRENT)) {
-                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
-                            } else {
-                                mBinding = true;
-                            }
-                        } else if (mBluetooth != null) {
-                            try {
-                                storeNameAndAddress(
-                                        mBluetooth.getName(mContext.getAttributionSource()),
-                                        mBluetooth.getAddressWithAttribution(
-                                                mContext.getAttributionSource()));
-                            } catch (RemoteException re) {
-                                Slog.e(TAG, "Unable to grab names", re);
-                            }
-                            if (mGetNameAddressOnly && !mEnable) {
-                                unbindAndFinish();
-                            }
-                            mGetNameAddressOnly = false;
-                        }
-                    } finally {
-                        mBluetoothLock.writeLock().unlock();
-                    }
-                    break;
-
-                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, isBle), ENABLE_DISABLE_DELAY_MS);
-                        break;
-                    }
-
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = "
-                                + mBluetooth);
-                    }
-                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-                    mEnable = true;
-
-                    if (isBle == 0) {
-                        persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
-                    }
-
-                    // Use service interface to get the exact state
-                    try {
-                        mBluetoothLock.readLock().lock();
-                        if (mBluetooth != null) {
-                            boolean isHandled = true;
-                            int state = mBluetooth.getState();
-                            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(mContext.getAttributionSource());
-                                    }
-                                    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);
-                    } finally {
-                        mBluetoothLock.readLock().unlock();
-                    }
-
-                    mQuietEnable = (quietEnable == 1);
-                    if (mBluetooth == null) {
-                        handleEnable(mQuietEnable);
-                    } else {
-                        //
-                        // We need to wait until transitioned to STATE_OFF and
-                        // the previous Bluetooth process has exited. The
-                        // waiting period has three components:
-                        // (a) Wait until the local state is STATE_OFF. This
-                        //     is accomplished by sending delay a message
-                        //     MESSAGE_HANDLE_ENABLE_DELAYED
-                        // (b) Wait until the STATE_OFF state is updated to
-                        //     all components.
-                        // (c) Wait until the Bluetooth process exits, and
-                        //     ActivityManager detects it.
-                        // The waiting for (b) and (c) is accomplished by
-                        // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
-                        // message. The delay time is backed off if Bluetooth
-                        // continuously failed to turn on itself.
-                        //
-                        mWaitForEnableRetry = 0;
-                        Message enableDelayedMsg =
-                                mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
-                        mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
-                    }
-                    break;
-
-                case MESSAGE_DISABLE:
-                    if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding
-                            || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
-                        // We are handling enable or disable right now, wait for it.
-                        mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE),
-                                ENABLE_DISABLE_DELAY_MS);
-                        break;
-                    }
-
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth
-                                + ", mBinding = " + mBinding);
-                    }
-                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-
-                    if (mEnable && mBluetooth != null) {
-                        mWaitForDisableRetry = 0;
-                        Message disableDelayedMsg =
-                                mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0);
-                        mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
-                    } else {
-                        mEnable = false;
-                        handleDisable();
-                    }
-                    break;
-
-                case MESSAGE_HANDLE_ENABLE_DELAYED: {
-                    // The Bluetooth is turning off, wait for STATE_OFF
-                    if (mState != BluetoothAdapter.STATE_OFF) {
-                        if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
-                            mWaitForEnableRetry++;
-                            Message enableDelayedMsg =
-                                    mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
-                            mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
-                            break;
-                        } else {
-                            Slog.e(TAG, "Wait for STATE_OFF timeout");
-                        }
-                    }
-                    // Either state is changed to STATE_OFF or reaches the maximum retry, we
-                    // should move forward to the next step.
-                    mWaitForEnableRetry = 0;
-                    Message restartMsg =
-                            mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-                    mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
-                    Slog.d(TAG, "Handle enable is finished");
-                    break;
-                }
-
-                case MESSAGE_HANDLE_DISABLE_DELAYED: {
-                    boolean disabling = (msg.arg1 == 1);
-                    Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling);
-                    if (!disabling) {
-                        // The Bluetooth is turning on, wait for STATE_ON
-                        if (mState != BluetoothAdapter.STATE_ON) {
-                            if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
-                                mWaitForDisableRetry++;
-                                Message disableDelayedMsg = mHandler.obtainMessage(
-                                        MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0);
-                                mHandler.sendMessageDelayed(disableDelayedMsg,
-                                        ENABLE_DISABLE_DELAY_MS);
-                                break;
-                            } else {
-                                Slog.e(TAG, "Wait for STATE_ON timeout");
-                            }
-                        }
-                        // Either state is changed to STATE_ON or reaches the maximum retry, we
-                        // should move forward to the next step.
-                        mWaitForDisableRetry = 0;
-                        mEnable = false;
-                        handleDisable();
-                        // Wait for state exiting STATE_ON
-                        Message disableDelayedMsg =
-                                mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
-                        mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
-                    } else {
-                        // The Bluetooth is turning off, wait for exiting STATE_ON
-                        if (mState == BluetoothAdapter.STATE_ON) {
-                            if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
-                                mWaitForDisableRetry++;
-                                Message disableDelayedMsg = mHandler.obtainMessage(
-                                        MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
-                                mHandler.sendMessageDelayed(disableDelayedMsg,
-                                        ENABLE_DISABLE_DELAY_MS);
-                                break;
-                            } else {
-                                Slog.e(TAG, "Wait for exiting STATE_ON timeout");
-                            }
-                        }
-                        // Either state is exited from STATE_ON or reaches the maximum retry, we
-                        // should move forward to the next step.
-                        Slog.d(TAG, "Handle disable is finished");
-                    }
-                    break;
-                }
-
-                case MESSAGE_RESTORE_USER_SETTING:
-                    if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
-                        if (DBG) {
-                            Slog.d(TAG, "Restore Bluetooth state to disabled");
-                        }
-                        persistBluetoothSetting(BLUETOOTH_OFF);
-                        mEnableExternal = false;
-                        sendDisableMsg(
-                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
-                                mContext.getPackageName());
-                    } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
-                        if (DBG) {
-                            Slog.d(TAG, "Restore Bluetooth state to enabled");
-                        }
-                        mQuietEnableExternal = false;
-                        mEnableExternal = true;
-                        // waive WRITE_SECURE_SETTINGS permission check
-                        sendEnableMsg(false,
-                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
-                                mContext.getPackageName());
-                    }
-                    break;
-                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
-                    IBluetoothStateChangeCallback callback =
-                            (IBluetoothStateChangeCallback) msg.obj;
-                    mStateChangeCallbacks.register(callback);
-                    break;
-                }
-                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: {
-                    IBluetoothStateChangeCallback callback =
-                            (IBluetoothStateChangeCallback) msg.obj;
-                    mStateChangeCallbacks.unregister(callback);
-                    break;
-                }
-                case MESSAGE_ADD_PROXY_DELAYED: {
-                    ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
-                    if (psc == null) {
-                        break;
-                    }
-                    IBluetoothProfileServiceConnection proxy =
-                            (IBluetoothProfileServiceConnection) msg.obj;
-                    psc.addProxy(proxy);
-                    break;
-                }
-                case MESSAGE_BIND_PROFILE_SERVICE: {
-                    ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
-                    removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
-                    if (psc == null) {
-                        break;
-                    }
-                    psc.bindService();
-                    break;
-                }
-                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
-                    }
-
-                    IBinder service = (IBinder) msg.obj;
-                    try {
-                        mBluetoothLock.writeLock().lock();
-                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
-                            mBluetoothGatt =
-                                    IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
-                            continueFromBleOnState();
-                            break;
-                        } // else must be SERVICE_IBLUETOOTH
-
-                        //Remove timeout
-                        mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
-
-                        mBinding = false;
-                        mBluetoothBinder = service;
-                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
-
-                        if (!isNameAndAddressSet()) {
-                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
-                            mHandler.sendMessage(getMsg);
-                            if (mGetNameAddressOnly) {
-                                return;
-                            }
-                        }
-
-                        //Register callback object
-                        try {
-                            mBluetooth.registerCallback(mBluetoothCallback,
-                                    mContext.getAttributionSource());
-                        } catch (RemoteException re) {
-                            Slog.e(TAG, "Unable to register BluetoothCallback", re);
-                        }
-                        //Inform BluetoothAdapter instances that service is up
-                        sendBluetoothServiceUpCallback();
-
-                        //Do enable request
-                        try {
-                            if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) {
-                                Slog.e(TAG, "IBluetooth.enable() returned false");
-                            }
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Unable to call enable()", e);
-                        }
-                    } finally {
-                        mBluetoothLock.writeLock().unlock();
-                    }
-
-                    if (!mEnable) {
-                        waitForState(Set.of(BluetoothAdapter.STATE_ON));
-                        handleDisable();
-                        waitForState(Set.of(BluetoothAdapter.STATE_OFF,
-                                BluetoothAdapter.STATE_TURNING_ON,
-                                BluetoothAdapter.STATE_TURNING_OFF,
-                                BluetoothAdapter.STATE_BLE_TURNING_ON,
-                                BluetoothAdapter.STATE_BLE_ON,
-                                BluetoothAdapter.STATE_BLE_TURNING_OFF));
-                    }
-                    break;
-                }
-                case MESSAGE_BLUETOOTH_STATE_CHANGE: {
-                    int prevState = msg.arg1;
-                    int newState = msg.arg2;
-                    if (DBG) {
-                        Slog.d(TAG,
-                                "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
-                                        prevState) + " > " + BluetoothAdapter.nameForState(
-                                        newState));
-                    }
-                    mState = newState;
-                    bluetoothStateChangeHandler(prevState, newState);
-                    // handle error state transition case from TURNING_ON to OFF
-                    // unbind and rebind bluetooth service and enable bluetooth
-                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) && (newState
-                            == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) {
-                        recoverBluetoothServiceFromError(false);
-                    }
-                    if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState
-                            == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) {
-                        recoverBluetoothServiceFromError(true);
-                    }
-                    // If we tried to enable BT while BT was in the process of shutting down,
-                    // wait for the BT process to fully tear down and then force a restart
-                    // here.  This is a bit of a hack (b/29363429).
-                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) && (newState
-                            == BluetoothAdapter.STATE_OFF)) {
-                        if (mEnable) {
-                            Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
-                            waitForState(Set.of(BluetoothAdapter.STATE_OFF));
-                            Message restartMsg =
-                                    mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-                            mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
-                        }
-                    }
-                    if (newState == BluetoothAdapter.STATE_ON
-                            || newState == BluetoothAdapter.STATE_BLE_ON) {
-                        // bluetooth is working, reset the counter
-                        if (mErrorRecoveryRetryCounter != 0) {
-                            Slog.w(TAG, "bluetooth is recovered from error");
-                            mErrorRecoveryRetryCounter = 0;
-                        }
-                    }
-                    break;
-                }
-                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: {
-                    Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED(" + msg.arg1 + ")");
-                    try {
-                        mBluetoothLock.writeLock().lock();
-                        if (msg.arg1 == SERVICE_IBLUETOOTH) {
-                            // if service is unbinded already, do nothing and return
-                            if (mBluetooth == null) {
-                                break;
-                            }
-                            mBluetooth = null;
-                        } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
-                            mBluetoothGatt = null;
-                            break;
-                        } else {
-                            Slog.e(TAG, "Unknown argument for service disconnect!");
-                            break;
-                        }
-                    } finally {
-                        mBluetoothLock.writeLock().unlock();
-                    }
-
-                    // log the unexpected crash
-                    addCrashLog();
-                    addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
-                            mContext.getPackageName(), false);
-                    if (mEnable) {
-                        mEnable = false;
-                        // Send a Bluetooth Restart message
-                        Message restartMsg =
-                                mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-                        mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
-                    }
-
-                    sendBluetoothServiceDownCallback();
-
-                    // Send BT state broadcast to update
-                    // the BT icon correctly
-                    if ((mState == BluetoothAdapter.STATE_TURNING_ON) || (mState
-                            == BluetoothAdapter.STATE_ON)) {
-                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
-                                BluetoothAdapter.STATE_TURNING_OFF);
-                        mState = BluetoothAdapter.STATE_TURNING_OFF;
-                    }
-                    if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
-                        bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
-                                BluetoothAdapter.STATE_OFF);
-                    }
-
-                    mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
-                    mState = BluetoothAdapter.STATE_OFF;
-                    break;
-                }
-                case MESSAGE_RESTART_BLUETOOTH_SERVICE: {
-                    mErrorRecoveryRetryCounter++;
-                    Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE: retry count="
-                            + mErrorRecoveryRetryCounter);
-                    if (mErrorRecoveryRetryCounter < MAX_ERROR_RESTART_RETRIES) {
-                        /* Enable without persisting the setting as
-                         it doesnt change when IBluetooth
-                         service restarts */
-                        mEnable = true;
-                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
-                                mContext.getPackageName(), true);
-                        handleEnable(mQuietEnable);
-                    } else {
-                        Slog.e(TAG, "Reach maximum retry to restart Bluetooth!");
-                    }
-                    break;
-                }
-                case MESSAGE_TIMEOUT_BIND: {
-                    Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
-                    mBluetoothLock.writeLock().lock();
-                    mBinding = false;
-                    mBluetoothLock.writeLock().unlock();
-                    break;
-                }
-                case MESSAGE_TIMEOUT_UNBIND: {
-                    Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
-                    mBluetoothLock.writeLock().lock();
-                    mUnbinding = false;
-                    mBluetoothLock.writeLock().unlock();
-                    break;
-                }
-
-                case MESSAGE_USER_SWITCHED: {
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_USER_SWITCHED");
-                    }
-                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
-
-                    /* disable and enable BT when detect a user switch */
-                    if (mBluetooth != null && isEnabled()) {
-                        restartForReason(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH);
-                    } else if (mBinding || mBluetooth != null) {
-                        Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
-                        userMsg.arg2 = 1 + msg.arg2;
-                        // if user is switched when service is binding retry after a delay
-                        mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
-                        if (DBG) {
-                            Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
-                        }
-                    }
-                    break;
-                }
-                case MESSAGE_USER_UNLOCKED: {
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
-                    }
-                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
-
-                    if (mEnable && !mBinding && (mBluetooth == null)) {
-                        // We should be connected, but we gave up for some
-                        // reason; maybe the Bluetooth service wasn't encryption
-                        // aware, so try binding again.
-                        if (DBG) {
-                            Slog.d(TAG, "Enabled but not bound; retrying after unlock");
-                        }
-                        handleEnable(mQuietEnable);
-                    }
-                    break;
-                }
-                case MESSAGE_INIT_FLAGS_CHANGED: {
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED");
-                    }
-                    mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
-                    if (mBluetoothModeChangeHelper.isMediaProfileConnected()) {
-                        Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by "
-                                + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS
-                                + " ms due to existing connections");
-                        mHandler.sendEmptyMessageDelayed(
-                                MESSAGE_INIT_FLAGS_CHANGED,
-                                DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS);
-                        break;
-                    }
-                    if (!isDeviceProvisioned()) {
-                        Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by "
-                                + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS
-                                +  "ms because device is not provisioned");
-                        mHandler.sendEmptyMessageDelayed(
-                                MESSAGE_INIT_FLAGS_CHANGED,
-                                DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS);
-                        break;
-                    }
-                    if (mBluetooth != null && isEnabled()) {
-                        Slog.i(TAG, "Restarting Bluetooth due to init flag change");
-                        restartForReason(
-                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED);
-                    }
-                    break;
-                }
-            }
-        }
-
-        @RequiresPermission(allOf = {
-                android.Manifest.permission.BLUETOOTH_CONNECT,
-                android.Manifest.permission.BLUETOOTH_PRIVILEGED
-        })
-        private void restartForReason(int reason) {
-            try {
-                mBluetoothLock.readLock().lock();
-                if (mBluetooth != null) {
-                    mBluetooth.unregisterCallback(mBluetoothCallback,
-                            mContext.getAttributionSource());
-                }
-            } catch (RemoteException re) {
-                Slog.e(TAG, "Unable to unregister", re);
-            } finally {
-                mBluetoothLock.readLock().unlock();
-            }
-
-            if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
-                // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
-                bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
-                mState = BluetoothAdapter.STATE_OFF;
-            }
-            if (mState == BluetoothAdapter.STATE_OFF) {
-                bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON);
-                mState = BluetoothAdapter.STATE_TURNING_ON;
-            }
-
-            waitForState(Set.of(BluetoothAdapter.STATE_ON));
-
-            if (mState == BluetoothAdapter.STATE_TURNING_ON) {
-                bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
-            }
-
-            unbindAllBluetoothProfileServices();
-            // disable
-            addActiveLog(reason, mContext.getPackageName(), false);
-            handleDisable();
-            // Pbap service need receive STATE_TURNING_OFF intent to close
-            bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
-                    BluetoothAdapter.STATE_TURNING_OFF);
-
-            boolean didDisableTimeout =
-                    !waitForState(Set.of(BluetoothAdapter.STATE_OFF));
-
-            bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
-                    BluetoothAdapter.STATE_OFF);
-            sendBluetoothServiceDownCallback();
-
-            try {
-                mBluetoothLock.writeLock().lock();
-                if (mBluetooth != null) {
-                    mBluetooth = null;
-                    // Unbind
-                    mContext.unbindService(mConnection);
-                }
-                mBluetoothGatt = null;
-            } finally {
-                mBluetoothLock.writeLock().unlock();
-            }
-
-            //
-            // If disabling Bluetooth times out, wait for an
-            // additional amount of time to ensure the process is
-            // shut down completely before attempting to restart.
-            //
-            if (didDisableTimeout) {
-                SystemClock.sleep(3000);
-            } else {
-                SystemClock.sleep(100);
-            }
-
-            mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
-            mState = BluetoothAdapter.STATE_OFF;
-            // enable
-            addActiveLog(reason, mContext.getPackageName(), true);
-            // mEnable flag could have been reset on disableBLE. Reenable it.
-            mEnable = true;
-            handleEnable(mQuietEnable);
-        }
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private void handleEnable(boolean quietMode) {
-        mQuietEnable = quietMode;
-
-        try {
-            mBluetoothLock.writeLock().lock();
-            if ((mBluetooth == null) && (!mBinding)) {
-                Slog.d(TAG, "binding Bluetooth service");
-                //Start bind timeout and bind
-                Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
-                mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
-                Intent i = new Intent(IBluetooth.class.getName());
-                if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
-                        UserHandle.CURRENT)) {
-                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
-                } else {
-                    mBinding = true;
-                }
-            } else if (mBluetooth != null) {
-                //Enable bluetooth
-                try {
-                    if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) {
-                        Slog.e(TAG, "IBluetooth.enable() returned false");
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to call enable()", e);
-                }
-            }
-        } finally {
-            mBluetoothLock.writeLock().unlock();
-        }
-    }
-
-    boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
-        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
-        intent.setComponent(comp);
-        if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
-            Slog.e(TAG, "Fail to bind to: " + intent);
-            return false;
-        }
-        return true;
-    }
-
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    private void handleDisable() {
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth != null) {
-                if (DBG) {
-                    Slog.d(TAG, "Sending off request.");
-                }
-                if (!mBluetooth.disable(mContext.getAttributionSource())) {
-                    Slog.e(TAG, "IBluetooth.disable() returned false");
-                }
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to call disable()", e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-    }
-
-    private boolean checkIfCallerIsForegroundUser() {
-        int foregroundUser;
-        int callingUser = UserHandle.getCallingUserId();
-        int callingUid = Binder.getCallingUid();
-        final long callingIdentity = Binder.clearCallingIdentity();
-        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        UserInfo ui = um.getProfileParent(callingUser);
-        int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
-        int callingAppId = UserHandle.getAppId(callingUid);
-        boolean valid = false;
-        try {
-            foregroundUser = ActivityManager.getCurrentUser();
-            valid = (callingUser == foregroundUser) || parentUser == foregroundUser
-                    || callingAppId == Process.NFC_UID || callingAppId == mSystemUiUid
-                    || callingAppId == Process.SHELL_UID;
-            if (DBG && !valid) {
-                Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser="
-                        + callingUser + " parentUser=" + parentUser + " foregroundUser="
-                        + foregroundUser);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-        return valid;
-    }
-
-    private void sendBleStateChanged(int prevState, int newState) {
-        if (DBG) {
-            Slog.d(TAG,
-                    "Sending BLE State Change: " + BluetoothAdapter.nameForState(prevState) + " > "
-                            + BluetoothAdapter.nameForState(newState));
-        }
-        // Send broadcast message to everyone else
-        Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
-        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
-        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions());
-    }
-
-    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;
-    }
-
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    private void bluetoothStateChangeHandler(int prevState, int newState) {
-        boolean isStandardBroadcast = true;
-        if (prevState == newState) { // No change. Nothing to do.
-            return;
-        }
-        // Notify all proxy objects first of adapter state change
-        if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
-            boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
-                    && newState == BluetoothAdapter.STATE_BLE_ON);
-
-            if (newState == BluetoothAdapter.STATE_OFF) {
-                // If Bluetooth is off, send service down event to proxy objects, and unbind
-                if (DBG) {
-                    Slog.d(TAG, "Bluetooth is complete send Service Down");
-                }
-                sendBluetoothServiceDownCallback();
-                unbindAndFinish();
-                sendBleStateChanged(prevState, newState);
-
-                /* 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
-                if (DBG) {
-                    Slog.d(TAG, "Bluetooth is in LE only mode");
-                }
-                if (mBluetoothGatt != null || !mContext.getPackageManager()
-                            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
-                    continueFromBleOnState();
-                } else {
-                    if (DBG) {
-                        Slog.d(TAG, "Binding Bluetooth GATT service");
-                    }
-                    Intent i = new Intent(IBluetoothGatt.class.getName());
-                    doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
-                            UserHandle.CURRENT);
-                }
-                sendBleStateChanged(prevState, newState);
-                //Don't broadcase this as std intent
-                isStandardBroadcast = false;
-
-            } else if (intermediate_off) {
-                if (DBG) {
-                    Slog.d(TAG, "Intermediate off, back to LE only mode");
-                }
-                // For LE only mode, broadcast as is
-                sendBleStateChanged(prevState, newState);
-                sendBluetoothStateCallback(false); // BT is OFF for general users
-                // Broadcast as STATE_OFF
-                newState = BluetoothAdapter.STATE_OFF;
-                sendBrEdrDownCallback(mContext.getAttributionSource());
-            }
-        } else if (newState == BluetoothAdapter.STATE_ON) {
-            boolean isUp = (newState == BluetoothAdapter.STATE_ON);
-            sendBluetoothStateCallback(isUp);
-            sendBleStateChanged(prevState, newState);
-
-        } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
-                || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
-            sendBleStateChanged(prevState, newState);
-            isStandardBroadcast = false;
-
-        } else if (newState == BluetoothAdapter.STATE_TURNING_ON
-                || newState == BluetoothAdapter.STATE_TURNING_OFF) {
-            sendBleStateChanged(prevState, newState);
-        }
-
-        if (isStandardBroadcast) {
-            if (prevState == BluetoothAdapter.STATE_BLE_ON) {
-                // 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);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null,
-                    getTempAllowlistBroadcastOptions());
-        }
-    }
-
-    private boolean waitForState(Set<Integer> states) {
-        int i = 0;
-        while (i < 10) {
-            try {
-                mBluetoothLock.readLock().lock();
-                if (mBluetooth == null) {
-                    break;
-                }
-                if (states.contains(mBluetooth.getState())) {
-                    return true;
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "getState()", e);
-                break;
-            } finally {
-                mBluetoothLock.readLock().unlock();
-            }
-            SystemClock.sleep(300);
-            i++;
-        }
-        Slog.e(TAG, "waitForState " + states + " time out");
-        return false;
-    }
-
-    private void sendDisableMsg(int reason, String packageName) {
-        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
-        addActiveLog(reason, packageName, false);
-    }
-
-    private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
-        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();
-    }
-
-    private void addActiveLog(int reason, String packageName, boolean enable) {
-        synchronized (mActiveLogs) {
-            if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
-                mActiveLogs.remove();
-            }
-            mActiveLogs.add(
-                    new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
-        }
-
-        int state = enable ? FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED :
-                             FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED;
-        FrameworkStatsLog.write_non_chained(FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
-                Binder.getCallingUid(), null, state, reason, packageName);
-    }
-
-    private void addCrashLog() {
-        synchronized (mCrashTimestamps) {
-            if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) {
-                mCrashTimestamps.removeFirst();
-            }
-            mCrashTimestamps.add(System.currentTimeMillis());
-            mCrashes++;
-        }
-    }
-
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    private void recoverBluetoothServiceFromError(boolean clearBle) {
-        Slog.e(TAG, "recoverBluetoothServiceFromError");
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth != null) {
-                //Unregister callback object
-                mBluetooth.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource());
-            }
-        } catch (RemoteException re) {
-            Slog.e(TAG, "Unable to unregister", re);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-
-        SystemClock.sleep(500);
-
-        // disable
-        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
-                mContext.getPackageName(), false);
-        handleDisable();
-
-        waitForState(Set.of(BluetoothAdapter.STATE_OFF));
-
-        sendBluetoothServiceDownCallback();
-
-        try {
-            mBluetoothLock.writeLock().lock();
-            if (mBluetooth != null) {
-                mBluetooth = null;
-                // Unbind
-                mContext.unbindService(mConnection);
-            }
-            mBluetoothGatt = null;
-        } finally {
-            mBluetoothLock.writeLock().unlock();
-        }
-
-        mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
-        mState = BluetoothAdapter.STATE_OFF;
-
-        if (clearBle) {
-            clearBleApps();
-        }
-
-        mEnable = false;
-
-        // Send a Bluetooth Restart message to reenable bluetooth
-        Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
-        mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS);
-    }
-
-    private boolean isBluetoothDisallowed() {
-        final long callingIdentity = Binder.clearCallingIdentity();
-        try {
-            return mContext.getSystemService(UserManager.class)
-                    .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM);
-        } finally {
-            Binder.restoreCallingIdentity(callingIdentity);
-        }
-    }
-
-    /**
-     * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
-     * offered to the user if Bluetooth or sharing is disallowed. Puts the component to its default
-     * state if Bluetooth is not disallowed.
-     *
-     * @param userId user to disable bluetooth sharing for.
-     * @param bluetoothSharingDisallowed whether bluetooth sharing is disallowed.
-     */
-    private void updateOppLauncherComponentState(int userId, boolean bluetoothSharingDisallowed) {
-        final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
-                "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
-        final int newState =
-                bluetoothSharingDisallowed ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                        : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-        try {
-            final IPackageManager imp = AppGlobals.getPackageManager();
-            imp.setComponentEnabledSetting(oppLauncherComponent, newState,
-                    PackageManager.DONT_KILL_APP, userId);
-        } catch (Exception e) {
-            // The component was not found, do nothing.
-        }
-    }
-
-    private int getServiceRestartMs() {
-        return (mErrorRecoveryRetryCounter + 1) * SERVICE_RESTART_TIME_MS;
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) {
-            return;
-        }
-        if ((args.length > 0) && args[0].startsWith("--proto")) {
-            dumpProto(fd);
-            return;
-        }
-        String errorMsg = null;
-
-        writer.println("Bluetooth Status");
-        writer.println("  enabled: " + isEnabled());
-        writer.println("  state: " + BluetoothAdapter.nameForState(mState));
-        writer.println("  address: " + mAddress);
-        writer.println("  name: " + mName);
-        if (mEnable) {
-            long onDuration = SystemClock.elapsedRealtime() - mLastEnabledTime;
-            String onDurationString = String.format(Locale.US, "%02d:%02d:%02d.%03d",
-                    (int) (onDuration / (1000 * 60 * 60)),
-                    (int) ((onDuration / (1000 * 60)) % 60), (int) ((onDuration / 1000) % 60),
-                    (int) (onDuration % 1000));
-            writer.println("  time since enabled: " + onDurationString);
-        }
-
-        if (mActiveLogs.size() == 0) {
-            writer.println("\nBluetooth never enabled!");
-        } else {
-            writer.println("\nEnable log:");
-            for (ActiveLog log : mActiveLogs) {
-                writer.println("  " + log);
-            }
-        }
-
-        writer.println(
-                "\nBluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
-        if (mCrashes == CRASH_LOG_MAX_SIZE) {
-            writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
-        }
-        for (Long time : mCrashTimestamps) {
-            writer.println("  " + timeToLog(time));
-        }
-
-        writer.println("\n" + mBleApps.size() + " BLE app" + (mBleApps.size() == 1 ? "" : "s")
-                + " registered");
-        for (ClientDeathRecipient app : mBleApps.values()) {
-            writer.println("  " + app.getPackageName());
-        }
-
-        writer.println("\nBluetoothManagerService:");
-        writer.println("  mEnable:" + mEnable);
-        writer.println("  mQuietEnable:" + mQuietEnable);
-        writer.println("  mEnableExternal:" + mEnableExternal);
-        writer.println("  mQuietEnableExternal:" + mQuietEnableExternal);
-
-        writer.println("");
-        writer.flush();
-        if (args.length == 0) {
-            // Add arg to produce output
-            args = new String[1];
-            args[0] = "--print";
-        }
-
-        if (mBluetoothBinder == null) {
-            errorMsg = "Bluetooth Service not connected";
-        } else {
-            try {
-                mBluetoothBinder.dump(fd, args);
-            } catch (RemoteException re) {
-                errorMsg = "RemoteException while dumping Bluetooth Service";
-            }
-        }
-        if (errorMsg != null) {
-            writer.println(errorMsg);
-        }
-    }
-
-    private void dumpProto(FileDescriptor fd) {
-        final ProtoOutputStream proto = new ProtoOutputStream(fd);
-        proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled());
-        proto.write(BluetoothManagerServiceDumpProto.STATE, mState);
-        proto.write(BluetoothManagerServiceDumpProto.STATE_NAME,
-                BluetoothAdapter.nameForState(mState));
-        proto.write(BluetoothManagerServiceDumpProto.ADDRESS, mAddress);
-        proto.write(BluetoothManagerServiceDumpProto.NAME, mName);
-        if (mEnable) {
-            proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime);
-        }
-        proto.write(BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS,
-                SystemClock.elapsedRealtime());
-        for (ActiveLog log : mActiveLogs) {
-            long token = proto.start(BluetoothManagerServiceDumpProto.ACTIVE_LOGS);
-            log.dump(proto);
-            proto.end(token);
-        }
-        proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes);
-        proto.write(BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED,
-                mCrashes == CRASH_LOG_MAX_SIZE);
-        for (Long time : mCrashTimestamps) {
-            proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time);
-        }
-        proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size());
-        for (ClientDeathRecipient app : mBleApps.values()) {
-            proto.write(BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES,
-                    app.getPackageName());
-        }
-        proto.flush();
-    }
-
-    private static String getEnableDisableReasonString(int reason) {
-        switch (reason) {
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
-                return "APPLICATION_REQUEST";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
-                return "AIRPLANE_MODE";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
-                return "DISALLOWED";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
-                return "RESTARTED";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
-                return "START_ERROR";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
-                return "SYSTEM_BOOT";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
-                return "CRASH";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
-                return "USER_SWITCH";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
-                return "RESTORE_USER_SETTING";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET:
-                return "FACTORY_RESET";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED:
-                return "INIT_FLAGS_CHANGED";
-            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
-            default: return "UNKNOWN[" + reason + "]";
-        }
-    }
-
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    private static boolean checkPermissionForDataDelivery(Context context, String permission,
-            AttributionSource attributionSource, String message) {
-        final int result = PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
-                context, permission, PID_UNKNOWN,
-                new AttributionSource(context.getAttributionSource(), attributionSource), message);
-        if (result == PERMISSION_GRANTED) {
-            return true;
-        }
-
-        final String msg = "Need " + permission + " permission for " + attributionSource + ": "
-                + message;
-        if (result == PERMISSION_HARD_DENIED) {
-            throw new SecurityException(msg);
-        } else {
-            Log.w(TAG, msg);
-            return false;
-        }
-    }
-
-    /**
-     * Returns true if the BLUETOOTH_CONNECT permission is granted for the calling app. Returns
-     * false if the result is a soft denial. Throws SecurityException if the result is a hard
-     * denial.
-     *
-     * <p>Should be used in situations where the app op should not be noted.
-     */
-    @SuppressLint("AndroidFrameworkRequiresPermission")
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    public static boolean checkConnectPermissionForDataDelivery(
-            Context context, AttributionSource attributionSource, String message) {
-        return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT,
-                attributionSource, message);
-    }
-
-    static @NonNull Bundle getTempAllowlistBroadcastOptions() {
-        final long duration = 10_000;
-        final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
-        bOptions.setTemporaryAppAllowlist(duration,
-                TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
-                PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, "");
-        return bOptions.toBundle();
-    }
-}
diff --git a/services/core/java/com/android/server/BluetoothModeChangeHelper.java b/services/core/java/com/android/server/BluetoothModeChangeHelper.java
deleted file mode 100644
index e5854c9..0000000
--- a/services/core/java/com/android/server/BluetoothModeChangeHelper.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.annotation.RequiresPermission;
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHearingAid;
-import android.bluetooth.BluetoothLeAudio;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfile.ServiceListener;
-import android.content.Context;
-import android.content.res.Resources;
-import android.provider.Settings;
-import android.widget.Toast;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Helper class that handles callout and callback methods without
- * complex logic.
- */
-public class BluetoothModeChangeHelper {
-    private volatile BluetoothA2dp mA2dp;
-    private volatile BluetoothHearingAid mHearingAid;
-    private volatile BluetoothLeAudio mLeAudio;
-    private final BluetoothAdapter mAdapter;
-    private final Context mContext;
-
-    BluetoothModeChangeHelper(Context context) {
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
-        mContext = context;
-
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener,
-                BluetoothProfile.HEARING_AID);
-        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.LE_AUDIO);
-    }
-
-    private final ServiceListener mProfileServiceListener = new ServiceListener() {
-        @Override
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            // Setup Bluetooth profile proxies
-            switch (profile) {
-                case BluetoothProfile.A2DP:
-                    mA2dp = (BluetoothA2dp) proxy;
-                    break;
-                case BluetoothProfile.HEARING_AID:
-                    mHearingAid = (BluetoothHearingAid) proxy;
-                    break;
-                case BluetoothProfile.LE_AUDIO:
-                    mLeAudio = (BluetoothLeAudio) proxy;
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(int profile) {
-            // Clear Bluetooth profile proxies
-            switch (profile) {
-                case BluetoothProfile.A2DP:
-                    mA2dp = null;
-                    break;
-                case BluetoothProfile.HEARING_AID:
-                    mHearingAid = null;
-                    break;
-                case BluetoothProfile.LE_AUDIO:
-                    mLeAudio = null;
-                    break;
-                default:
-                    break;
-            }
-        }
-    };
-
-    @VisibleForTesting
-    public boolean isMediaProfileConnected() {
-        return isA2dpConnected() || isHearingAidConnected() || isLeAudioConnected();
-    }
-
-    @VisibleForTesting
-    public boolean isBluetoothOn() {
-        final BluetoothAdapter adapter = mAdapter;
-        if (adapter == null) {
-            return false;
-        }
-        return adapter.getLeState() == BluetoothAdapter.STATE_ON;
-    }
-
-    @VisibleForTesting
-    public boolean isAirplaneModeOn() {
-        return Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
-    }
-
-    @VisibleForTesting
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    public void onAirplaneModeChanged(BluetoothManagerService managerService) {
-        managerService.onAirplaneModeChanged();
-    }
-
-    @VisibleForTesting
-    public int getSettingsInt(String name) {
-        return Settings.Global.getInt(mContext.getContentResolver(),
-                name, 0);
-    }
-
-    @VisibleForTesting
-    public void setSettingsInt(String name, int value) {
-        Settings.Global.putInt(mContext.getContentResolver(),
-                name, value);
-    }
-
-    @VisibleForTesting
-    public void showToastMessage() {
-        Resources r = mContext.getResources();
-        final CharSequence text = r.getString(
-                R.string.bluetooth_airplane_mode_toast, 0);
-        Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
-    }
-
-    private boolean isA2dpConnected() {
-        final BluetoothA2dp a2dp = mA2dp;
-        if (a2dp == null) {
-            return false;
-        }
-        return a2dp.getConnectedDevices().size() > 0;
-    }
-
-    private boolean isHearingAidConnected() {
-        final BluetoothHearingAid hearingAid = mHearingAid;
-        if (hearingAid == null) {
-            return false;
-        }
-        return hearingAid.getConnectedDevices().size() > 0;
-    }
-
-    private boolean isLeAudioConnected() {
-        final BluetoothLeAudio leAudio = mLeAudio;
-        if (leAudio == null) {
-            return false;
-        }
-        return leAudio.getConnectedDevices().size() > 0;
-    }
-}
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
deleted file mode 100644
index 1a1eecd..0000000
--- a/services/core/java/com/android/server/BluetoothService.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.os.UserManager;
-
-import com.android.server.SystemService.TargetUser;
-
-class BluetoothService extends SystemService {
-    private BluetoothManagerService mBluetoothManagerService;
-    private boolean mInitialized = false;
-
-    public BluetoothService(Context context) {
-        super(context);
-        mBluetoothManagerService = new BluetoothManagerService(context);
-    }
-
-    private void initialize() {
-        if (!mInitialized) {
-            mBluetoothManagerService.handleOnBootPhase();
-            mInitialized = true;
-        }
-    }
-
-    @Override
-    public void onStart() {
-    }
-
-    @Override
-    public void onBootPhase(int phase) {
-        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
-            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
-                    mBluetoothManagerService);
-        } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
-                !UserManager.isHeadlessSystemUserMode()) {
-            initialize();
-        }
-    }
-
-    @Override
-    public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
-        if (!mInitialized) {
-            initialize();
-        } else {
-            mBluetoothManagerService.handleOnSwitchUser(to.getUserIdentifier());
-        }
-    }
-
-    @Override
-    public void onUserUnlocking(@NonNull TargetUser user) {
-        mBluetoothManagerService.handleOnUnlockUser(user.getUserIdentifier());
-    }
-}
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index 48f5b51..26d76a84 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -51,15 +51,12 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.regex.Matcher;
@@ -128,11 +125,9 @@
     // Location of ftrace pipe for notifications from kernel memory tools like KFENCE and KASAN.
     private static final String ERROR_REPORT_TRACE_PIPE =
             "/sys/kernel/tracing/instances/bootreceiver/trace_pipe";
-    // Stop after sending this many reports. See http://b/182159975.
+    // Stop after sending too many reports. See http://b/182159975.
     private static final int MAX_ERROR_REPORTS = 8;
     private static int sSentReports = 0;
-    // Avoid reporing the same bug from processDmesg() twice.
-    private static String sLastReportedBug = null;
 
     @Override
     public void onReceive(final Context context, Intent intent) {
@@ -175,7 +170,8 @@
          * We read from /sys/kernel/tracing/instances/bootreceiver/trace_pipe (set up by the
          * system), which will print an ftrace event when a memory corruption is detected in the
          * kernel.
-         * When an error is detected, we run the dmesg shell command and process its output.
+         * When an error is detected, we set the dmesg.start system property to notify dmesgd
+         * about a new error.
          */
         OnFileDescriptorEventListener traceCallback = new OnFileDescriptorEventListener() {
             final int mBufferSize = 1024;
@@ -191,8 +187,7 @@
                  * line, but to be on the safe side we keep reading until the buffer
                  * contains a '\n' character. In the unlikely case of a very buggy kernel
                  * the buffer may contain multiple tracing events that cannot be attributed
-                 * to particular error reports. In that case the latest error report
-                 * residing in dmesg is picked.
+                 * to particular error reports. dmesgd will take care of all errors.
                  */
                 try {
                     int nbytes = Os.read(fd, mTraceBuffer, 0, mBufferSize);
@@ -201,10 +196,13 @@
                         if (readStr.indexOf("\n") == -1) {
                             return OnFileDescriptorEventListener.EVENT_INPUT;
                         }
-                        processDmesg(context);
+                        if (sSentReports < MAX_ERROR_REPORTS) {
+                            SystemProperties.set("dmesgd.start", "1");
+                            sSentReports++;
+                        }
                     }
                 } catch (Exception e) {
-                    Slog.wtf(TAG, "Error processing dmesg output", e);
+                    Slog.wtf(TAG, "Error watching for trace events", e);
                     return 0;  // Unregister the handler.
                 }
                 return OnFileDescriptorEventListener.EVENT_INPUT;
@@ -216,157 +214,6 @@
 
     }
 
-    /**
-     * Check whether it is safe to collect this dmesg line or not.
-     *
-     * We only consider lines belonging to KASAN or KFENCE reports, but those may still contain
-     * user information, namely the process name:
-     *
-     *   [   69.547684] [ T6006]c7   6006  CPU: 7 PID: 6006 Comm: sh Tainted: G S       C O      ...
-     *
-     * hardware information:
-     *
-     *   [   69.558923] [ T6006]c7   6006  Hardware name: <REDACTED>
-     *
-     * or register dump (in KASAN reports only):
-     *
-     *   ... RIP: 0033:0x7f96443109da
-     *   ... RSP: 002b:00007ffcf0b51b08 EFLAGS: 00000202 ORIG_RAX: 00000000000000af
-     *   ... RAX: ffffffffffffffda RBX: 000055dc3ee521a0 RCX: 00007f96443109da
-     *
-     * (on x86_64)
-     *
-     *   ... pc : lpm_cpuidle_enter+0x258/0x384
-     *   ... lr : lpm_cpuidle_enter+0x1d4/0x384
-     *   ... sp : ffffff800820bea0
-     *   ... x29: ffffff800820bea0 x28: ffffffc2305f3ce0
-     *   ... ...
-     *   ... x9 : 0000000000000001 x8 : 0000000000000000
-     * (on ARM64)
-     *
-     * We therefore omit the lines that contain "Comm:", "Hardware name:", or match the general
-     * purpose register regexp.
-     *
-     * @param  line single line of `dmesg` output.
-     * @return      updated line with sensitive data removed, or null if the line must be skipped.
-     */
-    public static String stripSensitiveData(String line) {
-        /*
-         * General purpose register names begin with "R" on x86_64 and "x" on ARM64. The letter is
-         * followed by two symbols (numbers, letters or spaces) and a colon, which is followed by a
-         * 16-digit hex number. The optional "_" prefix accounts for ORIG_RAX on x86.
-         */
-        final String registerRegex = "[ _][Rx]..: [0-9a-f]{16}";
-        final Pattern registerPattern = Pattern.compile(registerRegex);
-
-        final String corruptionRegex = "Detected corrupted memory at 0x[0-9a-f]+";
-        final Pattern corruptionPattern = Pattern.compile(corruptionRegex);
-
-        if (line.contains("Comm: ") || line.contains("Hardware name: ")) return null;
-        if (registerPattern.matcher(line).find()) return null;
-
-        Matcher cm = corruptionPattern.matcher(line);
-        if (cm.find()) return cm.group(0);
-        return line;
-    }
-
-    /*
-     * Search dmesg output for the last error report from KFENCE or KASAN and copy it to Dropbox.
-     *
-     * Example report printed by the kernel (redacted to fit into 100 column limit):
-     *   [   69.236673] [ T6006]c7   6006  =========================================================
-     *   [   69.245688] [ T6006]c7   6006  BUG: KFENCE: out-of-bounds in kfence_handle_page_fault
-     *   [   69.245688] [ T6006]c7   6006
-     *   [   69.257816] [ T6006]c7   6006  Out-of-bounds access at 0xffffffca75c45000 (...)
-     *   [   69.267102] [ T6006]c7   6006   kfence_handle_page_fault+0x1bc/0x208
-     *   [   69.273536] [ T6006]c7   6006   __do_kernel_fault+0xa8/0x11c
-     *   ...
-     *   [   69.355427] [ T6006]c7   6006  kfence-#2 [0xffffffca75c46f30-0xffffffca75c46fff, ...
-     *   [   69.366938] [ T6006]c7   6006   __d_alloc+0x3c/0x1b4
-     *   [   69.371946] [ T6006]c7   6006   d_alloc_parallel+0x48/0x538
-     *   [   69.377578] [ T6006]c7   6006   __lookup_slow+0x60/0x15c
-     *   ...
-     *   [   69.547684] [ T6006]c7   6006  CPU: 7 PID: 6006 Comm: sh Tainted: G S       C O      ...
-     *   [   69.558923] [ T6006]c7   6006  Hardware name: <REDACTED>
-     *   [   69.567059] [ T6006]c7   6006  =========================================================
-     *
-     *   We rely on the kernel printing task/CPU ID for every log line (CONFIG_PRINTK_CALLER=y).
-     *   E.g. for the above report the task ID is T6006. Report lines may interleave with lines
-     *   printed by other kernel tasks, which will have different task IDs, so in order to collect
-     *   the report we:
-     *    - find the next occurrence of the "BUG: " line in the kernel log, parse it to obtain the
-     *      task ID and the tool name;
-     *    - scan the rest of dmesg output and pick every line that has the same task ID, until we
-     *      encounter a horizontal ruler, i.e.:
-     *      [   69.567059] [ T6006]c7   6006  ======================================================
-     *    - add that line to the error report, unless it contains sensitive information (see
-     *      logLinePotentiallySensitive())
-     *    - repeat the above steps till the last report is found.
-     */
-    private void processDmesg(Context ctx) throws IOException {
-        if (sSentReports == MAX_ERROR_REPORTS) return;
-        /*
-         * Only SYSTEM_KASAN_ERROR_REPORT and SYSTEM_KFENCE_ERROR_REPORT are supported at the
-         * moment.
-         */
-        final String[] bugTypes = new String[] { "KASAN", "KFENCE" };
-        final String tsRegex = "^\\[[^]]+\\] ";
-        final String bugRegex =
-                tsRegex + "\\[([^]]+)\\].*BUG: (" + String.join("|", bugTypes) + "):";
-        final Pattern bugPattern = Pattern.compile(bugRegex);
-
-        Process p = new ProcessBuilder("/system/bin/timeout", "-k", "90s", "60s",
-                                       "dmesg").redirectErrorStream(true).start();
-        BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
-        String line = null;
-        String task = null;
-        String tool = null;
-        String bugTitle = null;
-        Pattern reportPattern = null;
-        ArrayList<String> currentReport = null;
-        String lastReport = null;
-
-        while ((line = reader.readLine()) != null) {
-            if (currentReport == null) {
-                Matcher bm = bugPattern.matcher(line);
-                if (!bm.find()) continue;
-                task = bm.group(1);
-                tool = bm.group(2);
-                bugTitle = line;
-                currentReport = new ArrayList<String>();
-                currentReport.add(line);
-                String reportRegex = tsRegex + "\\[" + task + "\\].*";
-                reportPattern = Pattern.compile(reportRegex);
-                continue;
-            }
-            Matcher rm = reportPattern.matcher(line);
-            if (!rm.matches()) continue;
-            if ((line = stripSensitiveData(line)) == null) continue;
-            if (line.contains("================================")) {
-                lastReport = String.join("\n", currentReport);
-                currentReport = null;
-                continue;
-            }
-            currentReport.add(line);
-        }
-        if (lastReport == null) {
-            Slog.w(TAG, "Could not find report in dmesg.");
-            return;
-        }
-
-        // Avoid sending the same bug report twice.
-        if (bugTitle.equals(sLastReportedBug)) return;
-
-        final String reportTag = "SYSTEM_" + tool + "_ERROR_REPORT";
-        final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
-        final String headers = getCurrentBootHeaders();
-        final String reportText = headers + lastReport;
-
-        addTextToDropBox(db, reportTag, reportText, "/dev/kmsg", LOG_SIZE);
-        sLastReportedBug = bugTitle;
-        sSentReports++;
-    }
-
     private void removeOldUpdatePackages(Context context) {
         Downloads.removeAllDownloadsByPackage(context, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS);
     }
@@ -484,7 +331,9 @@
         HashMap<String, Long> timestamps = readTimestamps();
         try {
             if (proto) {
-                db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0);
+                if (recordFileTimestamp(tombstone, timestamps)) {
+                    db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0);
+                }
             } else {
                 final String headers = getBootHeadersToLogAndUpdate();
                 addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE,
@@ -526,16 +375,10 @@
         if (db == null || !db.isTagEnabled(tag)) return;  // Logging disabled
 
         File file = new File(filename);
-        long fileTime = file.lastModified();
-        if (fileTime <= 0) return;  // File does not exist
-
-        if (timestamps.containsKey(filename) && timestamps.get(filename) == fileTime) {
-            return;  // Already logged this particular file
+        if (!recordFileTimestamp(file, timestamps)) {
+            return;
         }
 
-        timestamps.put(filename, fileTime);
-
-
         String fileContents = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
         String text = headers + fileContents + footers;
         // Create an additional report for system server native crashes, with a special tag.
@@ -548,6 +391,19 @@
         addTextToDropBox(db, tag, text, filename, maxSize);
     }
 
+    private static boolean recordFileTimestamp(File file, HashMap<String, Long> timestamps) {
+        final long fileTime = file.lastModified();
+        if (fileTime <= 0) return false;  // File does not exist
+
+        final String filename = file.getPath();
+        if (timestamps.containsKey(filename) && timestamps.get(filename) == fileTime) {
+            return false;  // Already logged this particular file
+        }
+
+        timestamps.put(filename, fileTime);
+        return true;
+    }
+
     private static void addTextToDropBox(DropBoxManager db, String tag, String text,
             String filename, int maxSize) {
         Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index e29e894..e924012 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -16,8 +16,9 @@
 
 package com.android.server;
 
+import android.annotation.EnforcePermission;
+import android.annotation.RequiresNoPermission;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.gsi.AvbPublicKey;
 import android.gsi.GsiProgress;
 import android.gsi.IGsiService;
@@ -53,20 +54,12 @@
     }
 
     private IGsiService getGsiService() {
-        checkPermission();
         if (mGsiService != null) {
             return mGsiService;
         }
         return IGsiService.Stub.asInterface(ServiceManager.waitForService("gsiservice"));
     }
 
-    private void checkPermission() {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires MANAGE_DYNAMIC_SYSTEM permission");
-        }
-    }
-
     class GsiServiceCallback extends IGsiServiceCallback.Stub {
         // 0 for success
         private int mResult = -1;
@@ -82,6 +75,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean startInstallation(String dsuSlot) throws RemoteException {
         IGsiService service = getGsiService();
         mGsiService = service;
@@ -124,6 +118,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean createPartition(String name, long size, boolean readOnly)
             throws RemoteException {
         IGsiService service = getGsiService();
@@ -135,6 +130,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean closePartition() throws RemoteException {
         IGsiService service = getGsiService();
         if (service.closePartition() != 0) {
@@ -145,6 +141,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean finishInstallation() throws RemoteException {
         IGsiService service = getGsiService();
         if (service.closeInstall() != 0) {
@@ -155,21 +152,25 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public GsiProgress getInstallationProgress() throws RemoteException {
         return getGsiService().getInstallProgress();
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean abort() throws RemoteException {
         return getGsiService().cancelGsiInstall();
     }
 
     @Override
+    @RequiresNoPermission
     public boolean isInUse() {
         return SystemProperties.getBoolean("ro.gsid.image_running", false);
     }
 
     @Override
+    @RequiresNoPermission
     public boolean isInstalled() {
         boolean installed = SystemProperties.getBoolean("gsid.image_installed", false);
         Slog.i(TAG, "isInstalled(): " + installed);
@@ -177,11 +178,13 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean isEnabled() throws RemoteException {
         return getGsiService().isGsiEnabled();
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean remove() throws RemoteException {
         try {
             GsiServiceCallback callback = new GsiServiceCallback();
@@ -197,6 +200,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
         IGsiService gsiService = getGsiService();
         if (enable) {
@@ -220,6 +224,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean setAshmem(ParcelFileDescriptor ashmem, long size) {
         try {
             return getGsiService().setGsiAshmem(ashmem, size);
@@ -229,6 +234,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean submitFromAshmem(long size) {
         try {
             return getGsiService().commitGsiChunkFromAshmem(size);
@@ -238,6 +244,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public boolean getAvbPublicKey(AvbPublicKey dst) {
         try {
             return getGsiService().getAvbPublicKey(dst) == 0;
@@ -247,6 +254,7 @@
     }
 
     @Override
+    @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
     public long suggestScratchSize() throws RemoteException {
         return getGsiService().suggestScratchSize();
     }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index a2c2dbd..b59cd4c 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -20,28 +20,29 @@
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
 import static android.Manifest.permission.SHUTDOWN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_ALLOWLIST;
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
 import static android.net.INetd.FIREWALL_CHAIN_NONE;
-import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
-import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_DENYLIST;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.INetd.FIREWALL_RULE_DENY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.STATS_PER_UID;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.TrafficStats.UID_TETHERING;
+
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.INetd;
 import android.net.INetdUnsolicitedEventListener;
 import android.net.INetworkManagementEventObserver;
@@ -55,7 +56,6 @@
 import android.net.NetworkStack;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
-import android.net.TetherStatsParcel;
 import android.net.UidRangeParcel;
 import android.net.util.NetdService;
 import android.os.BatteryStats;
@@ -133,12 +133,6 @@
 
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
-    /**
-     * Name representing {@link #setGlobalAlert(long)} limit when delivered to
-     * {@link INetworkManagementEventObserver#limitReached(String, String)}.
-     */
-    public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
-
     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
 
     static final boolean MODIFY_OPERATION_ADD = true;
@@ -214,6 +208,11 @@
      */
     @GuardedBy("mRulesLock")
     private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
+    /**
+     * Contains the per-UID firewall rules that are used when Low Power Standby is enabled.
+     */
+    @GuardedBy("mRulesLock")
+    private SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mRulesLock")
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -514,12 +513,14 @@
             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
             syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted ");
+            syncFirewallChainLocked(FIREWALL_CHAIN_LOW_POWER_STANDBY, "low power standby ");
 
             final int[] chains = {
                     FIREWALL_CHAIN_STANDBY,
                     FIREWALL_CHAIN_DOZABLE,
                     FIREWALL_CHAIN_POWERSAVE,
-                    FIREWALL_CHAIN_RESTRICTED
+                    FIREWALL_CHAIN_RESTRICTED,
+                    FIREWALL_CHAIN_LOW_POWER_STANDBY
             };
 
             for (int chain : chains) {
@@ -1162,19 +1163,12 @@
             }
 
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
+            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
             try {
                 if (allowlist) {
-                    if (enable) {
-                        mNetdService.bandwidthAddNiceApp(uid);
-                    } else {
-                        mNetdService.bandwidthRemoveNiceApp(uid);
-                    }
+                    cm.updateMeteredNetworkAllowList(uid, enable);
                 } else {
-                    if (enable) {
-                        mNetdService.bandwidthAddNaughtyApp(uid);
-                    } else {
-                        mNetdService.bandwidthRemoveNaughtyApp(uid);
-                    }
+                    cm.updateMeteredNetworkDenyList(uid, enable);
                 }
                 synchronized (mRulesLock) {
                     if (enable) {
@@ -1183,7 +1177,7 @@
                         quotaList.delete(uid);
                     }
                 }
-            } catch (RemoteException | ServiceSpecificException e) {
+            } catch (RuntimeException e) {
                 throw new IllegalStateException(e);
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
@@ -1296,40 +1290,9 @@
     private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
         @Override
         public NetworkStats getTetherStats(int how) {
-            // We only need to return per-UID stats. Per-device stats are already counted by
-            // interface counters.
-            if (how != STATS_PER_UID) {
-                return new NetworkStats(SystemClock.elapsedRealtime(), 0);
-            }
-
-            final TetherStatsParcel[] tetherStatsVec;
-            try {
-                tetherStatsVec = mNetdService.tetherGetStats();
-            } catch (RemoteException | ServiceSpecificException e) {
-                throw new IllegalStateException("problem parsing tethering stats: ", e);
-            }
-
-            final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
-                tetherStatsVec.length);
-            final NetworkStats.Entry entry = new NetworkStats.Entry();
-
-            for (TetherStatsParcel tetherStats : tetherStatsVec) {
-                try {
-                    entry.iface = tetherStats.iface;
-                    entry.uid = UID_TETHERING;
-                    entry.set = SET_DEFAULT;
-                    entry.tag = TAG_NONE;
-                    entry.rxBytes   = tetherStats.rxBytes;
-                    entry.rxPackets = tetherStats.rxPackets;
-                    entry.txBytes   = tetherStats.txBytes;
-                    entry.txPackets = tetherStats.txPackets;
-                    stats.combineValues(entry);
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    throw new IllegalStateException("invalid tethering stats " + e);
-                }
-            }
-
-            return stats;
+            // Remove the implementation of NetdTetheringStatsProvider#getTetherStats
+            // since all callers are migrated to use INetd#tetherGetStats directly.
+            throw new UnsupportedOperationException();
         }
 
         @Override
@@ -1340,20 +1303,9 @@
 
     @Override
     public NetworkStats getNetworkStatsTethering(int how) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
-        synchronized (mTetheringStatsProviders) {
-            for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
-                try {
-                    stats.combineAllValues(provider.getTetherStats(how));
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Problem reading tethering stats from " +
-                            mTetheringStatsProviders.get(provider) + ": " + e);
-                }
-            }
-        }
-        return stats;
+        // Remove the implementation of getNetworkStatsTethering since all callers are migrated
+        // to use INetd#tetherGetStats directly.
+        throw new UnsupportedOperationException();
     }
 
     @Override
@@ -1468,9 +1420,10 @@
                 throw new IllegalArgumentException("Bad child chain: " + chainName);
             }
 
+            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
             try {
-                mNetdService.firewallEnableChildChain(chain, enable);
-            } catch (RemoteException | ServiceSpecificException e) {
+                cm.setFirewallChainEnabled(chain, enable);
+            } catch (RuntimeException e) {
                 throw new IllegalStateException(e);
             }
 
@@ -1494,6 +1447,8 @@
                 return FIREWALL_CHAIN_NAME_POWERSAVE;
             case FIREWALL_CHAIN_RESTRICTED:
                 return FIREWALL_CHAIN_NAME_RESTRICTED;
+            case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+                return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
             default:
                 throw new IllegalArgumentException("Bad child chain: " + chain);
         }
@@ -1509,6 +1464,8 @@
                 return FIREWALL_ALLOWLIST;
             case FIREWALL_CHAIN_RESTRICTED:
                 return FIREWALL_ALLOWLIST;
+            case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+                return FIREWALL_ALLOWLIST;
             default:
                 return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST;
         }
@@ -1542,25 +1499,10 @@
                     updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
                 }
             }
+            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
             try {
-                switch (chain) {
-                    case FIREWALL_CHAIN_DOZABLE:
-                        mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
-                        break;
-                    case FIREWALL_CHAIN_STANDBY:
-                        mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
-                        break;
-                    case FIREWALL_CHAIN_POWERSAVE:
-                        mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
-                        break;
-                    case FIREWALL_CHAIN_RESTRICTED:
-                        mNetdService.firewallReplaceUidChain("fw_restricted", true, uids);
-                        break;
-                    case FIREWALL_CHAIN_NONE:
-                    default:
-                        Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
-                }
-            } catch (RemoteException e) {
+                cm.replaceFirewallChain(chain, uids);
+            } catch (RuntimeException e) {
                 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
             }
         }
@@ -1576,10 +1518,10 @@
 
     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
-            final int ruleType = getFirewallRuleType(chain, rule);
+            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
             try {
-                mNetdService.firewallSetUidRule(chain, uid, ruleType);
-            } catch (RemoteException | ServiceSpecificException e) {
+                cm.updateFirewallRule(chain, uid, isFirewallRuleAllow(chain, rule));
+            } catch (RuntimeException e) {
                 throw new IllegalStateException(e);
             }
         }
@@ -1642,6 +1584,8 @@
                 return mUidFirewallPowerSaveRules;
             case FIREWALL_CHAIN_RESTRICTED:
                 return mUidFirewallRestrictedRules;
+            case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+                return mUidFirewallLowPowerStandbyRules;
             case FIREWALL_CHAIN_NONE:
                 return mUidFirewallRules;
             default:
@@ -1649,12 +1593,12 @@
         }
     }
 
-    private int getFirewallRuleType(int chain, int rule) {
+    // There are only two type of firewall rule: FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY.
+    private boolean isFirewallRuleAllow(int chain, int rule) {
         if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
-            return getFirewallType(chain) == FIREWALL_ALLOWLIST
-                    ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
+            return getFirewallType(chain) == FIREWALL_DENYLIST;
         }
-        return rule;
+        return rule == INetd.FIREWALL_RULE_ALLOW;
     }
 
     private void enforceSystemUid() {
@@ -1697,6 +1641,11 @@
             pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED));
             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED,
                     mUidFirewallRestrictedRules);
+
+            pw.print("UID firewall low power standby chain enabled: ");
+            pw.println(getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY));
+            dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY,
+                    mUidFirewallLowPowerStandbyRules);
         }
 
         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
@@ -1820,6 +1769,11 @@
                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode");
                 return true;
             }
+            if (getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY)
+                    && mUidFirewallLowPowerStandbyRules.get(uid) != FIREWALL_RULE_ALLOW) {
+                if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of low power standby");
+                return true;
+            }
             if (mUidRejectOnMetered.get(uid)) {
                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
                         + " in the background");
diff --git a/services/core/java/com/android/server/SerialService.java b/services/core/java/com/android/server/SerialService.java
index 1abe458..e915fa1 100644
--- a/services/core/java/com/android/server/SerialService.java
+++ b/services/core/java/com/android/server/SerialService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.annotation.EnforcePermission;
 import android.content.Context;
 import android.hardware.ISerialManager;
 import android.os.ParcelFileDescriptor;
@@ -34,9 +35,8 @@
                 com.android.internal.R.array.config_serialPorts);
     }
 
+    @EnforcePermission(android.Manifest.permission.SERIAL_PORT)
     public String[] getSerialPorts() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
-
         ArrayList<String> ports = new ArrayList<String>();
         for (int i = 0; i < mSerialPorts.length; i++) {
             String path = mSerialPorts[i];
@@ -49,8 +49,8 @@
         return result;
     }
 
+    @EnforcePermission(android.Manifest.permission.SERIAL_PORT)
     public ParcelFileDescriptor openSerialPort(String path) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
         for (int i = 0; i < mSerialPorts.length; i++) {
             if (mSerialPorts[i].equals(path)) {
                 return native_open(path);
diff --git a/services/core/java/com/android/server/SmartStorageMaintIdler.java b/services/core/java/com/android/server/SmartStorageMaintIdler.java
new file mode 100644
index 0000000..2dff72f
--- /dev/null
+++ b/services/core/java/com/android/server/SmartStorageMaintIdler.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.Slog;
+
+import java.util.concurrent.TimeUnit;
+
+public class SmartStorageMaintIdler extends JobService {
+    private static final String TAG = "SmartStorageMaintIdler";
+
+    private static final ComponentName SMART_STORAGE_MAINT_SERVICE =
+            new ComponentName("android", SmartStorageMaintIdler.class.getName());
+
+    private static final int SMART_MAINT_JOB_ID = 2808;
+
+    private boolean mStarted;
+    private JobParameters mJobParams;
+    private final Runnable mFinishCallback = new Runnable() {
+        @Override
+        public void run() {
+            Slog.i(TAG, "Got smart storage maintenance service completion callback");
+            if (mStarted) {
+                jobFinished(mJobParams, false);
+                mStarted = false;
+            }
+            // ... and try again in a next period
+            scheduleSmartIdlePass(SmartStorageMaintIdler.this,
+                StorageManagerService.SMART_IDLE_MAINT_PERIOD);
+        }
+    };
+
+    @Override
+    public boolean onStartJob(JobParameters params) {
+        mJobParams = params;
+        StorageManagerService ms = StorageManagerService.sSelf;
+        if (ms != null) {
+            mStarted = true;
+            ms.runSmartIdleMaint(mFinishCallback);
+        }
+        return ms != null;
+    }
+
+    @Override
+    public boolean onStopJob(JobParameters params) {
+        mStarted = false;
+        return false;
+    }
+
+    /**
+     * Schedule the smart storage idle maintenance job
+     */
+    public static void scheduleSmartIdlePass(Context context, int nHours) {
+        StorageManagerService ms = StorageManagerService.sSelf;
+        if ((ms == null) || ms.isPassedLifetimeThresh()) {
+            return;
+        }
+
+        JobScheduler tm = context.getSystemService(JobScheduler.class);
+
+        long nextScheduleTime = TimeUnit.HOURS.toMillis(nHours);
+
+        JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID,
+            SMART_STORAGE_MAINT_SERVICE);
+
+        builder.setMinimumLatency(nextScheduleTime);
+        tm.schedule(builder.build());
+    }
+}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 2d6170b..9546496 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -79,6 +79,7 @@
 import android.content.res.ObbInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.DropBoxManager;
 import android.os.Environment;
@@ -158,6 +159,8 @@
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
 
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
 
@@ -339,7 +342,44 @@
 
     @Nullable public static String sMediaStoreAuthorityProcessName;
 
+    // Run period in hour for smart idle maintenance
+    static final int SMART_IDLE_MAINT_PERIOD = 1;
+
     private final AtomicFile mSettingsFile;
+    private final AtomicFile mHourlyWriteFile;
+
+    private static final int MAX_HOURLY_WRITE_RECORDS = 72;
+
+    /**
+     * Default config values for smart idle maintenance
+     * Actual values will be controlled by DeviceConfig
+     */
+    // Decide whether smart idle maintenance is enabled or not
+    private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false;
+    // Storage lifetime percentage threshold to decide to turn off the feature
+    private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70;
+    // Minimum required number of dirty + free segments to trigger GC
+    private static final int DEFAULT_MIN_SEGMENTS_THRESHOLD = 512;
+    // Determine how much portion of current dirty segments will be GCed
+    private static final float DEFAULT_DIRTY_RECLAIM_RATE = 0.5F;
+    // Multiplier to amplify the target segment number for GC
+    private static final float DEFAULT_SEGMENT_RECLAIM_WEIGHT = 1.0F;
+    // Low battery level threshold to decide to turn off the feature
+    private static final float DEFAULT_LOW_BATTERY_LEVEL = 20F;
+    // Decide whether charging is required to turn on the feature
+    private static final boolean DEFAULT_CHARGING_REQUIRED = true;
+
+    private volatile int mLifetimePercentThreshold;
+    private volatile int mMinSegmentsThreshold;
+    private volatile float mDirtyReclaimRate;
+    private volatile float mSegmentReclaimWeight;
+    private volatile float mLowBatteryLevel;
+    private volatile boolean mChargingRequired;
+    private volatile boolean mNeedGC;
+
+    private volatile boolean mPassedLifetimeThresh;
+    // Tracking storage hourly write amounts
+    private volatile int[] mStorageHourlyWrites;
 
     /**
      * <em>Never</em> hold the lock while performing downcalls into vold, since
@@ -901,6 +941,10 @@
     }
 
     private void handleSystemReady() {
+        if (prepareSmartIdleMaint()) {
+            SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, SMART_IDLE_MAINT_PERIOD);
+        }
+
         // Start scheduling nominally-daily fstrim operations
         MountServiceIdler.scheduleIdlePass(mContext);
 
@@ -1907,6 +1951,10 @@
 
         mSettingsFile = new AtomicFile(
                 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
+        mHourlyWriteFile = new AtomicFile(
+                new File(Environment.getDataSystemDirectory(), "storage-hourly-writes"));
+
+        mStorageHourlyWrites = new int[MAX_HOURLY_WRITE_RECORDS];
 
         synchronized (mLock) {
             readSettingsLocked();
@@ -2572,7 +2620,7 @@
             // fstrim time is still updated. If file based checkpoints are used, we run
             // idle maintenance (GC + fstrim) regardless of checkpoint status.
             if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
-                mVold.runIdleMaint(new IVoldTaskListener.Stub() {
+                mVold.runIdleMaint(mNeedGC, new IVoldTaskListener.Stub() {
                     @Override
                     public void onStatus(int status, PersistableBundle extras) {
                         // Not currently used
@@ -2623,6 +2671,176 @@
         abortIdleMaint(null);
     }
 
+    private boolean prepareSmartIdleMaint() {
+        /**
+         * We can choose whether going with a new storage smart idle maintenance job
+         * or falling back to the traditional way using DeviceConfig
+         */
+        boolean smartIdleMaintEnabled = DeviceConfig.getBoolean(
+            DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+            "smart_idle_maint_enabled",
+            DEFAULT_SMART_IDLE_MAINT_ENABLED);
+        if (smartIdleMaintEnabled) {
+            mLifetimePercentThreshold = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "lifetime_threshold", DEFAULT_LIFETIME_PERCENT_THRESHOLD);
+            mMinSegmentsThreshold = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "min_segments_threshold", DEFAULT_MIN_SEGMENTS_THRESHOLD);
+            mDirtyReclaimRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "dirty_reclaim_rate", DEFAULT_DIRTY_RECLAIM_RATE);
+            mSegmentReclaimWeight = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "segment_reclaim_weight", DEFAULT_SEGMENT_RECLAIM_WEIGHT);
+            mLowBatteryLevel = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "low_battery_level", DEFAULT_LOW_BATTERY_LEVEL);
+            mChargingRequired = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "charging_required", DEFAULT_CHARGING_REQUIRED);
+
+            // If we use the smart idle maintenance, we need to turn off GC in the traditional idle
+            // maintenance to avoid the conflict
+            mNeedGC = false;
+
+            loadStorageHourlyWrites();
+            try {
+                mVold.refreshLatestWrite();
+            } catch (Exception e) {
+                Slog.wtf(TAG, e);
+            }
+            refreshLifetimeConstraint();
+        }
+        return smartIdleMaintEnabled;
+    }
+
+    // Return whether storage lifetime exceeds the threshold
+    public boolean isPassedLifetimeThresh() {
+        return mPassedLifetimeThresh;
+    }
+
+    private void loadStorageHourlyWrites() {
+        FileInputStream fis = null;
+
+        try {
+            fis = mHourlyWriteFile.openRead();
+            ObjectInputStream ois = new ObjectInputStream(fis);
+            mStorageHourlyWrites = (int[])ois.readObject();
+        } catch (FileNotFoundException e) {
+            // Missing data is okay, probably first boot
+        } catch (Exception e) {
+            Slog.wtf(TAG, "Failed reading write records", e);
+        } finally {
+            IoUtils.closeQuietly(fis);
+        }
+    }
+
+    private int getAverageHourlyWrite() {
+        return Arrays.stream(mStorageHourlyWrites).sum() / MAX_HOURLY_WRITE_RECORDS;
+    }
+
+    private void updateStorageHourlyWrites(int latestWrite) {
+        FileOutputStream fos = null;
+
+        System.arraycopy(mStorageHourlyWrites,0, mStorageHourlyWrites, 1,
+                     MAX_HOURLY_WRITE_RECORDS - 1);
+        mStorageHourlyWrites[0] = latestWrite;
+        try {
+            fos = mHourlyWriteFile.startWrite();
+            ObjectOutputStream oos = new ObjectOutputStream(fos);
+            oos.writeObject(mStorageHourlyWrites);
+            mHourlyWriteFile.finishWrite(fos);
+        } catch (IOException e) {
+            if (fos != null) {
+                mHourlyWriteFile.failWrite(fos);
+            }
+        }
+    }
+
+    private boolean checkChargeStatus() {
+        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        Intent batteryStatus = mContext.registerReceiver(null, ifilter);
+
+        if (mChargingRequired) {
+            int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+            if (status != BatteryManager.BATTERY_STATUS_CHARGING &&
+                status != BatteryManager.BATTERY_STATUS_FULL) {
+                Slog.w(TAG, "Battery is not being charged");
+                return false;
+            }
+        }
+
+        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+        float chargePercent = level * 100f / (float)scale;
+
+        if (chargePercent < mLowBatteryLevel) {
+            Slog.w(TAG, "Battery level is " + chargePercent + ", which is lower than threshold: " +
+                        mLowBatteryLevel);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean refreshLifetimeConstraint() {
+        int storageLifeTime = 0;
+
+        try {
+            storageLifeTime = mVold.getStorageLifeTime();
+        } catch (Exception e) {
+            Slog.wtf(TAG, e);
+            return false;
+        }
+
+        if (storageLifeTime == -1) {
+            Slog.w(TAG, "Failed to get storage lifetime");
+            return false;
+        } else if (storageLifeTime > mLifetimePercentThreshold) {
+            Slog.w(TAG, "Ended smart idle maintenance, because of lifetime(" + storageLifeTime +
+                        ")" + ", lifetime threshold(" + mLifetimePercentThreshold + ")");
+            mPassedLifetimeThresh = true;
+            return false;
+        }
+        Slog.i(TAG, "Storage lifetime: " + storageLifeTime);
+        return true;
+    }
+
+    void runSmartIdleMaint(Runnable callback) {
+        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+
+        try {
+            // Block based checkpoint process runs fstrim. So, if checkpoint is in progress
+            // (first boot after OTA), We skip the smart idle maintenance
+            if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
+                if (!refreshLifetimeConstraint() || !checkChargeStatus()) {
+                    return;
+                }
+
+                int latestHourlyWrite = mVold.getWriteAmount();
+                if (latestHourlyWrite == -1) {
+                    Slog.w(TAG, "Failed to get storage hourly write");
+                    return;
+                }
+
+                updateStorageHourlyWrites(latestHourlyWrite);
+                int avgHourlyWrite = getAverageHourlyWrite();
+
+                Slog.i(TAG, "Set smart idle maintenance: " + "latest hourly write: " +
+                            latestHourlyWrite + ", average hourly write: " + avgHourlyWrite +
+                            ", min segment threshold: " + mMinSegmentsThreshold +
+                            ", dirty reclaim rate: " + mDirtyReclaimRate +
+                            ", segment reclaim weight:" + mSegmentReclaimWeight);
+                mVold.setGCUrgentPace(avgHourlyWrite, mMinSegmentsThreshold, mDirtyReclaimRate,
+                                      mSegmentReclaimWeight);
+            } else {
+                Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
+            }
+        } catch (Exception e) {
+            Slog.wtf(TAG, e);
+        } finally {
+            if (callback != null) {
+                callback.run();
+            }
+        }
+    }
+
     @Override
     public void setDebugFlags(int flags, int mask) {
         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
@@ -3402,8 +3620,12 @@
                     mInstaller.tryMountDataMirror(volumeUuid);
                 }
             }
-        } catch (Exception e) {
+        } catch (RemoteException | Installer.InstallerException e) {
             Slog.wtf(TAG, e);
+            // Make sure to re-throw this exception; we must not ignore failure
+            // to prepare the user storage as it could indicate that encryption
+            // wasn't successfully set up.
+            throw new RuntimeException(e);
         }
     }
 
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 6a7afd9..2d328d8 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -539,7 +539,13 @@
     @GuardedBy("mLock")
     private void notifyAllPolicyListenersLocked() {
         for (final PolicyListenerBinderDeath policyListener : mRegisteredPolicyListeners.values()) {
-            Binder.withCleanCallingIdentity(() -> policyListener.mListener.onPolicyChanged());
+            Binder.withCleanCallingIdentity(() -> {
+                try {
+                    policyListener.mListener.onPolicyChanged();
+                } catch (RemoteException e) {
+                    logDbg("VcnStatusCallback threw on VCN status change", e);
+                }
+            });
         }
     }
 
@@ -548,8 +554,13 @@
             @NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) {
         for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
             if (isCallbackPermissioned(cbInfo, subGroup)) {
-                Binder.withCleanCallingIdentity(
-                        () -> cbInfo.mCallback.onVcnStatusChanged(statusCode));
+                Binder.withCleanCallingIdentity(() -> {
+                    try {
+                        cbInfo.mCallback.onVcnStatusChanged(statusCode);
+                    } catch (RemoteException e) {
+                        logDbg("VcnStatusCallback threw on VCN status change", e);
+                    }
+                });
             }
         }
     }
@@ -1222,13 +1233,17 @@
                 // Notify all registered StatusCallbacks for this subGroup
                 for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
                     if (isCallbackPermissioned(cbInfo, mSubGroup)) {
-                        Binder.withCleanCallingIdentity(
-                                () ->
-                                        cbInfo.mCallback.onGatewayConnectionError(
-                                                gatewayConnectionName,
-                                                errorCode,
-                                                exceptionClass,
-                                                exceptionMessage));
+                        Binder.withCleanCallingIdentity(() -> {
+                            try {
+                                cbInfo.mCallback.onGatewayConnectionError(
+                                        gatewayConnectionName,
+                                        errorCode,
+                                        exceptionClass,
+                                        exceptionMessage);
+                            } catch (RemoteException e) {
+                                logDbg("VcnStatusCallback threw on VCN status change", e);
+                            }
+                        });
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index b48e21e..7b8cce5 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -340,17 +340,18 @@
      * <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
      * exclusively by the Settings app, and passed into the platform at startup time.
      *
+     * @return A unique key corresponding to this session.
      * @throws IllegalArgumentException if no profile was found for the given package name.
      * @hide
      */
     @Override
-    public void startVpnProfile(@NonNull String packageName) {
+    public String startVpnProfile(@NonNull String packageName) {
         final int callingUid = Binder.getCallingUid();
         verifyCallingUidAndPackage(packageName, callingUid);
         final int user = UserHandle.getUserId(callingUid);
         synchronized (mVpns) {
             throwIfLockdownEnabled();
-            mVpns.get(user).startVpnProfile(packageName);
+            return mVpns.get(user).startVpnProfile(packageName);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 7ba032f..c6bca19 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -16,6 +16,7 @@
 package com.android.server.am;
 
 import android.annotation.Nullable;
+import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
@@ -702,8 +703,10 @@
             if (wifiInfo.isValid()) {
                 final long wifiChargeUC = measuredEnergyDeltas != null ?
                         measuredEnergyDeltas.wifiChargeUC : MeasuredEnergySnapshot.UNAVAILABLE;
-                mStats.updateWifiState(
-                        extractDeltaLocked(wifiInfo), wifiChargeUC, elapsedRealtime, uptime);
+                final NetworkStatsManager networkStatsManager = mInjector.getSystemService(
+                        NetworkStatsManager.class);
+                mStats.updateWifiState(extractDeltaLocked(wifiInfo),
+                        wifiChargeUC, elapsedRealtime, uptime, networkStatsManager);
             } else {
                 Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
             }
@@ -712,8 +715,10 @@
         if (modemInfo != null) {
             final long mobileRadioChargeUC = measuredEnergyDeltas != null
                     ? measuredEnergyDeltas.mobileRadioChargeUC : MeasuredEnergySnapshot.UNAVAILABLE;
+            final NetworkStatsManager networkStatsManager = mInjector.getSystemService(
+                    NetworkStatsManager.class);
             mStats.noteModemControllerActivity(modemInfo, mobileRadioChargeUC, elapsedRealtime,
-                    uptime);
+                    uptime, networkStatsManager);
         }
 
         if (updateFlags == UPDATE_ALL) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 9a349ef..d75ddba 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -22,6 +22,7 @@
 
 import android.annotation.NonNull;
 import android.app.StatsManager;
+import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -2025,8 +2026,11 @@
         synchronized (mLock) {
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             final long uptime = SystemClock.uptimeMillis();
+            final NetworkStatsManager networkStatsManager = mContext.getSystemService(
+                    NetworkStatsManager.class);
             mHandler.post(() -> {
-                mStats.updateWifiState(info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime);
+                mStats.updateWifiState(info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime,
+                        networkStatsManager);
             });
         }
     }
@@ -2063,9 +2067,11 @@
         synchronized (mLock) {
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             final long uptime = SystemClock.uptimeMillis();
+            final NetworkStatsManager networkStatsManager = mContext.getSystemService(
+                    NetworkStatsManager.class);
             mHandler.post(() -> {
                 mStats.noteModemControllerActivity(info, POWER_DATA_UNAVAILABLE, elapsedRealtime,
-                        uptime);
+                        uptime, networkStatsManager);
             });
         }
     }
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 6230919..583fb89 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -191,7 +191,9 @@
                             } else if (KEY_COMPACT_THROTTLE_1.equals(name)
                                     || KEY_COMPACT_THROTTLE_2.equals(name)
                                     || KEY_COMPACT_THROTTLE_3.equals(name)
-                                    || KEY_COMPACT_THROTTLE_4.equals(name)) {
+                                    || KEY_COMPACT_THROTTLE_4.equals(name)
+                                    || KEY_COMPACT_THROTTLE_5.equals(name)
+                                    || KEY_COMPACT_THROTTLE_6.equals(name)) {
                                 updateCompactionThrottles();
                             } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
                                 updateCompactStatsdSampleRate();
diff --git a/services/core/java/com/android/server/am/DataConnectionStats.java b/services/core/java/com/android/server/am/DataConnectionStats.java
index 6e39a4c..651e98c 100644
--- a/services/core/java/com/android/server/am/DataConnectionStats.java
+++ b/services/core/java/com/android/server/am/DataConnectionStats.java
@@ -73,7 +73,8 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
-        mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
+        mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler,
+                Context.RECEIVER_NOT_EXPORTED);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 4fc6614..54987cf 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -29,7 +29,7 @@
 import android.media.AudioManager;
 import android.media.AudioRoutesInfo;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.media.IAudioRoutesObserver;
 import android.media.ICapturePresetDevicesRoleDispatcher;
 import android.media.ICommunicationDeviceDispatcher;
@@ -517,12 +517,12 @@
     /*package*/ static final class BtDeviceChangedData {
         final @Nullable BluetoothDevice mNewDevice;
         final @Nullable BluetoothDevice mPreviousDevice;
-        final @NonNull BtProfileConnectionInfo mInfo;
+        final @NonNull BluetoothProfileConnectionInfo mInfo;
         final @NonNull String mEventSource;
 
         BtDeviceChangedData(@Nullable BluetoothDevice newDevice,
                 @Nullable BluetoothDevice previousDevice,
-                @NonNull BtProfileConnectionInfo info, @NonNull String eventSource) {
+                @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) {
             mNewDevice = newDevice;
             mPreviousDevice = previousDevice;
             mInfo = info;
@@ -554,9 +554,9 @@
             mDevice = device;
             mState = state;
             mProfile = d.mInfo.getProfile();
-            mSupprNoisy = d.mInfo.getSuppressNoisyIntent();
+            mSupprNoisy = d.mInfo.isSuppressNoisyIntent();
             mVolume = d.mInfo.getVolume();
-            mIsLeOutput = d.mInfo.getIsLeOutput();
+            mIsLeOutput = d.mInfo.isLeOutput();
             mEventSource = d.mEventSource;
             mAudioSystemDevice = audioDevice;
             mMusicDevice = AudioSystem.DEVICE_NONE;
@@ -627,7 +627,7 @@
                 audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID;
                 break;
             case BluetoothProfile.LE_AUDIO:
-                if (d.mInfo.getIsLeOutput()) {
+                if (d.mInfo.isLeOutput()) {
                     audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET;
                 } else {
                     audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET;
@@ -1205,6 +1205,7 @@
                         mDeviceInventory.onSetBtActiveDevice((BtDeviceInfo) msg.obj,
                                 mAudioService.getBluetoothContextualVolumeStream());
                     }
+                    break;
                 case MSG_BT_HEADSET_CNCT_FAILED:
                     synchronized (mSetModeLock) {
                         synchronized (mDeviceStateLock) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 0a114b9..fba8c05 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1088,6 +1088,12 @@
     private void makeLeAudioDeviceAvailable(String address, String name, int streamType, int device,
             String eventSource) {
         if (device != AudioSystem.DEVICE_NONE) {
+
+            /* Audio Policy sees Le Audio similar to A2DP. Let's make sure
+             * AUDIO_POLICY_FORCE_NO_BT_A2DP is not set
+             */
+            mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
+
             AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE,
                     address, name, AudioSystem.AUDIO_FORMAT_DEFAULT);
             mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e00c8a3..4c56381 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -83,7 +83,7 @@
 import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioModeDispatcher;
 import android.media.IAudioRoutesObserver;
@@ -2817,8 +2817,9 @@
         int step;
 
         // skip a2dp absolute volume control request when the device
-        // is not an a2dp device
-        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+        // is neither an a2dp device nor BLE device
+        if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))
                 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
@@ -2958,7 +2959,8 @@
             }
 
             if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
-                    && streamType == getBluetoothContextualVolumeStream()) {
+                    && streamType == getBluetoothContextualVolumeStream()
+                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
                     Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
                             + newIndex + " stream=" + streamType);
@@ -3559,8 +3561,9 @@
         int oldIndex;
 
         // skip a2dp absolute volume control request when the device
-        // is not an a2dp device
-        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+        // is neither an a2dp device nor BLE device
+        if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))
                 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
@@ -3602,7 +3605,8 @@
             }
 
             if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
-                    && streamType == getBluetoothContextualVolumeStream()) {
+                    && streamType == getBluetoothContextualVolumeStream()
+                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
                     Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
                             + index + " stream=" + streamType);
@@ -6301,14 +6305,14 @@
      * See AudioManager.handleBluetoothActiveDeviceChanged(...)
      */
     public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice,
-            BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
+            BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Bluetooth is the only caller allowed");
         }
         if (info == null) {
-            throw new IllegalArgumentException("Illegal null BtProfileConnectionInfo for device "
-                    + previousDevice + " -> " + newDevice);
+            throw new IllegalArgumentException("Illegal null BluetoothProfileConnectionInfo for"
+                    + " device " + previousDevice + " -> " + newDevice);
         }
         final int profile = info.getProfile();
         if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 9273a5d..f813ae0 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -31,7 +31,7 @@
 import android.media.AudioDeviceAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.os.Binder;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -490,16 +490,16 @@
             return;
         }
         final BluetoothDevice btDevice = deviceList.get(0);
-        final @BluetoothProfile.BtProfileState int state =
-                proxy.getConnectionState(btDevice);
-        if (state == BluetoothProfile.STATE_CONNECTED) {
+        if (proxy.getConnectionState(btDevice) == BluetoothProfile.STATE_CONNECTED) {
             mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                     new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
-                        new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
+                        new BluetoothProfileConnectionInfo(profile),
+                        "mBluetoothProfileServiceListener"));
         } else {
             mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                     new AudioDeviceBroker.BtDeviceChangedData(null, btDevice,
-                        new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
+                        new BluetoothProfileConnectionInfo(profile),
+                        "mBluetoothProfileServiceListener"));
         }
     }
 
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java
index 8c93891..6654c0c 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java
@@ -189,7 +189,8 @@
                 removed.add(id);
             }
         }
-        if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.isComplete()) {
+        if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.isComplete()
+                && !chunk.isPurge()) {
             return null;
         }
         mComplete = chunk.isComplete();
@@ -239,9 +240,10 @@
         }
 
         // Determine number of chunks we need to send.
-        int numChunks = 0;
+        int numChunks = purge ? 1 : 0;
         if (modified != null) {
-            numChunks = roundUpFraction(modified.size(), maxNumModifiedPerChunk);
+            numChunks = Math.max(numChunks,
+                    roundUpFraction(modified.size(), maxNumModifiedPerChunk));
         }
         if (removed != null) {
             numChunks = Math.max(numChunks, roundUpFraction(removed.size(), maxNumRemovedPerChunk));
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 093ecd5..a0c5aa3 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -535,9 +535,6 @@
         mEmulatorClipboardMonitor.accept(clip);
 
         final int userId = UserHandle.getUserId(uid);
-        if (clip != null) {
-            startClassificationLocked(clip, userId);
-        }
 
         // Update this user
         setPrimaryClipInternalLocked(getClipboardLocked(userId), clip, uid, sourcePackage);
@@ -574,7 +571,7 @@
                         final boolean canCopyIntoProfile = !hasRestriction(
                                 UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id);
                         if (canCopyIntoProfile) {
-                            setPrimaryClipInternalLocked(
+                            setPrimaryClipInternalNoClassifyLocked(
                                     getClipboardLocked(id), clip, uid, sourcePackage);
                         }
                     }
@@ -593,6 +590,17 @@
     @GuardedBy("mLock")
     private void setPrimaryClipInternalLocked(PerUserClipboard clipboard, @Nullable ClipData clip,
             int uid, @Nullable String sourcePackage) {
+        final int userId = UserHandle.getUserId(uid);
+        if (clip != null) {
+            startClassificationLocked(clip, userId);
+        }
+
+        setPrimaryClipInternalNoClassifyLocked(clipboard, clip, uid, sourcePackage);
+    }
+
+    @GuardedBy("mLock")
+    private void setPrimaryClipInternalNoClassifyLocked(PerUserClipboard clipboard,
+            @Nullable ClipData clip, int uid, @Nullable String sourcePackage) {
         revokeUris(clipboard);
         clipboard.activePermissionOwners.clear();
         if (clip == null && clipboard.primaryClip == null) {
@@ -631,7 +639,7 @@
                         clipboard.primaryClipListeners.getBroadcastItem(i)
                                 .dispatchPrimaryClipChanged();
                     }
-                } catch (RemoteException e) {
+                } catch (RemoteException | SecurityException e) {
                     // The RemoteCallbackList will take care of removing
                     // the dead object for us.
                 }
diff --git a/services/core/java/com/android/server/clipboard/OWNERS b/services/core/java/com/android/server/clipboard/OWNERS
index 5449df9..0d5dbf9 100644
--- a/services/core/java/com/android/server/clipboard/OWNERS
+++ b/services/core/java/com/android/server/clipboard/OWNERS
@@ -1 +1,3 @@
 per-file EmulatorClipboardMonitor.java = bohu@google.com,lfy@google.com,rkir@google.com
+
+olilan@google.com
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index cc9efbc..603f206 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -18,14 +18,12 @@
 
 import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER;
 import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
-import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
 import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
@@ -95,6 +93,7 @@
     private static String TAG = MultipathPolicyTracker.class.getSimpleName();
 
     private static final boolean DBG = false;
+    private static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
 
     // This context is for the current user.
     private final Context mContext;
@@ -199,6 +198,7 @@
         private final NetworkTemplate mNetworkTemplate;
         private final UsageCallback mUsageCallback;
         private NetworkCapabilities mNetworkCapabilities;
+        private final NetworkStatsManager mStatsManager;
 
         public MultipathTracker(Network network, NetworkCapabilities nc) {
             this.network = network;
@@ -238,6 +238,13 @@
                     updateMultipathBudget();
                 }
             };
+            mStatsManager = mContext.getSystemService(NetworkStatsManager.class);
+            // Query stats from NetworkStatsService will trigger a poll by default.
+            // But since MultipathPolicyTracker listens NPMS events that triggered by
+            // stats updated event, and will query stats
+            // after the event. A polling -> updated -> query -> polling loop will be introduced
+            // if polls on open. Hence, set flag to false to prevent a polling loop.
+            mStatsManager.setPollOnOpen(false);
 
             updateMultipathBudget();
         }
@@ -262,8 +269,7 @@
         private long getNetworkTotalBytes(long start, long end) {
             try {
                 final android.app.usage.NetworkStats.Bucket ret =
-                        mContext.getSystemService(NetworkStatsManager.class)
-                        .querySummaryForDevice(mNetworkTemplate, start, end);
+                        mStatsManager.querySummaryForDevice(mNetworkTemplate, start, end);
                 return ret.getRxBytes() + ret.getTxBytes();
             } catch (RuntimeException e) {
                 Log.w(TAG, "Failed to get data usage: " + e);
@@ -272,15 +278,11 @@
         }
 
         private NetworkIdentity getTemplateMatchingNetworkIdentity(NetworkCapabilities nc) {
-            return new NetworkIdentity(
-                    ConnectivityManager.TYPE_MOBILE,
-                    0 /* subType, unused for template matching */,
-                    subscriberId,
-                    null /* networkId, unused for matching mobile networks */,
-                    !nc.hasCapability(NET_CAPABILITY_NOT_ROAMING),
-                    !nc.hasCapability(NET_CAPABILITY_NOT_METERED),
-                    false /* defaultNetwork, templates should have DEFAULT_NETWORK_ALL */,
-                    OEM_MANAGED_ALL);
+            return new NetworkIdentity.Builder().setType(ConnectivityManager.TYPE_MOBILE)
+                    .setSubscriberId(subscriberId)
+                    .setRoaming(!nc.hasCapability(NET_CAPABILITY_NOT_ROAMING))
+                    .setMetered(!nc.hasCapability(NET_CAPABILITY_NOT_METERED))
+                    .build();
         }
 
         private long getRemainingDailyBudget(long limitBytes,
@@ -369,7 +371,7 @@
             // This will only be called if the total quota for the day changed, not if usage changed
             // since last time, so even if this is called very often the budget will not snap to 0
             // as soon as there are less than 2MB left for today.
-            if (budget > NetworkStatsManager.MIN_THRESHOLD_BYTES) {
+            if (budget > MIN_THRESHOLD_BYTES) {
                 if (DBG) {
                     Log.d(TAG, "Setting callback for " + budget + " bytes on network " + network);
                 }
@@ -402,8 +404,8 @@
 
         private void registerUsageCallback(long budget) {
             maybeUnregisterUsageCallback();
-            mStatsManager.registerUsageCallback(mNetworkTemplate, TYPE_MOBILE, budget,
-                    mUsageCallback, mHandler);
+            mStatsManager.registerUsageCallback(mNetworkTemplate, budget,
+                    (command) -> mHandler.post(command), mUsageCallback);
             mMultipathBudget = budget;
         }
 
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2c666b5..30ae7d6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -151,6 +151,7 @@
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -203,6 +204,7 @@
     private final NetworkInfo mNetworkInfo;
     private int mLegacyState;
     @VisibleForTesting protected String mPackage;
+    private String mSessionKey;
     private int mOwnerUID;
     private boolean mIsPackageTargetingAtLeastQ;
     @VisibleForTesting
@@ -1208,8 +1210,11 @@
             for (RouteInfo route : mConfig.routes) {
                 lp.addRoute(route);
                 InetAddress address = route.getDestination().getAddress();
-                allowIPv4 |= address instanceof Inet4Address;
-                allowIPv6 |= address instanceof Inet6Address;
+
+                if (route.getType() == RouteInfo.RTN_UNICAST) {
+                    allowIPv4 |= address instanceof Inet4Address;
+                    allowIPv6 |= address instanceof Inet6Address;
+                }
             }
         }
 
@@ -1299,6 +1304,7 @@
                 .setLegacyType(ConnectivityManager.TYPE_VPN)
                 .setLegacyTypeName("VPN")
                 .setBypassableVpn(mConfig.allowBypass && !mLockdown)
+                .setVpnRequiresValidation(mConfig.requiresInternetValidation)
                 .build();
 
         capsBuilder.setOwnerUid(mOwnerUID);
@@ -2000,7 +2006,8 @@
                             .setCategory(Notification.CATEGORY_SYSTEM)
                             .setVisibility(Notification.VISIBILITY_PUBLIC)
                             .setOngoing(true)
-                            .setColor(mContext.getColor(R.color.system_notification_accent_color));
+                            .setColor(mContext.getColor(
+                                    android.R.color.system_notification_accent_color));
             notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build());
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -2500,6 +2507,7 @@
             mProfile = profile;
             mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
             mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this);
+            mSessionKey = UUID.randomUUID().toString();
         }
 
         @Override
@@ -2821,6 +2829,7 @@
          */
         private void disconnectVpnRunner() {
             mActiveNetwork = null;
+            mSessionKey = null;
             mIsRunning = false;
 
             resetIkeState();
@@ -3311,7 +3320,7 @@
      *
      * @param packageName the package name of the app provisioning this profile
      */
-    public synchronized void startVpnProfile(@NonNull String packageName) {
+    public synchronized String startVpnProfile(@NonNull String packageName) {
         requireNonNull(packageName, "No package name provided");
 
         enforceNotRestrictedUser();
@@ -3329,6 +3338,7 @@
             }
 
             startVpnProfilePrivileged(profile, packageName);
+            return mSessionKey;
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3360,6 +3370,7 @@
             }
             mConfig.startTime = SystemClock.elapsedRealtime();
             mConfig.proxyInfo = profile.proxy;
+            mConfig.requiresInternetValidation = profile.requiresInternetValidation;
 
             switch (profile.type) {
                 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index c27293c..c12522b 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -75,6 +75,8 @@
     protected int mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
     protected int mLastKeyRepeatCount = 0;
 
+    HdmiCecStandbyModeHandler mStandbyHandler;
+
     // Stores recent changes to the active source in the CEC network.
     private final ArrayBlockingQueue<HdmiCecController.Dumpable> mActiveSourceHistory =
             new ArrayBlockingQueue<>(MAX_HDMI_ACTIVE_SOURCE_HISTORY);
@@ -263,6 +265,11 @@
         if (dest != mAddress && dest != Constants.ADDR_BROADCAST) {
             return Constants.NOT_HANDLED;
         }
+        if (mService.isPowerStandby()
+                && !mService.isWakeUpMessageReceived()
+                && mStandbyHandler.handleCommand(message)) {
+            return Constants.HANDLED;
+        }
         // Cache incoming message if it is included in the list of cacheable opcodes.
         mCecMessageCache.cacheMessage(message);
         return onMessage(message);
@@ -829,17 +836,12 @@
     protected int handleVendorCommandWithId(HdmiCecMessage message) {
         byte[] params = message.getParams();
         int vendorId = HdmiUtils.threeBytesToInt(params);
-        if (vendorId == mService.getVendorId()) {
-            if (!mService.invokeVendorCommandListenersOnReceived(
-                    mDeviceType, message.getSource(), message.getDestination(), params, true)) {
-                return Constants.ABORT_REFUSED;
-            }
-        } else if (message.getDestination() != Constants.ADDR_BROADCAST
-                && message.getSource() != Constants.ADDR_UNREGISTERED) {
-            Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>");
-            return Constants.ABORT_UNRECOGNIZED_OPCODE;
-        } else {
+        if (message.getDestination() == Constants.ADDR_BROADCAST
+                || message.getSource() == Constants.ADDR_UNREGISTERED) {
             Slog.v(TAG, "Wrong broadcast vendor command. Ignoring");
+        } else if (!mService.invokeVendorCommandListenersOnReceived(
+                mDeviceType, message.getSource(), message.getDestination(), params, true)) {
+            return Constants.ABORT_REFUSED;
         }
         return Constants.HANDLED;
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 0bb1285..c549b55 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -112,6 +112,7 @@
             mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, false);
         mSystemAudioControlFeatureEnabled =
             mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);
+        mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
     }
 
     private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml";
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 37ee76b..4071858 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -64,6 +64,7 @@
 
     HdmiCecLocalDevicePlayback(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
+        mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 6e7a2a0..3d218cf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -91,8 +91,6 @@
     @GuardedBy("mLock")
     private boolean mSystemAudioMute = false;
 
-    private final HdmiCecStandbyModeHandler mStandbyHandler;
-
     // If true, do not do routing control/send active source for internal source.
     // Set to true when the device was woken up by <Text/Image View On>.
     private boolean mSkipRoutingControl;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
index 6f7473d..1c296e5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.hdmi.HdmiDeviceInfo;
 import android.util.SparseArray;
 
 /**
@@ -56,7 +57,8 @@
     private final class AutoOnHandler implements CecMessageHandler {
         @Override
         public boolean handle(HdmiCecMessage message) {
-            if (!mTv.getAutoWakeup()) {
+            HdmiCecLocalDeviceTv tv = (HdmiCecLocalDeviceTv) mDevice;
+            if (!tv.getAutoWakeup()) {
                 mAborterRefused.handle(message);
                 return true;
             }
@@ -78,7 +80,7 @@
     }
 
     private final HdmiControlService mService;
-    private final HdmiCecLocalDeviceTv mTv;
+    private final HdmiCecLocalDevice mDevice;
 
     private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>();
     private final CecMessageHandler mDefaultHandler = new Aborter(
@@ -92,13 +94,7 @@
     private final UserControlProcessedHandler
             mUserControlProcessedHandler = new UserControlProcessedHandler();
 
-    public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) {
-        mService = service;
-        mTv = tv;
-
-        addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
-        addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
-
+    private void addCommonHandlers() {
         addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander);
         addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander);
         addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander);
@@ -112,6 +108,30 @@
         addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander);
         addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander);
 
+        addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
+        addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
+        addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
+        addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
+        addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
+        addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
+        addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBypasser);
+        addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser);
+        addHandler(Constants.MESSAGE_GIVE_FEATURES, mBypasser);
+
+        addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
+
+        addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
+        addHandler(Constants.MESSAGE_ABORT, mBypasser);
+        addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
+
+        addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
+        addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
+    }
+
+    private void addTvHandlers() {
+        addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
+        addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
+
         // If TV supports the following messages during power-on, ignore them and do nothing,
         // else reply with <Feature Abort>["Unrecognized Opcode"]
         // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status>
@@ -124,24 +144,16 @@
         addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode);
         addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode);
         addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode);
+    }
 
-        addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
-        addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
-        addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
-        addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
-        addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
-        addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
-        addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBypasser);
-        addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser);
+    public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDevice device) {
+        mService = service;
+        mDevice = device;
 
-        addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
-
-        addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
-        addHandler(Constants.MESSAGE_ABORT, mBypasser);
-        addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
-
-        addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
-        addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
+        addCommonHandlers();
+        if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) {
+            addTvHandlers();
+        }
     }
 
     private void addHandler(int opcode, CecMessageHandler handler) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a571dc0..8dadf5a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1582,11 +1582,11 @@
 
     class VendorCommandListenerRecord implements IBinder.DeathRecipient {
         private final IHdmiVendorCommandListener mListener;
-        private final int mDeviceType;
+        private final int mVendorId;
 
-        public VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int deviceType) {
+        VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int vendorId) {
             mListener = listener;
-            mDeviceType = deviceType;
+            mVendorId = vendorId;
         }
 
         @Override
@@ -2077,10 +2077,10 @@
         }
 
         @Override
-        public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
-                final int deviceType) {
+        public void addVendorCommandListener(
+                final IHdmiVendorCommandListener listener, final int vendorId) {
             initBinderCall();
-            HdmiControlService.this.addVendorCommandListener(listener, deviceType);
+            HdmiControlService.this.addVendorCommandListener(listener, vendorId);
         }
 
         @Override
@@ -3219,8 +3219,9 @@
         }
     }
 
-    private void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
-        VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, deviceType);
+    @VisibleForTesting
+    void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {
+        VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, vendorId);
         try {
             listener.asBinder().linkToDeath(record, 0);
         } catch (RemoteException e) {
@@ -3239,8 +3240,14 @@
                 return false;
             }
             for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) {
-                if (record.mDeviceType != deviceType) {
-                    continue;
+                if (hasVendorId) {
+                    int vendorId =
+                            ((params[0] & 0xFF) << 16)
+                                    + ((params[1] & 0xFF) << 8)
+                                    + (params[2] & 0xFF);
+                    if (record.mVendorId != vendorId) {
+                        continue;
+                    }
                 }
                 try {
                     record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3e52f5e..5b7f5c8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2837,7 +2837,7 @@
                 return;
             }
             final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
-            if (targetWindow != null && mLastImeTargetWindow != targetWindow) {
+            if (targetWindow != null) {
                 mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
             }
             mLastImeTargetWindow = targetWindow;
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index ffc1aed..91de9e5 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -344,10 +344,19 @@
     }
 
     private void addActiveRoute(BluetoothRouteInfo btRoute) {
+        if (btRoute == null) {
+            if (DEBUG) {
+                Log.d(TAG, " btRoute is null");
+            }
+            return;
+        }
         if (DEBUG) {
             Log.d(TAG, "Adding active route: " + btRoute.route);
         }
-        if (btRoute == null || mActiveRoutes.contains(btRoute)) {
+        if (mActiveRoutes.contains(btRoute)) {
+            if (DEBUG) {
+                Log.d(TAG, " btRoute is already added.");
+            }
             return;
         }
         setRouteConnectionState(btRoute, STATE_CONNECTED);
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
index 2e2d812..8097f4e 100644
--- a/services/core/java/com/android/server/media/OWNERS
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -1,8 +1,6 @@
+# Bug component: 137631
 elaurent@google.com
-hdmoon@google.com
-insun@google.com
-jaewan@google.com
-jinpark@google.com
-klhyun@google.com
 lajos@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/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 851ea3d..1b7d1ba 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -293,7 +293,7 @@
                         .addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset),
                                 mResetIntent)
                         .setColor(mContext.getColor(
-                                com.android.internal.R.color.system_notification_accent_color));
+                                android.R.color.system_notification_accent_color));
 
         mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS,
                 builder.build());
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 81106b1..33ac6cd 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -15,13 +15,17 @@
  */
 package com.android.server.net;
 
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
-import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
-import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
+import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.INetd.FIREWALL_RULE_DENY;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
@@ -29,6 +33,7 @@
 import static android.os.PowerExemptionManager.reasonCodeToString;
 import static android.os.Process.INVALID_UID;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.ProcessCapability;
 import android.net.NetworkPolicyManager;
@@ -81,13 +86,18 @@
 
     private final Object mLock = new Object();
 
-    void networkBlocked(int uid, UidBlockedState uidBlockedState) {
+    void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) {
         synchronized (mLock) {
             if (LOGD || uid == mDebugUid) {
                 Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString());
             }
-            mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
-                    uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+            if (uidBlockedState == null) {
+                mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE,
+                        BLOCKED_REASON_NONE);
+            } else {
+                mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
+                        uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+            }
         }
     }
 
@@ -320,6 +330,8 @@
                 return FIREWALL_CHAIN_NAME_POWERSAVE;
             case FIREWALL_CHAIN_RESTRICTED:
                 return FIREWALL_CHAIN_NAME_RESTRICTED;
+            case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+                return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
             default:
                 return String.valueOf(chain);
         }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 03a63b9..8ef42ff 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -16,11 +16,8 @@
 
 package com.android.server.net;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.Network;
-import android.net.NetworkTemplate;
-import android.net.netstats.provider.NetworkStatsProvider;
 import android.os.PowerExemptionManager.ReasonCode;
 import android.telephony.SubscriptionPlan;
 
@@ -56,11 +53,6 @@
      */
     public abstract SubscriptionPlan getSubscriptionPlan(Network network);
 
-    /**
-     * Return the active {@link SubscriptionPlan} for the given template.
-     */
-    public abstract SubscriptionPlan getSubscriptionPlan(NetworkTemplate template);
-
     public static final int QUOTA_TYPE_JOBS = 1;
     public static final int QUOTA_TYPE_MULTIPATH = 2;
 
@@ -99,13 +91,4 @@
      */
     public abstract void setMeteredRestrictedPackagesAsync(
             Set<String> packageNames, int userId);
-
-    /**
-     *  Notifies that the specified {@link NetworkStatsProvider} has reached its quota
-     *  which was set through {@link NetworkStatsProvider#onSetLimit(String, long)} or
-     *  {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}.
-     *
-     * @param tag the human readable identifier of the custom network stats provider.
-     */
-    public abstract void onStatsProviderWarningOrLimitReached(@NonNull String tag);
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2ca057d..6a00d06 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -24,7 +24,6 @@
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.Manifest.permission.NETWORK_STACK;
 import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
-import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.Manifest.permission.READ_PHONE_STATE;
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -63,7 +62,6 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkIdentity.OEM_NONE;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.SNOOZE_NEVER;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -100,9 +98,6 @@
 import static android.net.NetworkTemplate.MATCH_CARRIER;
 import static android.net.NetworkTemplate.MATCH_MOBILE;
 import static android.net.NetworkTemplate.MATCH_WIFI;
-import static android.net.NetworkTemplate.buildTemplateCarrierMetered;
-import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
 import static android.os.Trace.TRACE_TAG_NETWORK;
 import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
@@ -130,8 +125,7 @@
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.internal.util.XmlUtils.writeStringAttribute;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
-import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -151,6 +145,8 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -170,7 +166,6 @@
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkIdentity;
@@ -181,10 +176,8 @@
 import android.net.NetworkSpecifier;
 import android.net.NetworkStack;
 import android.net.NetworkStateSnapshot;
-import android.net.NetworkStats;
 import android.net.NetworkTemplate;
 import android.net.TelephonyNetworkSpecifier;
-import android.net.TrafficStats;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.BestClock;
@@ -443,7 +436,7 @@
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
-    private NetworkStatsManagerInternal mNetworkStats;
+    private NetworkStatsManager mNetworkStats;
     private final INetworkManagementService mNetworkManager;
     private UsageStatsManagerInternal mUsageStats;
     private AppStandbyInternal mAppStandby;
@@ -455,6 +448,8 @@
     private ConnectivityManager mConnManager;
     private PowerManagerInternal mPowerManagerInternal;
     private PowerWhitelistManager mPowerWhitelistManager;
+    @NonNull
+    private final Dependencies mDeps;
 
     /** Current cached value of the current Battery Saver mode's setting for restrict background. */
     @GuardedBy("mUidRulesFirstLock")
@@ -706,7 +701,7 @@
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkManagementService networkManagement) {
         this(context, activityManager, networkManagement, AppGlobals.getPackageManager(),
-                getDefaultClock(), getDefaultSystemDir(), false);
+                getDefaultClock(), getDefaultSystemDir(), false, new Dependencies(context));
     }
 
     private static @NonNull File getDefaultSystemDir() {
@@ -718,9 +713,59 @@
                 Clock.systemUTC());
     }
 
+    static class Dependencies {
+        final Context mContext;
+        final NetworkStatsManager mNetworkStatsManager;
+        Dependencies(Context context) {
+            mContext = context;
+            mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
+            // Query stats from NetworkStatsService will trigger a poll by default.
+            // But since NPMS listens stats updated event, and will query stats
+            // after the event. A polling -> updated -> query -> polling loop will be introduced
+            // if polls on open. Hence, while NPMS manages it's poll requests explicitly, set
+            // flag to false to prevent a polling loop.
+            mNetworkStatsManager.setPollOnOpen(false);
+        }
+
+        long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
+            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes");
+            try {
+                final NetworkStats.Bucket ret = mNetworkStatsManager
+                        .querySummaryForDevice(template, start, end);
+                return ret.getRxBytes() + ret.getTxBytes();
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Failed to read network stats: " + e);
+                return 0;
+            } finally {
+                Trace.traceEnd(TRACE_TAG_NETWORK);
+            }
+        }
+
+        @NonNull
+        List<NetworkStats.Bucket> getNetworkUidBytes(
+                @NonNull NetworkTemplate template, long start, long end) {
+            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes");
+            final List<NetworkStats.Bucket> buckets = new ArrayList<>();
+            try {
+                final NetworkStats stats = mNetworkStatsManager.querySummary(template, start, end);
+                while (stats.hasNextBucket()) {
+                    final NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+                    stats.getNextBucket(bucket);
+                    buckets.add(bucket);
+                }
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Failed to read network stats: " + e);
+            } finally {
+                Trace.traceEnd(TRACE_TAG_NETWORK);
+            }
+            return buckets;
+        }
+    }
+
+    @VisibleForTesting
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkManagementService networkManagement, IPackageManager pm, Clock clock,
-            File systemDir, boolean suppressDefaultPolicy) {
+            File systemDir, boolean suppressDefaultPolicy, Dependencies deps) {
         mContext = Objects.requireNonNull(context, "missing context");
         mActivityManager = Objects.requireNonNull(activityManager, "missing activityManager");
         mNetworkManager = Objects.requireNonNull(networkManagement, "missing networkManagement");
@@ -741,10 +786,12 @@
         mUidEventHandler = new Handler(mUidEventThread.getLooper(), mUidEventHandlerCallback);
 
         mSuppressDefaultPolicy = suppressDefaultPolicy;
+        mDeps = Objects.requireNonNull(deps, "missing Dependencies");
 
         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
 
         mAppOps = context.getSystemService(AppOpsManager.class);
+        mNetworkStats = context.getSystemService(NetworkStatsManager.class);
         mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
         // Expose private service for system components to use.
         LocalServices.addService(NetworkPolicyManagerInternal.class,
@@ -844,7 +891,6 @@
 
             mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
             mAppStandby = LocalServices.getService(AppStandbyInternal.class);
-            mNetworkStats = LocalServices.getService(NetworkStatsManagerInternal.class);
 
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
@@ -959,10 +1005,11 @@
             userFilter.addAction(ACTION_USER_REMOVED);
             mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
 
-            // listen for stats update events
-            final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
-            mContext.registerReceiver(
-                    mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
+            // listen for stats updated callbacks for interested network types.
+            mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_MOBILE).build(),
+                    0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
+            mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_WIFI).build(),
+                    0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
 
             // listen for restrict background changes from notifications
             final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
@@ -1167,14 +1214,16 @@
     };
 
     /**
-     * Receiver that watches for {@link INetworkStatsService} updates, which we
-     * use to check against {@link NetworkPolicy#warningBytes}.
+     * Listener that watches for {@link NetworkStatsManager} updates, which
+     * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}.
      */
-    final private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
+    private final StatsCallback mStatsCallback = new StatsCallback();
+    private class StatsCallback extends NetworkStatsManager.UsageCallback {
+        private boolean mIsAnyCallbackReceived = false;
+
         @Override
-        public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and verified
-            // READ_NETWORK_USAGE_HISTORY permission above.
+        public void onThresholdReached(int networkType, String subscriberId) {
+            mIsAnyCallbackReceived = true;
 
             synchronized (mNetworkPoliciesSecondLock) {
                 updateNetworkRulesNL();
@@ -1182,6 +1231,14 @@
                 updateNotificationsNL();
             }
         }
+
+        /**
+         * Return whether any callback is received.
+         * Used to determine if NetworkStatsService is ready.
+         */
+        public boolean isAnyCallbackReceived() {
+            return mIsAnyCallbackReceived;
+        }
     };
 
     /**
@@ -1284,7 +1341,7 @@
     };
 
     /**
-     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
+     * Check {@link NetworkPolicy} against current {@link NetworkStatsManager}
      * to show visible notifications as needed.
      */
     @GuardedBy("mNetworkPoliciesSecondLock")
@@ -1405,15 +1462,17 @@
         long maxBytes = 0;
         int maxUid = 0;
 
-        final NetworkStats stats = getNetworkUidBytes(template, start, end);
-        NetworkStats.Entry entry = null;
-        for (int i = 0; i < stats.size(); i++) {
-            entry = stats.getValues(i, entry);
-            final long bytes = entry.rxBytes + entry.txBytes;
+        // Skip if not ready. NetworkStatsService will block public API calls until it is
+        // ready. To prevent NPMS be blocked on that, skip and fail fast instead.
+        if (!mStatsCallback.isAnyCallbackReceived()) return null;
+
+        final List<NetworkStats.Bucket> stats = mDeps.getNetworkUidBytes(template, start, end);
+        for (final NetworkStats.Bucket entry : stats) {
+            final long bytes = entry.getRxBytes() + entry.getTxBytes();
             totalBytes += bytes;
             if (bytes > maxBytes) {
                 maxBytes = bytes;
-                maxUid = entry.uid;
+                maxUid = entry.getUid();
             }
         }
 
@@ -1449,13 +1508,11 @@
         for (int i = 0; i < mSubIdToSubscriberId.size(); i++) {
             final int subId = mSubIdToSubscriberId.keyAt(i);
             final String subscriberId = mSubIdToSubscriberId.valueAt(i);
-            final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                    TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
-                    true, OEM_NONE);
-            /* While OEM_NONE indicates "any non OEM managed network", OEM_NONE is meant to be a
-             * placeholder value here. The probeIdent is matched against a NetworkTemplate which
-             * should have its OEM managed value set to OEM_MANAGED_ALL, which will cause the
-             * template to match probeIdent without regard to OEM managed status. */
+            final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+                    .setType(TYPE_MOBILE)
+                    .setSubscriberId(subscriberId)
+                    .setMetered(true)
+                    .setDefaultNetwork(true).build();
             if (template.matches(probeIdent)) {
                 return subId;
             }
@@ -1688,9 +1745,11 @@
 
         // find and update the carrier NetworkPolicy for this subscriber id
         boolean policyUpdated = false;
-        final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true,
-                OEM_NONE);
+        final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+                .setType(TYPE_MOBILE)
+                .setSubscriberId(subscriberId)
+                .setMetered(true)
+                .setDefaultNetwork(true).build();
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
@@ -1918,10 +1977,11 @@
                 for (int i = 0; i < mSubIdToSubscriberId.size(); i++) {
                     final int subId = mSubIdToSubscriberId.keyAt(i);
                     final String subscriberId = mSubIdToSubscriberId.valueAt(i);
-
-                    final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                            TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
-                            true, OEM_NONE);
+                    final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+                            .setType(TYPE_MOBILE)
+                            .setSubscriberId(subscriberId)
+                            .setMetered(true)
+                            .setDefaultNetwork(true).build();
                     // Template is matched when subscriber id matches.
                     if (template.matches(probeIdent)) {
                         matchingSubIds.add(subId);
@@ -2025,11 +2085,9 @@
         for (final NetworkStateSnapshot snapshot : snapshots) {
             mNetIdToSubId.put(snapshot.getNetwork().getNetId(), parseSubId(snapshot));
 
-            // Policies matched by NPMS only match by subscriber ID or by network ID. Thus subtype
-            // in the object created here is never used and its value doesn't matter, so use
-            // NETWORK_TYPE_UNKNOWN.
-            final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
-                    true, TelephonyManager.NETWORK_TYPE_UNKNOWN /* subType */);
+            // Policies matched by NPMS only match by subscriber ID or by network ID.
+            final NetworkIdentity ident = new NetworkIdentity.Builder()
+                    .setNetworkStateSnapshot(snapshot).setDefaultNetwork(true).build();
             identified.put(snapshot, ident);
         }
 
@@ -2226,9 +2284,11 @@
     @GuardedBy("mNetworkPoliciesSecondLock")
     private boolean ensureActiveCarrierPolicyAL(int subId, String subscriberId) {
         // Poke around to see if we already have a policy
-        final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true,
-                OEM_NONE);
+        final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+                .setType(TYPE_MOBILE)
+                .setSubscriberId(subscriberId)
+                .setMetered(true)
+                .setDefaultNetwork(true).build();
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
@@ -2254,7 +2314,7 @@
         if (dataWarningConfig == WARNING_DISABLED) {
             return WARNING_DISABLED;
         } else {
-            return dataWarningConfig * MB_IN_BYTES;
+            return DataUnit.MEBIBYTES.toBytes(dataWarningConfig);
         }
     }
 
@@ -2279,6 +2339,18 @@
     }
 
     /**
+     * Template to match all metered carrier networks with the given IMSI.
+     *
+     * @hide
+     */
+    public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
+        Objects.requireNonNull(subscriberId);
+        return new NetworkTemplate.Builder(MATCH_CARRIER)
+                .setSubscriberIds(Set.of(subscriberId))
+                .setMeteredness(METERED_YES).build();
+    }
+
+    /**
      * Update the given {@link NetworkPolicy} based on any carrier-provided
      * defaults via {@link SubscriptionPlan} or {@link CarrierConfigManager}.
      * Leaves policy untouched if the user has modified it.
@@ -2638,7 +2710,7 @@
         final List<WifiConfiguration> configs = wm.getConfiguredNetworks();
         for (int i = 0; i < configs.size(); ++i) {
             final WifiConfiguration config = configs.get(i);
-            for (String key : config.getAllPersistableNetworkKeys()) {
+            for (String key : config.getAllNetworkKeys()) {
                 final Boolean metered = wifiNetworkKeys.get(key);
                 if (metered != null) {
                     Slog.d(TAG, "Found network " + key + "; upgrading metered hint");
@@ -2681,7 +2753,8 @@
 
                 out.startTag(null, TAG_NETWORK_POLICY);
                 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
-                final String subscriberId = template.getSubscriberId();
+                final String subscriberId = template.getSubscriberIds().isEmpty() ? null
+                        : template.getSubscriberIds().iterator().next();
                 if (subscriberId != null) {
                     out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
                 }
@@ -3058,7 +3131,7 @@
             }
             // When two normalized templates conflict, prefer the most
             // restrictive policy
-            policy.template = NetworkTemplate.normalize(policy.template, mMergedSubscriberIds);
+            policy.template = normalizeTemplate(policy.template, mMergedSubscriberIds);
             final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
             if (existing == null || existing.compareTo(policy) > 0) {
                 if (existing != null) {
@@ -3069,6 +3142,46 @@
         }
     }
 
+    /**
+     * Examine the given template and normalize it.
+     * We pick the "lowest" merged subscriber as the primary
+     * for key purposes, and expand the template to match all other merged
+     * subscribers.
+     *
+     * There can be multiple merged subscriberIds for multi-SIM devices.
+     *
+     * <p>
+     * For example, given an incoming template matching B, and the currently
+     * active merge set [A,B], we'd return a new template that primarily matches
+     * A, but also matches B.
+     */
+    private static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template,
+            @NonNull List<String[]> mergedList) {
+        // Now there are several types of network which uses Subscriber Id to store network
+        // information. For instance:
+        // 1. A merged carrier wifi network which has TYPE_WIFI with a Subscriber Id.
+        // 2. A typical cellular network could have TYPE_MOBILE with a Subscriber Id.
+
+        if (template.getSubscriberIds().isEmpty()) return template;
+
+        for (final String[] merged : mergedList) {
+            // TODO: Handle incompatible subscriberIds if that happens in practice.
+            for (final String subscriberId : template.getSubscriberIds()) {
+                if (com.android.net.module.util.CollectionUtils.contains(merged, subscriberId)) {
+                    // Requested template subscriber is part of the merged group; return
+                    // a template that matches all merged subscribers.
+                    return new NetworkTemplate.Builder(template.getMatchRule())
+                            .setWifiNetworkKeys(template.getWifiNetworkKeys())
+                            .setSubscriberIds(Set.of(merged))
+                            .setMeteredness(template.getMeteredness())
+                            .build();
+                }
+            }
+        }
+
+        return template;
+    }
+
     @Override
     public void snoozeLimit(NetworkTemplate template) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
@@ -3383,6 +3496,35 @@
         return result;
     }
 
+    /**
+     * Get subscription plan for the given networkTemplate.
+     *
+     * @param template the networkTemplate to get the subscription plan for.
+     */
+    @Override
+    public SubscriptionPlan getSubscriptionPlan(@NonNull NetworkTemplate template) {
+        enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
+        synchronized (mNetworkPoliciesSecondLock) {
+            final int subId = findRelevantSubIdNL(template);
+            return getPrimarySubscriptionPlanLocked(subId);
+        }
+    }
+
+    /**
+     * Notifies that the specified {@link NetworkStatsProvider} has reached its quota
+     * which was set through {@link NetworkStatsProvider#onSetLimit(String, long)} or
+     * {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}.
+     */
+    @Override
+    public void notifyStatsProviderWarningOrLimitReached() {
+        enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
+        // This API may be called before the system is ready.
+        synchronized (mNetworkPoliciesSecondLock) {
+            if (!mSystemReady) return;
+        }
+        mHandler.obtainMessage(MSG_STATS_PROVIDER_WARNING_OR_LIMIT_REACHED).sendToTarget();
+    }
+
     @Override
     public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) {
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
@@ -3394,9 +3536,9 @@
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
-                        .setDataUsage(1 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(1),
                                 ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
@@ -3404,15 +3546,15 @@
                         .setTitle("G-Mobile Happy")
                         .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
                                 SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, Charged after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
                         .build());
             } else if ("month_soft".equals(fake)) {
@@ -3421,25 +3563,25 @@
                         .setTitle("G-Mobile is the carriers name who this plan belongs to")
                         .setSummary("Crazy unlimited bandwidth plan with incredibly long title "
                                 + "that should be cut off to prevent UI from looking terrible")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(1 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(1),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, Throttled after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, No data connection after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
 
@@ -3447,25 +3589,25 @@
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile is the carriers name who this plan belongs to")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(6 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(6),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, Throttled after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, No data connection after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
 
@@ -3479,9 +3621,9 @@
                         .createNonrecurring(ZonedDateTime.now().minusDays(20),
                                 ZonedDateTime.now().plusDays(10))
                         .setTitle("G-Mobile")
-                        .setDataLimit(512 * TrafficStats.MB_IN_BYTES,
+                        .setDataLimit(DataUnit.MEBIBYTES.toBytes(512),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(100 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(100),
                                 ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
                         .build());
             } else if ("prepaid_crazy".equals(fake)) {
@@ -3489,9 +3631,9 @@
                         .createNonrecurring(ZonedDateTime.now().minusDays(20),
                                 ZonedDateTime.now().plusDays(10))
                         .setTitle("G-Mobile Anytime")
-                        .setDataLimit(512 * TrafficStats.MB_IN_BYTES,
+                        .setDataLimit(DataUnit.MEBIBYTES.toBytes(512),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(100 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(100),
                                 ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
@@ -3499,9 +3641,9 @@
                                 ZonedDateTime.now().plusDays(20))
                         .setTitle("G-Mobile Nickel Nights")
                         .setSummary("5¢/GB between 1-5AM")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(15 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(15),
                                 ZonedDateTime.now().minusHours(30).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
@@ -3509,9 +3651,9 @@
                                 ZonedDateTime.now().plusDays(20))
                         .setTitle("G-Mobile Bonus 3G")
                         .setSummary("Unlimited 3G data")
-                        .setDataLimit(1 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(1),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(300 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(300),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
             } else if ("unlimited".equals(fake)) {
@@ -3521,7 +3663,7 @@
                         .setTitle("G-Mobile Awesome")
                         .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(50 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(50),
                                 ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
                         .build());
             }
@@ -5000,7 +5142,8 @@
                     // make sure stats are recorded frequently enough; we aim
                     // for 2MB threshold for 2GB/month rules.
                     final long persistThreshold = lowestRule / 1000;
-                    mNetworkStats.advisePersistThreshold(persistThreshold);
+                    // TODO: Sync internal naming with the API surface.
+                    mNetworkStats.setDefaultGlobalAlert(persistThreshold);
                     return true;
                 }
                 case MSG_UPDATE_INTERFACE_QUOTAS: {
@@ -5369,25 +5512,10 @@
 
     @Deprecated
     private long getTotalBytes(NetworkTemplate template, long start, long end) {
-        return getNetworkTotalBytes(template, start, end);
-    }
-
-    private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
-        try {
-            return mNetworkStats.getNetworkTotalBytes(template, start, end);
-        } catch (RuntimeException e) {
-            Slog.w(TAG, "Failed to read network stats: " + e);
-            return 0;
-        }
-    }
-
-    private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
-        try {
-            return mNetworkStats.getNetworkUidBytes(template, start, end);
-        } catch (RuntimeException e) {
-            Slog.w(TAG, "Failed to read network stats: " + e);
-            return new NetworkStats(SystemClock.elapsedRealtime(), 0);
-        }
+        // Skip if not ready. NetworkStatsService will block public API calls until it is
+        // ready. To prevent NPMS be blocked on that, skip and fail fast instead.
+        if (!mStatsCallback.isAnyCallbackReceived()) return 0;
+        return mDeps.getNetworkTotalBytes(template, start, end);
     }
 
     private boolean isBandwidthControlEnabled() {
@@ -5505,7 +5633,11 @@
         NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
         NetworkTemplate templateCarrier = subscriber != null
                 ? buildTemplateCarrierMetered(subscriber) : null;
-        NetworkTemplate templateMobile = buildTemplateMobileAll(subscriber);
+        NetworkTemplate templateMobile = subscriber != null
+                ? new NetworkTemplate.Builder(MATCH_MOBILE)
+                .setSubscriberIds(Set.of(subscriber))
+                .setMeteredness(android.net.NetworkStats.METERED_YES)
+                .build() : null;
         for (NetworkPolicy policy : policies) {
             //  All policies loaded from disk will be carrier templates, and setting will also only
             //  set carrier templates, but we clear mobile templates just in case one is set by
@@ -5607,14 +5739,6 @@
         }
 
         @Override
-        public SubscriptionPlan getSubscriptionPlan(NetworkTemplate template) {
-            synchronized (mNetworkPoliciesSecondLock) {
-                final int subId = findRelevantSubIdNL(template);
-                return getPrimarySubscriptionPlanLocked(subId);
-            }
-        }
-
-        @Override
         public long getSubscriptionOpportunisticQuota(Network network, int quotaType) {
             final long quotaBytes;
             synchronized (mNetworkPoliciesSecondLock) {
@@ -5656,12 +5780,6 @@
             mHandler.obtainMessage(MSG_METERED_RESTRICTED_PACKAGES_CHANGED,
                     userId, 0, packageNames).sendToTarget();
         }
-
-        @Override
-        public void onStatsProviderWarningOrLimitReached(@NonNull String tag) {
-            Log.v(TAG, "onStatsProviderWarningOrLimitReached: " + tag);
-            mHandler.obtainMessage(MSG_STATS_PROVIDER_WARNING_OR_LIMIT_REACHED).sendToTarget();
-        }
     }
 
     private void setMeteredRestrictedPackagesInternal(Set<String> packageNames, int userId) {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 8fd545f..5a5f9ef 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -40,7 +40,6 @@
 import dalvik.system.BlockGuard;
 import dalvik.system.VMRuntime;
 
-import java.io.FileDescriptor;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -681,28 +680,6 @@
         }
     }
 
-    public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
-            throws InstallerException {
-        if (!checkBeforeRemote()) return;
-        BlockGuard.getVmPolicy().onPathAccess(filePath);
-        try {
-            mInstalld.installApkVerity(filePath, verityInput, contentSize);
-        } catch (Exception e) {
-            throw InstallerException.from(e);
-        }
-    }
-
-    public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)
-            throws InstallerException {
-        if (!checkBeforeRemote()) return;
-        BlockGuard.getVmPolicy().onPathAccess(filePath);
-        try {
-            mInstalld.assertFsverityRootHashMatches(filePath, expectedHash);
-        } catch (Exception e) {
-            throw InstallerException.from(e);
-        }
-    }
-
     public boolean reconcileSecondaryDexFile(String apkPath, String packageName, int uid,
             String[] isas, @Nullable String volumeUuid, int flags) throws InstallerException {
         for (int i = 0; i < isas.length; i++) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bc28cff..2d3cbfe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12118,14 +12118,14 @@
      * Returns if forced apk verification can be skipped for the whole package, including splits.
      */
     private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
-        if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) {
+        if (!VerityUtils.hasFsverity(pkg.getBaseApkPath())) {
             return false;
         }
         // TODO: Allow base and splits to be verified individually.
         String[] splitCodePaths = pkg.getSplitCodePaths();
         if (!ArrayUtils.isEmpty(splitCodePaths)) {
             for (int i = 0; i < splitCodePaths.length; i++) {
-                if (!canSkipForcedApkVerification(splitCodePaths[i])) {
+                if (!VerityUtils.hasFsverity(splitCodePaths[i])) {
                     return false;
                 }
             }
@@ -12134,33 +12134,6 @@
     }
 
     /**
-     * Returns if forced apk verification can be skipped, depending on current FSVerity setup and
-     * whether the apk contains signed root hash.  Note that the signer's certificate still needs to
-     * match one in a trusted source, and should be done separately.
-     */
-    private boolean canSkipForcedApkVerification(String apkPath) {
-        if (!PackageManagerServiceUtils.isLegacyApkVerityEnabled()) {
-            return VerityUtils.hasFsverity(apkPath);
-        }
-
-        try {
-            final byte[] rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath);
-            if (rootHashObserved == null) {
-                return false;  // APK does not contain Merkle tree root hash.
-            }
-            synchronized (mInstallLock) {
-                // Returns whether the observed root hash matches what kernel has.
-                mInstaller.assertFsverityRootHashMatches(apkPath, rootHashObserved);
-                return true;
-            }
-        } catch (InstallerException | IOException | DigestException |
-                NoSuchAlgorithmException e) {
-            Slog.w(TAG, "Error in fsverity check. Fallback to full apk verification.", e);
-        }
-        return false;
-    }
-
-    /**
      * Adds a new package to the internal data structures during platform initialization.
      * <p>After adding, the package is known to the system and available for querying.
      * <p>For packages located on the device ROM [eg. packages located in /system, /vendor,
@@ -21192,9 +21165,7 @@
      */
     private void setUpFsVerityIfPossible(AndroidPackage pkg) throws InstallerException,
             PrepareFailure, IOException, DigestException, NoSuchAlgorithmException {
-        final boolean standardMode = PackageManagerServiceUtils.isApkVerityEnabled();
-        final boolean legacyMode = PackageManagerServiceUtils.isLegacyApkVerityEnabled();
-        if (!standardMode && !legacyMode) {
+        if (!PackageManagerServiceUtils.isApkVerityEnabled()) {
             return;
         }
 
@@ -21205,39 +21176,25 @@
 
         // Collect files we care for fs-verity setup.
         ArrayMap<String, String> fsverityCandidates = new ArrayMap<>();
-        if (legacyMode) {
-            synchronized (mLock) {
-                final PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName());
-                if (ps != null && ps.isPrivileged()) {
-                    fsverityCandidates.put(pkg.getBaseApkPath(), null);
-                    if (pkg.getSplitCodePaths() != null) {
-                        for (String splitPath : pkg.getSplitCodePaths()) {
-                            fsverityCandidates.put(splitPath, null);
-                        }
-                    }
-                }
-            }
-        } else {
-            // NB: These files will become only accessible if the signing key is loaded in kernel's
-            // .fs-verity keyring.
-            fsverityCandidates.put(pkg.getBaseApkPath(),
-                    VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
+        // NB: These files will become only accessible if the signing key is loaded in kernel's
+        // .fs-verity keyring.
+        fsverityCandidates.put(pkg.getBaseApkPath(),
+                VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
 
-            final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
-                    pkg.getBaseApkPath());
-            if (new File(dmPath).exists()) {
-                fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
-            }
+        final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
+                pkg.getBaseApkPath());
+        if (new File(dmPath).exists()) {
+            fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
+        }
 
-            if (pkg.getSplitCodePaths() != null) {
-                for (String path : pkg.getSplitCodePaths()) {
-                    fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
+        if (pkg.getSplitCodePaths() != null) {
+            for (String path : pkg.getSplitCodePaths()) {
+                fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
 
-                    final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
-                    if (new File(splitDmPath).exists()) {
-                        fsverityCandidates.put(splitDmPath,
-                                VerityUtils.getFsveritySignatureFilePath(splitDmPath));
-                    }
+                final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
+                if (new File(splitDmPath).exists()) {
+                    fsverityCandidates.put(splitDmPath,
+                            VerityUtils.getFsveritySignatureFilePath(splitDmPath));
                 }
             }
         }
@@ -21246,40 +21203,14 @@
             final String filePath = entry.getKey();
             final String signaturePath = entry.getValue();
 
-            if (!legacyMode) {
-                // fs-verity is optional for now.  Only set up if signature is provided.
-                if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
-                    try {
-                        VerityUtils.setUpFsverity(filePath, signaturePath);
-                    } catch (IOException e) {
-                        throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
-                                "Failed to enable fs-verity: " + e);
-                    }
-                }
-                continue;
-            }
-
-            // In legacy mode, fs-verity can only be enabled by process with CAP_SYS_ADMIN.
-            final VerityUtils.SetupResult result = VerityUtils.generateApkVeritySetupData(filePath);
-            if (result.isOk()) {
-                if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling verity to " + filePath);
-                final FileDescriptor fd = result.getUnownedFileDescriptor();
+            // fs-verity is optional for now.  Only set up if signature is provided.
+            if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
                 try {
-                    final byte[] rootHash = VerityUtils.generateApkVerityRootHash(filePath);
-                    try {
-                        // A file may already have fs-verity, e.g. when reused during a split
-                        // install. If the measurement succeeds, no need to attempt to set up.
-                        mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
-                    } catch (InstallerException e) {
-                        mInstaller.installApkVerity(filePath, fd, result.getContentSize());
-                        mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
-                    }
-                } finally {
-                    IoUtils.closeQuietly(fd);
+                    VerityUtils.setUpFsverity(filePath, signaturePath);
+                } catch (IOException e) {
+                    throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
+                            "Failed to enable fs-verity: " + e);
                 }
-            } else if (result.isFailed()) {
-                throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
-                        "Failed to generate verity");
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 8b5abf3..8970049 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -591,12 +591,6 @@
     /** Default is to not use fs-verity since it depends on kernel support. */
     private static final int FSVERITY_DISABLED = 0;
 
-    /**
-     * Experimental implementation targeting priv apps, with Android specific kernel patches to
-     * extend fs-verity.
-     */
-    private static final int FSVERITY_LEGACY = 1;
-
     /** Standard fs-verity. */
     private static final int FSVERITY_ENABLED = 2;
 
@@ -607,10 +601,6 @@
                         == FSVERITY_ENABLED;
     }
 
-    static boolean isLegacyApkVerityEnabled() {
-        return SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED) == FSVERITY_LEGACY;
-    }
-
     /** Returns true to force apk verification if the package is considered privileged. */
     static boolean isApkVerificationForced(@Nullable PackageSetting ps) {
         // TODO(b/154310064): re-enable.
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 045a295..5047690 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -22,6 +22,7 @@
 import android.content.pm.UserInfo;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.RecoverySystem;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.os.SystemProperties;
@@ -115,6 +116,13 @@
                 // Try one last time; if we fail again we're really in trouble
                 prepareUserDataLI(volumeUuid, userId, userSerial,
                     flags | StorageManager.FLAG_STORAGE_DE, false);
+            } else {
+                try {
+                    Log.e(TAG, "prepareUserData failed", e);
+                    RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed");
+                } catch (IOException e2) {
+                    throw new RuntimeException("error rebooting into recovery", e2);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/policy/KeyCombinationManager.java b/services/core/java/com/android/server/policy/KeyCombinationManager.java
index 268de3e..68e078c 100644
--- a/services/core/java/com/android/server/policy/KeyCombinationManager.java
+++ b/services/core/java/com/android/server/policy/KeyCombinationManager.java
@@ -17,11 +17,13 @@
 
 import static android.view.KeyEvent.KEYCODE_POWER;
 
+import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.SparseLongArray;
 import android.view.KeyEvent;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ToBooleanFunction;
 
 import java.io.PrintWriter;
@@ -35,13 +37,18 @@
     private static final String TAG = "KeyCombinationManager";
 
     // Store the received down time of keycode.
+    @GuardedBy("mLock")
     private final SparseLongArray mDownTimes = new SparseLongArray(2);
     private final ArrayList<TwoKeysCombinationRule> mRules = new ArrayList();
 
     // Selected rules according to current key down.
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
     private final ArrayList<TwoKeysCombinationRule> mActiveRules = new ArrayList();
     // The rule has been triggered by current keys.
+    @GuardedBy("mLock")
     private TwoKeysCombinationRule mTriggeredRule;
+    private final Handler mHandler = new Handler();
 
     // Keys in a key combination must be pressed within this interval of each other.
     private static final long COMBINE_KEY_DELAY_MILLIS = 150;
@@ -109,6 +116,12 @@
      * Return true if any active rule could be triggered by the key event, otherwise false.
      */
     boolean interceptKey(KeyEvent event, boolean interactive) {
+        synchronized (mLock) {
+            return interceptKeyLocked(event, interactive);
+        }
+    }
+
+    private boolean interceptKeyLocked(KeyEvent event, boolean interactive) {
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         final int keyCode = event.getKeyCode();
         final int count = mActiveRules.size();
@@ -154,7 +167,7 @@
                         return false;
                     }
                     Log.v(TAG, "Performing combination rule : " + rule);
-                    rule.execute();
+                    mHandler.post(rule::execute);
                     mTriggeredRule = rule;
                     return true;
                 });
@@ -169,7 +182,7 @@
             for (int index = count - 1; index >= 0; index--) {
                 final TwoKeysCombinationRule rule = mActiveRules.get(index);
                 if (rule.shouldInterceptKey(keyCode)) {
-                    rule.cancel();
+                    mHandler.post(rule::cancel);
                     mActiveRules.remove(index);
                 }
             }
@@ -181,31 +194,37 @@
      * Return the interceptTimeout to tell InputDispatcher when is ready to deliver to window.
      */
     long getKeyInterceptTimeout(int keyCode) {
-        if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
-            return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
+        synchronized (mLock) {
+            if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
+                return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
+            }
+            return 0;
         }
-        return 0;
     }
 
     /**
      * True if the key event had been handled.
      */
     boolean isKeyConsumed(KeyEvent event) {
-        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
-            return false;
+        synchronized (mLock) {
+            if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
+                return false;
+            }
+            return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
         }
-        return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
     }
 
     /**
      * True if power key is the candidate.
      */
     boolean isPowerKeyIntercepted() {
-        if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
-            // return false if only if power key pressed.
-            return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
+        synchronized (mLock) {
+            if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
+                // return false if only if power key pressed.
+                return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
+            }
+            return false;
         }
-        return false;
     }
 
     /**
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index ef0079e..ca67597 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -35,7 +35,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
-
 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
 import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils;
 import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerResultUtils;
@@ -313,12 +312,12 @@
         return mStartWallTime;
     }
 
-    public PowerStatsLogger(Context context, File dataStoragePath,
+    public PowerStatsLogger(Context context, Looper looper, File dataStoragePath,
             String meterFilename, String meterCacheFilename,
             String modelFilename, String modelCacheFilename,
             String residencyFilename, String residencyCacheFilename,
             IPowerStatsHALWrapper powerStatsHALWrapper) {
-        super(Looper.getMainLooper());
+        super(looper);
         mStartWallTime = currentTimeMillis() - SystemClock.elapsedRealtime();
         if (DEBUG) Slog.d(TAG, "mStartWallTime: " + mStartWallTime);
         mPowerStatsHALWrapper = powerStatsHALWrapper;
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index bb52c1d..9953ca8 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -28,6 +28,7 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.power.PowerStatsInternal;
 import android.util.Slog;
@@ -79,6 +80,9 @@
     private StatsPullAtomCallbackImpl mPullAtomCallback;
     @Nullable
     private PowerStatsInternal mPowerStatsInternal;
+    @Nullable
+    @GuardedBy("this")
+    private Looper mLooper;
 
     @VisibleForTesting
     static class Injector {
@@ -127,12 +131,12 @@
             }
         }
 
-        PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
-                String meterFilename, String meterCacheFilename,
+        PowerStatsLogger createPowerStatsLogger(Context context, Looper looper,
+                File dataStoragePath, String meterFilename, String meterCacheFilename,
                 String modelFilename, String modelCacheFilename,
                 String residencyFilename, String residencyCacheFilename,
                 IPowerStatsHALWrapper powerStatsHALWrapper) {
-            return new PowerStatsLogger(context, dataStoragePath,
+            return new PowerStatsLogger(context, looper, dataStoragePath,
                 meterFilename, meterCacheFilename,
                 modelFilename, modelCacheFilename,
                 residencyFilename, residencyCacheFilename,
@@ -229,11 +233,11 @@
             mDataStoragePath = mInjector.createDataStoragePath();
 
             // Only start logger and triggers if initialization is successful.
-            mPowerStatsLogger = mInjector.createPowerStatsLogger(mContext, mDataStoragePath,
-                mInjector.createMeterFilename(), mInjector.createMeterCacheFilename(),
-                mInjector.createModelFilename(), mInjector.createModelCacheFilename(),
-                mInjector.createResidencyFilename(), mInjector.createResidencyCacheFilename(),
-                getPowerStatsHal());
+            mPowerStatsLogger = mInjector.createPowerStatsLogger(mContext, getLooper(),
+                    mDataStoragePath, mInjector.createMeterFilename(),
+                    mInjector.createMeterCacheFilename(), mInjector.createModelFilename(),
+                    mInjector.createModelCacheFilename(), mInjector.createResidencyFilename(),
+                    mInjector.createResidencyCacheFilename(), getPowerStatsHal());
             mBatteryTrigger = mInjector.createBatteryTrigger(mContext, mPowerStatsLogger);
             mTimerTrigger = mInjector.createTimerTrigger(mContext, mPowerStatsLogger);
         } else {
@@ -245,6 +249,17 @@
         return mInjector.getPowerStatsHALWrapperImpl();
     }
 
+    private Looper getLooper() {
+        synchronized (this) {
+            if (mLooper == null) {
+                HandlerThread thread = new HandlerThread(TAG);
+                thread.start();
+                return thread.getLooper();
+            }
+            return mLooper;
+        }
+    }
+
     public PowerStatsService(Context context) {
         this(context, new Injector());
     }
@@ -260,9 +275,7 @@
         private final Handler mHandler;
 
         LocalService() {
-            HandlerThread thread = new HandlerThread(TAG);
-            thread.start();
-            mHandler = new Handler(thread.getLooper());
+            mHandler = new Handler(getLooper());
         }
 
 
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 1ef2025..1fa948c 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -18,28 +18,17 @@
 
 import static android.app.AppOpsManager.OP_FLAG_SELF;
 import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
-import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
-import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE;
-import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN;
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.NetworkIdentity.OEM_PAID;
-import static android.net.NetworkIdentity.OEM_PRIVATE;
-import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
-import static android.net.NetworkStats.METERED_ALL;
 import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.ROAMING_ALL;
 import static android.net.NetworkTemplate.MATCH_ETHERNET;
-import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
-import static android.net.NetworkTemplate.MATCH_WIFI_WILDCARD;
-import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_WIFI;
 import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
-import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
-import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
-import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
-import static android.net.NetworkTemplate.getAllCollapsedRatTypes;
+import static android.net.NetworkTemplate.OEM_MANAGED_PAID;
+import static android.net.NetworkTemplate.OEM_MANAGED_PRIVATE;
 import static android.os.Debug.getIonHeapsSizeKb;
 import static android.os.Process.LAST_SHARED_APPLICATION_GID;
 import static android.os.Process.getUidForPid;
@@ -80,6 +69,7 @@
 import android.app.RuntimeAppOpAccessMessage;
 import android.app.StatsManager;
 import android.app.StatsManager.PullAtomMetadata;
+import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.UidTraffic;
@@ -93,8 +83,6 @@
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
 import android.net.Network;
 import android.net.NetworkRequest;
 import android.net.NetworkStats;
@@ -188,6 +176,7 @@
 import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.net.module.util.NetworkStatsUtils;
 import com.android.role.RoleManagerLocal;
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalManagerRegistry;
@@ -235,7 +224,7 @@
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.function.BiConsumer;
+import java.util.function.Function;
 
 /**
  * SystemService containing PullAtomCallbacks that are registered with statsd.
@@ -331,6 +320,7 @@
     private WifiManager mWifiManager;
     private TelephonyManager mTelephony;
     private SubscriptionManager mSubscriptionManager;
+    private NetworkStatsManager mNetworkStatsManager;
 
     @GuardedBy("mKernelWakelockLock")
     private KernelWakelockReader mKernelWakelockReader;
@@ -776,7 +766,7 @@
                 mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager);
         mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
-
+        mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
         // Initialize DiskIO
         mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();
 
@@ -966,32 +956,6 @@
         registerOemManagedBytesTransfer();
     }
 
-    /**
-     * Return the {@code INetworkStatsSession} object that holds the necessary properties needed
-     * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or
-     * null if the service or binder cannot be obtained. Calling this method will trigger poll
-     * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit}
-     * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where
-     * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at
-     * the network usage of their app.
-     */
-    @Nullable
-    private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) {
-        final INetworkStatsService networkStatsService =
-                INetworkStatsService.Stub.asInterface(
-                        ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-        if (networkStatsService == null) return null;
-
-        try {
-            return networkStatsService.openSessionForUsageStats(
-                    FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE
-                            : FLAG_POLL_ON_OPEN), mContext.getOpPackageName());
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Cannot get NetworkStats session", e);
-            return null;
-        }
-    }
-
     private IThermalService getIThermalService() {
         synchronized (mThermalLock) {
             if (mThermalService == null) {
@@ -1122,8 +1086,8 @@
             case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
                 final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI);
                 if (stats != null) {
-                    ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI},
-                                    /*slicedByFgbg=*/false));
+                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
+                            new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false));
                 }
                 break;
             }
@@ -1139,7 +1103,7 @@
                 final NetworkStats stats =
                         getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR);
                 if (stats != null) {
-                    ret.add(new NetworkStatsExt(stats.groupedByUid(),
+                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
                                     new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
                 }
                 break;
@@ -1155,9 +1119,10 @@
             }
             case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
                 final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplate(
-                        buildTemplateWifiWildcard(), /*includeTags=*/true);
+                        new NetworkTemplate.Builder(MATCH_WIFI).build(), /*includeTags=*/true);
                 final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplate(
-                        buildTemplateMobileWildcard(), /*includeTags=*/true);
+                        new NetworkTemplate.Builder(MATCH_MOBILE)
+                        .setMeteredness(METERED_YES).build(), /*includeTags=*/true);
                 if (wifiStats != null && cellularStats != null) {
                     final NetworkStats stats = wifiStats.add(cellularStats);
                     ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
@@ -1202,13 +1167,14 @@
                 Slog.e(TAG, "baseline is null for " + atomTag + ", return.");
                 return StatsManager.PULL_SKIP;
             }
+
             final NetworkStatsExt diff = new NetworkStatsExt(
-                    item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports,
+                    removeEmptyEntries(item.stats.subtract(baseline.stats)), item.transports,
                     item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType,
                     item.subInfo, item.oemManaged);
 
             // If no diff, skip.
-            if (diff.stats.size() == 0) continue;
+            if (!diff.stats.iterator().hasNext()) continue;
 
             switch (atomTag) {
                 case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
@@ -1227,25 +1193,32 @@
         return StatsManager.PULL_SUCCESS;
     }
 
+    @NonNull private static NetworkStats removeEmptyEntries(NetworkStats stats) {
+        NetworkStats ret = new NetworkStats(0, 1);
+        for (NetworkStats.Entry e : stats) {
+            if (e.getRxBytes() != 0 || e.getRxPackets() != 0 || e.getTxBytes() != 0
+                    || e.getTxPackets() != 0 || e.getOperations() != 0) {
+                ret = ret.addEntry(e);
+            }
+        }
+        return ret;
+    }
+
     private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret,
             @NonNull NetworkStatsExt statsExt) {
-        int size = statsExt.stats.size();
-        final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
-        for (int j = 0; j < size; j++) {
-            statsExt.stats.getValues(j, entry);
+        for (NetworkStats.Entry entry : statsExt.stats) {
             StatsEvent statsEvent;
-
             if (statsExt.slicedByFgbg) {
                 // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom.
                 statsEvent = FrameworkStatsLog.buildStatsEvent(
-                        atomTag, entry.uid,
-                        (entry.set > 0), entry.rxBytes, entry.rxPackets, entry.txBytes,
-                        entry.txPackets);
+                        atomTag, entry.getUid(),
+                        (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(),
+                        entry.getTxBytes(), entry.getTxPackets());
             } else {
                 // MobileBytesTransfer atom or WifiBytesTransfer atom.
                 statsEvent = FrameworkStatsLog.buildStatsEvent(
-                        atomTag, entry.uid, entry.rxBytes,
-                        entry.rxPackets, entry.txBytes, entry.txPackets);
+                        atomTag, entry.getUid(), entry.getRxBytes(),
+                        entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets());
             }
             ret.add(statsEvent);
         }
@@ -1253,33 +1226,31 @@
 
     private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt,
             @NonNull List<StatsEvent> pulledData) {
-        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
-        for (int i = 0; i < statsExt.stats.size(); i++) {
-            statsExt.stats.getValues(i, entry);
+        for (NetworkStats.Entry entry : statsExt.stats) {
             pulledData.add(FrameworkStatsLog.buildStatsEvent(
-                    FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.uid,
-                    entry.metered == NetworkStats.METERED_YES, entry.tag, entry.rxBytes,
-                    entry.rxPackets, entry.txBytes, entry.txPackets));
+                    FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(),
+                    entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(),
+                    entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(),
+                    entry.getTxPackets()));
         }
     }
 
     private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
             @NonNull List<StatsEvent> pulledData) {
 
-        // Workaround for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+        // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
         // 5G NSA mode means the primary cell is LTE with a secondary connection to an
         // NR cell. To mitigate risk, NetworkStats is currently storing this state as
         // a fake RAT type rather than storing the boolean separately.
-        final boolean is5GNsa = statsExt.ratType == NetworkTemplate.NETWORK_TYPE_5G_NSA;
+        final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA;
         // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with.
         final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR;
 
-        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
-        for (int i = 0; i < statsExt.stats.size(); i++) {
-            statsExt.stats.getValues(i, entry);
+        for (NetworkStats.Entry entry : statsExt.stats) {
             pulledData.add(FrameworkStatsLog.buildStatsEvent(
-                    FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.set, entry.rxBytes,
-                    entry.rxPackets, entry.txBytes, entry.txPackets,
+                    FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER,
+                    entry.getSet(), entry.getRxBytes(), entry.getRxPackets(),
+                    entry.getTxBytes(), entry.getTxPackets(),
                     is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType,
                     // Fill information about subscription, these cannot be null since invalid data
                     // would be filtered when adding into subInfo list.
@@ -1293,38 +1264,35 @@
 
     private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
             @NonNull List<StatsEvent> pulledData) {
-        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
         final int oemManaged = statsExt.oemManaged;
         for (final int transport : statsExt.transports) {
-            for (int i = 0; i < statsExt.stats.size(); i++) {
-                statsExt.stats.getValues(i, entry);
+            for (NetworkStats.Entry entry : statsExt.stats) {
                 pulledData.add(FrameworkStatsLog.buildStatsEvent(
-                        FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.uid, (entry.set > 0),
-                        oemManaged, transport, entry.rxBytes, entry.rxPackets, entry.txBytes,
-                        entry.txPackets));
+                        FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(),
+                        (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(),
+                        entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()));
             }
         }
     }
 
     @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManaged() {
-        final int[] transports = new int[] {MATCH_ETHERNET, MATCH_MOBILE_WILDCARD,
-                MATCH_WIFI_WILDCARD};
-        final int[] oemManagedTypes = new int[] {OEM_PAID | OEM_PRIVATE, OEM_PAID, OEM_PRIVATE};
+        final int[] matchRules = new int[] {MATCH_ETHERNET, MATCH_MOBILE, MATCH_WIFI};
+        final int[] oemManagedTypes = new int[] {OEM_MANAGED_PAID | OEM_MANAGED_PRIVATE,
+                OEM_MANAGED_PAID, OEM_MANAGED_PRIVATE};
 
         final List<NetworkStatsExt> ret = new ArrayList<>();
 
-        for (final int transport : transports) {
+        for (final int matchRule : matchRules) {
             for (final int oemManaged : oemManagedTypes) {
-                /* A null subscriberId will set wildcard=true, since we aren't trying to select a
-                   specific ssid or subscriber. */
-                final NetworkTemplate template = new NetworkTemplate(transport,
-                        /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
-                        METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                        oemManaged);
+                // Subscriber Ids and Wifi Network Keys will not be set since the purpose is to
+                // slice statistics of different OEM managed networks among all network types.
+                // Thus, specifying networks through their identifiers are not needed.
+                final NetworkTemplate template = new NetworkTemplate.Builder(matchRule)
+                        .setOemManaged(oemManaged).build();
                 final NetworkStats stats = getUidNetworkStatsSnapshotForTemplate(template, true);
                 if (stats != null) {
                     ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
-                            new int[] {transport}, /*slicedByFgbg=*/true, /*slicedByTag=*/true,
+                            new int[] {matchRule}, /*slicedByFgbg=*/true, /*slicedByTag=*/true,
                             /*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                             /*subInfo=*/null, oemManaged));
                 }
@@ -1338,10 +1306,18 @@
      * Create a snapshot of NetworkStats for a given transport.
      */
     @Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
-        final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
-                ? NetworkTemplate.buildTemplateMobileWithRatType(
-                /*subscriptionId=*/null, NETWORK_TYPE_ALL, METERED_YES)
-                : NetworkTemplate.buildTemplateWifiWildcard();
+        NetworkTemplate template = null;
+        switch (transport) {
+            case TRANSPORT_CELLULAR:
+                template = new NetworkTemplate.Builder(MATCH_MOBILE)
+                        .setMeteredness(METERED_YES).build();
+                break;
+            case TRANSPORT_WIFI:
+                template = new NetworkTemplate.Builder(MATCH_WIFI).build();
+                break;
+            default:
+                Log.wtf(TAG, "Unexpected transport.");
+        }
         return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
     }
 
@@ -1357,22 +1333,32 @@
         final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
         final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(),
                 NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS);
-        try {
-            // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats
-            //  history when query in every second in order to show realtime statistics. However,
-            //  this is not a good long-term solution since NetworkStatsService will make frequent
-            //  I/O and also block main thread when polling.
-            //  Consider making perfd queries NetworkStatsService directly.
-            final NetworkStats stats = getNetworkStatsSession(template.getMatchRule()
-                    == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template,
-                    currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
-                    currentTimeInMillis, includeTags);
-            return stats;
-        } catch (RemoteException | NullPointerException e) {
-            Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags="
-                    + includeTags  + " causes error", e);
+
+        // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats
+        //  history when query in every second in order to show realtime statistics. However,
+        //  this is not a good long-term solution since NetworkStatsService will make frequent
+        //  I/O and also block main thread when polling.
+        //  Consider making perfd queries NetworkStatsService directly.
+        if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) {
+            mNetworkStatsManager.forceUpdate();
         }
-        return null;
+
+        final android.app.usage.NetworkStats queryNonTaggedStats =
+                mNetworkStatsManager.querySummary(
+                template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
+                currentTimeInMillis);
+
+        final NetworkStats nonTaggedStats =
+                NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats);
+        if (!includeTags) return nonTaggedStats;
+
+        final android.app.usage.NetworkStats queryTaggedStats =
+                mNetworkStatsManager.queryTaggedSummary(template,
+                currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
+                currentTimeInMillis);
+        final NetworkStats taggedStats =
+                NetworkStatsUtils.fromPublicNetworkStats(queryTaggedStats);
+        return nonTaggedStats.add(taggedStats);
     }
 
     @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub(
@@ -1380,8 +1366,10 @@
         final List<NetworkStatsExt> ret = new ArrayList<>();
         for (final int ratType : getAllCollapsedRatTypes()) {
             final NetworkTemplate template =
-                    buildTemplateMobileWithRatType(subInfo.subscriberId, ratType,
-                    METERED_YES);
+                    new NetworkTemplate.Builder(MATCH_MOBILE)
+                    .setSubscriberIds(Set.of(subInfo.subscriberId))
+                    .setRatType(ratType)
+                    .setMeteredness(METERED_YES).build();
             final NetworkStats stats =
                     getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
             if (stats != null) {
@@ -1394,27 +1382,72 @@
         return ret;
     }
 
+    /**
+     * Return all supported collapsed RAT types that could be returned by
+     * {@link android.app.usage.NetworkStatsManager#getCollapsedRatType(int)}.
+     */
+    @NonNull
+    private static int[] getAllCollapsedRatTypes() {
+        final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
+        final HashSet<Integer> collapsedRatTypes = new HashSet<>();
+        for (final int ratType : ratTypes) {
+            collapsedRatTypes.add(NetworkStatsManager.getCollapsedRatType(ratType));
+        }
+        // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
+        // it is not in TelephonyManager#NETWORK_TYPE_* constants.
+        // See {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
+        collapsedRatTypes.add(
+                NetworkStatsManager.getCollapsedRatType(NetworkStatsManager.NETWORK_TYPE_5G_NSA));
+        // Ensure that unknown type is returned.
+        collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
+        return com.android.net.module.util.CollectionUtils.toIntArray(collapsedRatTypes);
+    }
+
+    @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) {
+        return sliceNetworkStats(stats,
+                (entry) -> {
+                        return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
+                                NetworkStats.SET_ALL, NetworkStats.TAG_NONE,
+                                NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+                                NetworkStats.DEFAULT_NETWORK_ALL,
+                                entry.getRxBytes(), entry.getRxPackets(),
+                                entry.getTxBytes(), entry.getTxPackets(), 0);
+                });
+    }
+
     @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) {
         return sliceNetworkStats(stats,
-                (newEntry, oldEntry) -> {
-                    newEntry.set = oldEntry.set;
+                (entry) -> {
+                        return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL,
+                                entry.getSet(), NetworkStats.TAG_NONE,
+                                NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+                                NetworkStats.DEFAULT_NETWORK_ALL,
+                                entry.getRxBytes(), entry.getRxPackets(),
+                                entry.getTxBytes(), entry.getTxPackets(), 0);
                 });
     }
 
     @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
         return sliceNetworkStats(stats,
-                (newEntry, oldEntry) -> {
-                    newEntry.uid = oldEntry.uid;
-                    newEntry.set = oldEntry.set;
+                (entry) -> {
+                        return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
+                                entry.getSet(), NetworkStats.TAG_NONE,
+                                NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+                                NetworkStats.DEFAULT_NETWORK_ALL,
+                                entry.getRxBytes(), entry.getRxPackets(),
+                                entry.getTxBytes(), entry.getTxPackets(), 0);
                 });
     }
 
     @NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) {
         return sliceNetworkStats(stats,
-                (newEntry, oldEntry) -> {
-                    newEntry.uid = oldEntry.uid;
-                    newEntry.tag = oldEntry.tag;
-                    newEntry.metered = oldEntry.metered;
+                (entry) -> {
+                        return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
+                                NetworkStats.SET_ALL, entry.getTag(),
+                                entry.getMetered(), NetworkStats.ROAMING_ALL,
+                                NetworkStats.DEFAULT_NETWORK_ALL,
+                                entry.getRxBytes(), entry.getRxPackets(),
+                                entry.getTxBytes(), entry.getTxPackets(), 0);
                 });
     }
 
@@ -1424,46 +1457,27 @@
      *
      * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the
      * default state (with the presumption that we don't want to slice on anything), and then
-     * applies the slicer lambda to allow users to control which dimensions to slice on. This is
-     * adapted from groupedByUid within NetworkStats.java
+     * applies the slicer lambda to allow users to control which dimensions to slice on.
      *
-     * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old
-     *               NetworkStats.Entry, that should be used to copy state from the old to the new.
+     * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to
+     *               get the state from entry to replace the default value.
      *               This is useful for slicing by particular dimensions. For example, if we wished
      *               to slice by uid and tag, we could write the following lambda:
-     *                  (new, old) -> {
-     *                          new.uid = old.uid;
-     *                          new.tag = old.tag;
+     *                  (entry) -> {
+     *                   return new NetworkStats.Entry(null, entry.getUid(),
+     *                           NetworkStats.SET_ALL, entry.getTag(),
+     *                           NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+     *                           NetworkStats.DEFAULT_NETWORK_ALL,
+     *                           entry.getRxBytes(), entry.getRxPackets(),
+     *                           entry.getTxBytes(), entry.getTxPackets(), 0);
      *                  }
-     *               If no slicer is provided, the data is not sliced by any dimensions.
      * @return new NeworkStats object appropriately sliced
      */
     @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats,
-            @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) {
-        final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
-
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-        entry.uid = NetworkStats.UID_ALL;
-        entry.iface = NetworkStats.IFACE_ALL;
-        entry.set = NetworkStats.SET_ALL;
-        entry.tag = NetworkStats.TAG_NONE;
-        entry.metered = NetworkStats.METERED_ALL;
-        entry.roaming = NetworkStats.ROAMING_ALL;
-        entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL;
-
-        final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values
-        for (int i = 0; i < stats.size(); i++) {
-            stats.getValues(i, recycle);
-            if (slicer != null) {
-                slicer.accept(entry, recycle);
-            }
-
-            entry.rxBytes = recycle.rxBytes;
-            entry.rxPackets = recycle.rxPackets;
-            entry.txBytes = recycle.txBytes;
-            entry.txPackets = recycle.txPackets;
-            // Operations purposefully omitted since we don't use them for statsd.
-            ret.combineValues(entry);
+            @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) {
+        NetworkStats ret = new NetworkStats(0, 1);
+        for (NetworkStats.Entry e : stats) {
+            ret = ret.addEntry(slicer.apply(e));
         }
         return ret;
     }
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 0f37450..e7d05b6 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -527,12 +527,13 @@
                     callback.onFailure();
                     return;
                 }
-                textClassifierServiceConsumer.accept(serviceState.mService);
+                consumeServiceNoExceptLocked(textClassifierServiceConsumer, serviceState.mService);
             } else {
                 serviceState.mPendingRequests.add(
                         new PendingRequest(
                                 methodName,
-                                () -> textClassifierServiceConsumer.accept(serviceState.mService),
+                                () -> consumeServiceNoExceptLocked(
+                                        textClassifierServiceConsumer, serviceState.mService),
                                 callback::onFailure, callback.asBinder(),
                                 this,
                                 serviceState,
@@ -541,6 +542,16 @@
         }
     }
 
+    private static void consumeServiceNoExceptLocked(
+            @NonNull ThrowingConsumer<ITextClassifierService> textClassifierServiceConsumer,
+            @Nullable ITextClassifierService service) {
+        try {
+            textClassifierServiceConsumer.accept(service);
+        } catch (RuntimeException | Error e) {
+            Slog.e(LOG_TAG, "Exception when consume textClassifierService: " + e);
+        }
+    }
+
     private static ITextClassifierCallback wrap(ITextClassifierCallback orig) {
         return new CallbackWrapper(orig);
     }
diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
index ff2f08b..10e868d 100644
--- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java
+++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
@@ -15,52 +15,99 @@
  */
 package com.android.server.tracing;
 
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BEGIN;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BIND_PERM_INCORRECT;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_COMM_ERROR;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_HANDOFF;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_PERM_MISSING;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
 import android.os.Binder;
+import android.os.IMessenger;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.ParcelFileDescriptor.AutoCloseInputStream;
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
 import android.os.UserHandle;
+import android.service.tracing.TraceReportService;
 import android.tracing.ITracingServiceProxy;
+import android.tracing.TraceReportParams;
 import android.util.Log;
+import android.util.LruCache;
+import android.util.Slog;
 
+import com.android.internal.infra.ServiceConnector;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.SystemService;
 
+import java.io.IOException;
+
 /**
  * TracingServiceProxy is the system_server intermediary between the Perfetto tracing daemon and the
- * system tracing app Traceur.
+ * other components (e.g. system tracing app Traceur, trace reporting apps).
  *
  * Access to this service is restricted via SELinux. Normal apps do not have access.
  *
  * @hide
  */
 public class TracingServiceProxy extends SystemService {
-    private static final String TAG = "TracingServiceProxy";
-
     public static final String TRACING_SERVICE_PROXY_BINDER_NAME = "tracing.proxy";
-
+    private static final String TAG = "TracingServiceProxy";
     private static final String TRACING_APP_PACKAGE_NAME = "com.android.traceur";
     private static final String TRACING_APP_ACTIVITY = "com.android.traceur.StopTraceService";
 
+    private static final int MAX_CACHED_REPORTER_SERVICES = 8;
+
+    // The maximum size of the trace allowed if the option |usePipeForTesting| is set.
+    // Note: this size MUST be smaller than the buffer size of the pipe (i.e. what you can
+    // write to the pipe without blocking) to avoid system_server blocking on this.
+    // (on Linux, the minimum value is 4K i.e. 1 minimally sized page).
+    private static final int MAX_FILE_SIZE_BYTES_TO_PIPE = 1024;
+
     // Keep this in sync with the definitions in TraceService
     private static final String INTENT_ACTION_NOTIFY_SESSION_STOPPED =
             "com.android.traceur.NOTIFY_SESSION_STOPPED";
     private static final String INTENT_ACTION_NOTIFY_SESSION_STOLEN =
             "com.android.traceur.NOTIFY_SESSION_STOLEN";
 
+    private static final int REPORT_BEGIN =
+            TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BEGIN;
+    private static final int REPORT_SVC_HANDOFF =
+            TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_HANDOFF;
+    private static final int REPORT_BIND_PERM_INCORRECT =
+            TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BIND_PERM_INCORRECT;
+    private static final int REPORT_SVC_PERM_MISSING =
+            TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_PERM_MISSING;
+    private static final int REPORT_SVC_COMM_ERROR =
+            TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_COMM_ERROR;
+
     private final Context mContext;
     private final PackageManager mPackageManager;
+    private final LruCache<ComponentName, ServiceConnector<IMessenger>> mCachedReporterServices;
 
     private final ITracingServiceProxy.Stub mTracingServiceProxy = new ITracingServiceProxy.Stub() {
         /**
-          * Notifies system tracing app that a tracing session has ended. If a session is repurposed
-          * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
-          * there is no buffer available to dump.
-          */
+         * Notifies system tracing app that a tracing session has ended. If a session is repurposed
+         * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
+         * there is no buffer available to dump.
+         */
         @Override
         public void notifyTraceSessionEnded(boolean sessionStolen) {
-            notifyTraceur(sessionStolen);
+            TracingServiceProxy.this.notifyTraceur(sessionStolen);
+        }
+
+        @Override
+        public void reportTrace(@NonNull TraceReportParams params) {
+            TracingServiceProxy.this.reportTrace(params);
         }
     };
 
@@ -68,6 +115,7 @@
         super(context);
         mContext = context;
         mPackageManager = context.getPackageManager();
+        mCachedReporterServices = new LruCache<>(MAX_CACHED_REPORTER_SERVICES);
     }
 
     @Override
@@ -103,4 +151,131 @@
             Log.e(TAG, "Failed to locate Traceur", e);
         }
     }
+
+    private void reportTrace(@NonNull TraceReportParams params) {
+        FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_BEGIN,
+                params.uuidLsb, params.uuidMsb);
+
+        // We don't need to do any permission checks on the caller because access
+        // to this service is guarded by SELinux.
+        ComponentName component = new ComponentName(params.reporterPackageName,
+                params.reporterClassName);
+        if (!hasBindServicePermission(component)) {
+            FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_BIND_PERM_INCORRECT,
+                    params.uuidLsb, params.uuidMsb);
+            return;
+        }
+        boolean hasDumpPermission = hasPermission(component, Manifest.permission.DUMP);
+        boolean hasUsageStatsPermission = hasPermission(component,
+                Manifest.permission.PACKAGE_USAGE_STATS);
+        if (!hasDumpPermission || !hasUsageStatsPermission) {
+            FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_SVC_PERM_MISSING,
+                    params.uuidLsb, params.uuidMsb);
+            return;
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            reportTrace(getOrCreateReporterService(component), params);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void reportTrace(
+            @NonNull ServiceConnector<IMessenger> reporterService,
+            @NonNull TraceReportParams params) {
+        reporterService.post(messenger -> {
+            if (params.usePipeForTesting) {
+                ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
+                try (AutoCloseInputStream i = new AutoCloseInputStream(params.fd)) {
+                    try (AutoCloseOutputStream o = new AutoCloseOutputStream(pipe[1])) {
+                        byte[] array = i.readNBytes(MAX_FILE_SIZE_BYTES_TO_PIPE);
+                        if (array.length == MAX_FILE_SIZE_BYTES_TO_PIPE) {
+                            throw new IllegalArgumentException(
+                                    "Trace file too large when |usePipeForTesting| is set.");
+                        }
+                        o.write(array);
+                    }
+                }
+                params.fd = pipe[0];
+            }
+
+            Message message = Message.obtain();
+            message.what = TraceReportService.MSG_REPORT_TRACE;
+            message.obj = params;
+            messenger.send(message);
+
+            FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_SVC_HANDOFF,
+                    params.uuidLsb, params.uuidMsb);
+        }).whenComplete((res, err) -> {
+            if (err != null) {
+                FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_SVC_COMM_ERROR,
+                        params.uuidLsb, params.uuidMsb);
+                Slog.e(TAG, "Failed to report trace", err);
+            }
+            try {
+                params.fd.close();
+            } catch (IOException ignored) {
+            }
+        });
+    }
+
+    private ServiceConnector<IMessenger> getOrCreateReporterService(
+            @NonNull ComponentName component) {
+        ServiceConnector<IMessenger> connector = mCachedReporterServices.get(component);
+        if (connector == null) {
+            Intent intent = new Intent();
+            intent.setComponent(component);
+            connector = new ServiceConnector.Impl<IMessenger>(
+                    mContext, intent,
+                    Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY,
+                    mContext.getUser().getIdentifier(), IMessenger.Stub::asInterface) {
+                private static final long DISCONNECT_TIMEOUT_MS = 15_000;
+                private static final long REQUEST_TIMEOUT_MS = 10_000;
+
+                @Override
+                protected long getAutoDisconnectTimeoutMs() {
+                    return DISCONNECT_TIMEOUT_MS;
+                }
+
+                @Override
+                protected long getRequestTimeoutMs() {
+                    return REQUEST_TIMEOUT_MS;
+                }
+            };
+            mCachedReporterServices.put(intent.getComponent(), connector);
+        }
+        return connector;
+    }
+
+    private boolean hasPermission(@NonNull ComponentName componentName,
+            @NonNull String permission) throws SecurityException {
+        if (mPackageManager.checkPermission(permission, componentName.getPackageName())
+                != PackageManager.PERMISSION_GRANTED) {
+            Slog.e(TAG,
+                    "Trace reporting service " + componentName.toShortString() + " does not have "
+                            + permission + " permission");
+            return false;
+        }
+        return true;
+    }
+
+    private boolean hasBindServicePermission(@NonNull ComponentName componentName) {
+        ServiceInfo info;
+        try {
+            info = mPackageManager.getServiceInfo(componentName, 0);
+        } catch (NameNotFoundException ex) {
+            Slog.e(TAG,
+                    "Trace reporting service " + componentName.toShortString() + " does not exist");
+            return false;
+        }
+        if (!Manifest.permission.BIND_TRACE_REPORT_SERVICE.equals(info.permission)) {
+            Slog.e(TAG,
+                    "Trace reporting service " + componentName.toShortString()
+                            + " does not request " + Manifest.permission.BIND_TRACE_REPORT_SERVICE
+                            + " permission; instead requests " + info.permission);
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index a17e792..30e2617 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -146,7 +146,7 @@
         filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
         filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED);
 
-        mContext.registerReceiver(this, filter, null, mHandler);
+        mContext.registerReceiver(this, filter, null, mHandler, Context.RECEIVER_NOT_EXPORTED);
         mSubscriptionManager.addOnSubscriptionsChangedListener(
                 executor, mSubscriptionChangedListener);
         mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index e0cc8e1..f29c40f 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -39,10 +39,13 @@
 import android.net.vcn.VcnGatewayConnectionConfig;
 import android.net.vcn.VcnManager.VcnErrorCode;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Message;
 import android.os.ParcelUuid;
 import android.provider.Settings;
+import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
 
@@ -57,6 +60,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -148,6 +152,10 @@
     @NonNull private final VcnContentResolver mContentResolver;
     @NonNull private final ContentObserver mMobileDataSettingsObserver;
 
+    @NonNull
+    private final Map<Integer, VcnUserMobileDataStateListener> mMobileDataStateListeners =
+            new ArrayMap<>();
+
     /**
      * Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs.
      *
@@ -221,6 +229,9 @@
         // Update mIsMobileDataEnabled before starting handling of NetworkRequests.
         mIsMobileDataEnabled = getMobileDataStatus();
 
+        // Register mobile data state listeners.
+        updateMobileDataStateListeners();
+
         // Register to receive cached and future NetworkRequests
         mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener);
     }
@@ -348,6 +359,12 @@
             gatewayConnection.teardownAsynchronously();
         }
 
+        // Unregister MobileDataStateListeners
+        for (VcnUserMobileDataStateListener listener : mMobileDataStateListeners.values()) {
+            getTelephonyManager().unregisterTelephonyCallback(listener);
+        }
+        mMobileDataStateListeners.clear();
+
         mCurrentStatus = VCN_STATUS_CODE_INACTIVE;
     }
 
@@ -454,11 +471,40 @@
             gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
         }
 
+        updateMobileDataStateListeners();
+
         // Update the mobile data state after updating the subscription snapshot as a change in
         // subIds for a subGroup may affect the mobile data state.
         handleMobileDataToggled();
     }
 
+    private void updateMobileDataStateListeners() {
+        final Set<Integer> subIdsInGroup = mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup);
+        final HandlerExecutor executor = new HandlerExecutor(this);
+
+        // Register new callbacks
+        for (int subId : subIdsInGroup) {
+            if (!mMobileDataStateListeners.containsKey(subId)) {
+                final VcnUserMobileDataStateListener listener =
+                        new VcnUserMobileDataStateListener();
+
+                getTelephonyManagerForSubid(subId).registerTelephonyCallback(executor, listener);
+                mMobileDataStateListeners.put(subId, listener);
+            }
+        }
+
+        // Unregister old callbacks
+        Iterator<Entry<Integer, VcnUserMobileDataStateListener>> iterator =
+                mMobileDataStateListeners.entrySet().iterator();
+        while (iterator.hasNext()) {
+            final Entry<Integer, VcnUserMobileDataStateListener> entry = iterator.next();
+            if (!subIdsInGroup.contains(entry.getKey())) {
+                getTelephonyManager().unregisterTelephonyCallback(entry.getValue());
+                iterator.remove();
+            }
+        }
+    }
+
     private void handleMobileDataToggled() {
         final boolean oldMobileDataEnabledStatus = mIsMobileDataEnabled;
         mIsMobileDataEnabled = getMobileDataStatus();
@@ -493,11 +539,8 @@
     }
 
     private boolean getMobileDataStatus() {
-        final TelephonyManager genericTelMan =
-                mVcnContext.getContext().getSystemService(TelephonyManager.class);
-
         for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) {
-            if (genericTelMan.createForSubscriptionId(subId).isDataEnabled()) {
+            if (getTelephonyManagerForSubid(subId).isDataEnabled()) {
                 return true;
             }
         }
@@ -517,6 +560,14 @@
         return request.canBeSatisfiedBy(builder.build());
     }
 
+    private TelephonyManager getTelephonyManager() {
+        return mVcnContext.getContext().getSystemService(TelephonyManager.class);
+    }
+
+    private TelephonyManager getTelephonyManagerForSubid(int subid) {
+        return getTelephonyManager().createForSubscriptionId(subid);
+    }
+
     private String getLogPrefix() {
         return "["
                 + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
@@ -670,6 +721,16 @@
         }
     }
 
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    class VcnUserMobileDataStateListener extends TelephonyCallback
+            implements TelephonyCallback.UserMobileDataStateListener {
+
+        @Override
+        public void onUserMobileDataStateChanged(boolean enabled) {
+            sendMessage(obtainMessage(MSG_EVENT_MOBILE_DATA_TOGGLED));
+        }
+    }
+
     /** External dependencies used by Vcn, for injection in tests */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     public static class Dependencies {
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 8b80b4a..597f7f2 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -78,6 +78,7 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 import android.util.Slog;
 
@@ -163,6 +164,14 @@
 public class VcnGatewayConnection extends StateMachine {
     private static final String TAG = VcnGatewayConnection.class.getSimpleName();
 
+    // Matches DataConnection.NETWORK_TYPE private constant, and magic string from
+    // ConnectivityManager#getNetworkTypeName()
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final String NETWORK_INFO_NETWORK_TYPE_STRING = "MOBILE";
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final String NETWORK_INFO_EXTRA_INFO = "VCN";
+
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0");
 
@@ -1631,6 +1640,12 @@
             final NetworkAgentConfig nac =
                     new NetworkAgentConfig.Builder()
                             .setLegacyType(ConnectivityManager.TYPE_MOBILE)
+                            .setLegacyTypeName(NETWORK_INFO_NETWORK_TYPE_STRING)
+                            .setLegacySubType(TelephonyManager.NETWORK_TYPE_UNKNOWN)
+                            .setLegacySubTypeName(
+                                    TelephonyManager.getNetworkTypeName(
+                                            TelephonyManager.NETWORK_TYPE_UNKNOWN))
+                            .setLegacyExtraInfo(NETWORK_INFO_EXTRA_INFO)
                             .build();
 
             final VcnNetworkAgent agent =
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index 6db25b7..c96c1ee 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -22,8 +22,6 @@
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
 
 import static com.android.server.VcnManagementService.LOCAL_LOG;
 
@@ -47,6 +45,7 @@
 import com.android.server.vcn.VcnContext;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /** @hide */
@@ -121,9 +120,10 @@
             TelephonySubscriptionSnapshot snapshot,
             UnderlyingNetworkRecord currentlySelected,
             PersistableBundle carrierConfig) {
-        // TODO: Check Network Quality reported by metric monitors/probers.
-
         final NetworkCapabilities caps = networkRecord.networkCapabilities;
+        final boolean isSelectedUnderlyingNetwork =
+                currentlySelected != null
+                        && Objects.equals(currentlySelected.network, networkRecord.network);
 
         final int meteredMatch = networkPriority.getMetered();
         final boolean isMetered = !caps.hasCapability(NET_CAPABILITY_NOT_METERED);
@@ -132,6 +132,23 @@
             return false;
         }
 
+        // Fails bandwidth requirements if either (a) less than exit threshold, or (b), not
+        // selected, but less than entry threshold
+        if (caps.getLinkUpstreamBandwidthKbps() < networkPriority.getMinExitUpstreamBandwidthKbps()
+                || (caps.getLinkUpstreamBandwidthKbps()
+                                < networkPriority.getMinEntryUpstreamBandwidthKbps()
+                        && !isSelectedUnderlyingNetwork)) {
+            return false;
+        }
+
+        if (caps.getLinkDownstreamBandwidthKbps()
+                        < networkPriority.getMinExitDownstreamBandwidthKbps()
+                || (caps.getLinkDownstreamBandwidthKbps()
+                                < networkPriority.getMinEntryDownstreamBandwidthKbps()
+                        && !isSelectedUnderlyingNetwork)) {
+            return false;
+        }
+
         if (vcnContext.isInTestMode() && caps.hasTransport(TRANSPORT_TEST)) {
             return true;
         }
@@ -172,8 +189,7 @@
         }
 
         // TODO: Move the Network Quality check to the network metric monitor framework.
-        if (networkPriority.getNetworkQuality()
-                > getWifiQuality(networkRecord, currentlySelected, carrierConfig)) {
+        if (!isWifiRssiAcceptable(networkRecord, currentlySelected, carrierConfig)) {
             return false;
         }
 
@@ -185,7 +201,7 @@
         return true;
     }
 
-    private static int getWifiQuality(
+    private static boolean isWifiRssiAcceptable(
             UnderlyingNetworkRecord networkRecord,
             UnderlyingNetworkRecord currentlySelected,
             PersistableBundle carrierConfig) {
@@ -196,14 +212,14 @@
 
         if (isSelectedNetwork
                 && caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)) {
-            return NETWORK_QUALITY_OK;
+            return true;
         }
 
         if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
-            return NETWORK_QUALITY_OK;
+            return true;
         }
 
-        return NETWORK_QUALITY_ANY;
+        return false;
     }
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b52e527..b685d48 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1038,6 +1038,8 @@
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(getActivityType()));
+        pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput=");
+                pw.println(mImeInsetsFrozenUntilStartInput);
         if (requestedVrComponent != null) {
             pw.print(prefix);
             pw.print("requestedVrComponent=");
@@ -4932,6 +4934,10 @@
                 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
                 break;
             case DESTROYED:
+                if (app != null && (mVisible || mVisibleRequested)) {
+                    // The app may be died while visible (no PAUSED state).
+                    mAtmService.updateBatteryStats(this, false);
+                }
                 mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
                 // Fall through.
             case DESTROYING:
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index f61cc94..a83a033 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -65,7 +65,16 @@
         @Override
         public void binderDied() {
             synchronized (mGlobalLock) {
-                mOrganizersByFeatureIds.remove(mFeature).destroy();
+                IDisplayAreaOrganizer featureOrganizer = getOrganizerByFeature(mFeature);
+                if (featureOrganizer != null) {
+                    IBinder organizerBinder = featureOrganizer.asBinder();
+                    if (!organizerBinder.equals(mOrganizer.asBinder()) &&
+                               organizerBinder.isBinderAlive()) {
+                        Slog.d(TAG, "Dead organizer replaced for feature=" + mFeature);
+                        return;
+                    }
+                    mOrganizersByFeatureIds.remove(mFeature).destroy();
+                }
             }
         }
     }
@@ -172,7 +181,7 @@
                         organizer.asBinder(), uid);
                 mOrganizersByFeatureIds.entrySet().removeIf((entry) -> {
                     final boolean matches = entry.getValue().mOrganizer.asBinder()
-                            == organizer.asBinder();
+                            .equals(organizer.asBinder());
                     if (matches) {
                         entry.getValue().destroy();
                     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9335846..bb8d6ef 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3969,11 +3969,11 @@
      * which controls the visibility and animation of the input method window.
      */
     void updateImeInputAndControlTarget(WindowState target) {
+        if (target != null && target.mActivityRecord != null) {
+            target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
+        }
         if (mImeInputTarget != target) {
             ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
-            if (target != null && target.mActivityRecord != null) {
-                target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
-            }
             setImeInputTarget(target);
             updateImeControlTarget();
         }
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index c7bf8ec..94f0e24 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -85,6 +85,8 @@
 
     private boolean mAnimationStartDelayed;
 
+    private boolean mAnimationFinished;
+
     /**
      * @param animatable The object to animate.
      * @param staticAnimationFinishedCallback Callback to invoke when an animation has finished
@@ -134,6 +136,7 @@
                         || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
                     resetAndInvokeFinish.run();
                 }
+                mAnimationFinished = true;
             }
         };
     }
@@ -289,6 +292,9 @@
             Slog.w(TAG, "Unable to transfer animation, surface or parent is null");
             cancelAnimation();
             return;
+        } else if (from.mAnimationFinished) {
+            Slog.w(TAG, "Unable to transfer animation, because " + from + " animation is finished");
+            return;
         }
         endDelayingAnimationStart();
         final Transaction t = mAnimatable.getPendingTransaction();
@@ -367,6 +373,7 @@
         SurfaceControl leash = mLeash;
         mLeash = null;
         final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
+        mAnimationFinished = false;
         if (scheduleAnim) {
             mService.scheduleAnimationLocked();
         }
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index ee4c629..152b4bc 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -42,13 +42,12 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
-import static java.lang.Integer.MIN_VALUE;
-
 import android.annotation.ColorInt;
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
+import android.graphics.Color;
 import android.os.UserHandle;
 import android.util.IntArray;
 import android.util.Slog;
@@ -83,9 +82,9 @@
     DisplayContent mDisplayContent;
 
     /**
-     * A color layer that serves as a solid color background to certain animations.
+     * Keeps track of the last set color layer so that it can be reset during surface migrations.
      */
-    private SurfaceControl mColorBackgroundLayer;
+    private @ColorInt int mBackgroundColor = 0;
 
     /**
      * This counter is used to make sure we don't prematurely clear the background color in the
@@ -367,6 +366,14 @@
     }
 
     @Override
+    void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
+        // We want an effect layer instead of the default container layer so that we can set a
+        // background color on it for task animations.
+        b.setEffectLayer();
+        super.setInitialSurfaceControlProperties(b);
+    }
+
+    @Override
     void addChild(WindowContainer child, int position) {
         if (child.asTaskDisplayArea() != null) {
             if (DEBUG_ROOT_TASK) {
@@ -980,11 +987,6 @@
     void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
         if (getParent() != null) {
             super.onParentChanged(newParent, oldParent, () -> {
-                mColorBackgroundLayer = makeChildSurface(null)
-                        .setColorLayer()
-                        .setName("colorBackgroundLayer")
-                        .setCallsite("TaskDisplayArea.onParentChanged")
-                        .build();
                 mAppAnimationLayer = makeChildSurface(null)
                         .setName("animationLayer")
                         .setCallsite("TaskDisplayArea.onParentChanged")
@@ -1011,13 +1013,11 @@
         } else {
             super.onParentChanged(newParent, oldParent);
             mWmService.mTransactionFactory.get()
-                    .remove(mColorBackgroundLayer)
                     .remove(mAppAnimationLayer)
                     .remove(mBoostedAppAnimationLayer)
                     .remove(mHomeAppAnimationLayer)
                     .remove(mSplitScreenDividerAnchor)
                     .apply();
-            mColorBackgroundLayer = null;
             mAppAnimationLayer = null;
             mBoostedAppAnimationLayer = null;
             mHomeAppAnimationLayer = null;
@@ -1025,35 +1025,29 @@
         }
     }
 
-    void setBackgroundColor(@ColorInt int color) {
-        if (mColorBackgroundLayer == null) {
-            return;
-        }
-
-        float r = ((color >> 16) & 0xff) / 255.0f;
-        float g = ((color >>  8) & 0xff) / 255.0f;
-        float b = ((color >>  0) & 0xff) / 255.0f;
-        float a = ((color >> 24) & 0xff) / 255.0f;
-
+    void setBackgroundColor(@ColorInt int colorInt) {
+        mBackgroundColor = colorInt;
+        Color color = Color.valueOf(colorInt);
         mColorLayerCounter++;
 
-        getPendingTransaction().setLayer(mColorBackgroundLayer, MIN_VALUE)
-                .setColor(mColorBackgroundLayer, new float[]{r, g, b})
-                .setAlpha(mColorBackgroundLayer, a)
-                .setWindowCrop(mColorBackgroundLayer, getSurfaceWidth(), getSurfaceHeight())
-                .setPosition(mColorBackgroundLayer, 0, 0)
-                .show(mColorBackgroundLayer);
-
-        scheduleAnimation();
+        // Only apply the background color if the TDA is actually attached and has a valid surface
+        // to set the background color on. We still want to keep track of the background color state
+        // even if we are not showing it for when/if the TDA is reattached and gets a valid surface
+        if (mSurfaceControl != null) {
+            getPendingTransaction()
+                    .setColor(mSurfaceControl,
+                            new float[]{color.red(), color.green(), color.blue()});
+            scheduleAnimation();
+        }
     }
 
     void clearBackgroundColor() {
         mColorLayerCounter--;
 
         // Only clear the color layer if we have received the same amounts of clear as set
-        // requests.
-        if (mColorLayerCounter == 0) {
-            getPendingTransaction().hide(mColorBackgroundLayer);
+        // requests and TDA has a non null surface control (i.e. is attached)
+        if (mColorLayerCounter == 0 && mSurfaceControl != null) {
+            getPendingTransaction().unsetColor(mSurfaceControl);
             scheduleAnimation();
         }
     }
@@ -1061,12 +1055,16 @@
     @Override
     void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
         super.migrateToNewSurfaceControl(t);
+
+        if (mColorLayerCounter > 0) {
+            setBackgroundColor(mBackgroundColor);
+        }
+
         if (mAppAnimationLayer == null) {
             return;
         }
 
         // As TaskDisplayArea is getting a new surface, reparent and reorder the child surfaces.
-        t.reparent(mColorBackgroundLayer, mSurfaceControl);
         t.reparent(mAppAnimationLayer, mSurfaceControl);
         t.reparent(mBoostedAppAnimationLayer, mSurfaceControl);
         t.reparent(mHomeAppAnimationLayer, mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index a518222..71893f4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -288,7 +288,7 @@
         }
         final ActivityRecord activity = result.first;
         final WindowState mainWindow = result.second;
-        final Rect contentInsets = getSystemBarInsets(task.getBounds(),
+        final Rect contentInsets = getSystemBarInsets(mainWindow.getFrame(),
                 mainWindow.getInsetsStateWithVisibilityOverride());
         InsetUtils.addInsets(contentInsets, activity.getLetterboxInsets());
 
@@ -554,7 +554,7 @@
         final LayoutParams attrs = mainWindow.getAttrs();
         final Rect taskBounds = task.getBounds();
         final InsetsState insetsState = mainWindow.getInsetsStateWithVisibilityOverride();
-        final Rect systemBarInsets = getSystemBarInsets(taskBounds, insetsState);
+        final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
                 attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),
                 mHighResTaskSnapshotScale, insetsState);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e7005da..e48b5e1 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -141,8 +141,8 @@
         "libutils",
         "libhwui",
         "libbpf_android",
-        "libnetdbpf",
         "libnetdutils",
+        "libnetworkstats",
         "libpsi",
         "libdataloader",
         "libincfs",
diff --git a/services/core/jni/BroadcastRadio/types.h b/services/core/jni/BroadcastRadio/types.h
index 910bb7c..4d286bf 100644
--- a/services/core/jni/BroadcastRadio/types.h
+++ b/services/core/jni/BroadcastRadio/types.h
@@ -30,13 +30,13 @@
 // Keep in sync with STATUS_* constants from RadioManager.java.
 enum class Status : jint {
     OK = 0,
-    ERROR = -0x80000000ll,  // Integer.MIN_VALUE
+    ERROR = -0x80000000LL,   // Integer.MIN_VALUE
     PERMISSION_DENIED = -1,  // -EPERM
-    NO_INIT = -19,  // -ENODEV
-    BAD_VALUE = -22,  // -EINVAL
-    DEAD_OBJECT = -32,  // -EPIPE
-    INVALID_OPERATION = -38,  // -ENOSYS
-    TIMED_OUT = -110,  // -ETIMEDOUT
+    NO_INIT = -19,           // -ENODEV
+    BAD_VALUE = -22,         // -EINVAL
+    DEAD_OBJECT = -32,       // -EPIPE
+    INVALID_OPERATION = -38, // -ENOSYS
+    TIMED_OUT = -110,        // -ETIMEDOUT
 };
 
 // Keep in sync with REGION_* constants from RadioManager.java.
diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
index ccb4f59..cba54b3 100644
--- a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
+++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
@@ -25,7 +25,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <asm/byteorder.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
index d29d3fc..9917bcb 100644
--- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp
+++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
@@ -15,16 +15,14 @@
  */
 
 #define LOG_TAG "UsbHostManagerJNI"
-#include "utils/Log.h"
-
+#include <nativehelper/JNIHelp.h>
 #include <stdlib.h>
+#include <usbhost/usbhost.h>
+#include <usbhost/usbhost_jni.h>
 
 #include "jni.h"
-#include <nativehelper/JNIHelp.h>
+#include "utils/Log.h"
 
-#include <usbhost/usbhost.h>
-
-#define MAX_DESCRIPTORS_LENGTH 4096
 static const int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;
 
 // com.android.server.usb.descriptors
@@ -41,26 +39,9 @@
     }
 
     int fd = usb_device_get_fd(device);
-    if (fd < 0) {
-        usb_device_close(device);
-        return NULL;
-    }
-
-    // from android_hardware_UsbDeviceConnection_get_desc()
-    jbyte buffer[MAX_DESCRIPTORS_LENGTH];
-    lseek(fd, 0, SEEK_SET);
-    int numBytes = read(fd, buffer, sizeof(buffer));
-    jbyteArray ret = NULL;
+    jbyteArray descriptors = usb_jni_read_descriptors(env, fd);
     usb_device_close(device);
-
-    if (numBytes > 0) {
-        ret = env->NewByteArray(numBytes);
-        env->SetByteArrayRegion(ret, 0, numBytes, buffer);
-    } else {
-        ALOGE("error reading descriptors\n");
-    }
-
-    return ret;
+    return descriptors;
 }
 
 jstring JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_getDescriptorString_1native(
diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp
index 3ab5920..0a9ce2f 100644
--- a/services/core/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp
@@ -25,7 +25,6 @@
 #include "MtpDescriptors.h"
 
 #include <stdio.h>
-#include <asm/byteorder.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index a629b69..e29d2ca 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -23,7 +23,6 @@
 #include "android_runtime/Log.h"
 
 #include <stdio.h>
-#include <asm/byteorder.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -31,8 +30,6 @@
 
 #include <usbhost/usbhost.h>
 
-#define MAX_DESCRIPTORS_LENGTH 4096
-
 namespace android
 {
 
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 5178132..39cbaf7 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -16,20 +16,18 @@
 
 #define LOG_TAG "NetworkStatsNative"
 
+#include <cutils/qtaguid.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "core_jni_helpers.h"
 #include <jni.h>
 #include <nativehelper/ScopedUtfChars.h>
-#include <utils/misc.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <utils/Log.h>
+#include <utils/misc.h>
 
-#include "android-base/unique_fd.h"
 #include "bpf/BpfUtils.h"
 #include "netdbpf/BpfNetworkStats.h"
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 37a84f3..1c9d584 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -32,6 +32,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.FactoryResetProtectionPolicy;
 import android.app.admin.PasswordPolicy;
+import android.app.admin.PreferentialNetworkServiceConfig;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.os.PersistableBundle;
@@ -294,6 +295,8 @@
     public boolean mAdminCanGrantSensorsPermissions;
     public boolean mPreferentialNetworkServiceEnabled =
             DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT;
+    public PreferentialNetworkServiceConfig mPreferentialNetworkServiceConfig =
+            PreferentialNetworkServiceConfig.DEFAULT;
 
     private static final boolean USB_DATA_SIGNALING_ENABLED_DEFAULT = true;
     boolean mUsbDataSignalingEnabled = USB_DATA_SIGNALING_ENABLED_DEFAULT;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0792d9b..564b608 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -109,6 +109,8 @@
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
 import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
 import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
@@ -179,6 +181,7 @@
 import android.app.admin.ParcelableGranteeMap;
 import android.app.admin.PasswordMetrics;
 import android.app.admin.PasswordPolicy;
+import android.app.admin.PreferentialNetworkServiceConfig;
 import android.app.admin.SecurityLog;
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.app.admin.StartInstallingUpdateCallback;
@@ -231,6 +234,7 @@
 import android.net.ConnectivityManager;
 import android.net.ConnectivitySettingsManager;
 import android.net.IIpConnectivityMetrics;
+import android.net.ProfileNetworkPreference;
 import android.net.ProxyInfo;
 import android.net.Uri;
 import android.net.VpnManager;
@@ -3276,14 +3280,14 @@
         updatePermissionPolicyCache(userId);
         updateAdminCanGrantSensorsPermissionCache(userId);
 
-        final boolean preferentialNetworkServiceEnabled;
+        final PreferentialNetworkServiceConfig preferentialNetworkServiceConfig;
         synchronized (getLockObject()) {
             ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
-            preferentialNetworkServiceEnabled = owner != null
-                    ? owner.mPreferentialNetworkServiceEnabled
-                             : DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT;
+            preferentialNetworkServiceConfig = owner != null
+                    ? owner.mPreferentialNetworkServiceConfig
+                    : PreferentialNetworkServiceConfig.DEFAULT;
         }
-        updateNetworkPreferenceForUser(userId, preferentialNetworkServiceEnabled);
+        updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfig);
 
         startOwnerService(userId, "start-user");
     }
@@ -3300,7 +3304,7 @@
 
     @Override
     void handleStopUser(int userId) {
-        updateNetworkPreferenceForUser(userId, false);
+        updateNetworkPreferenceForUser(userId, PreferentialNetworkServiceConfig.DEFAULT);
         stopOwnerService(userId, "stop-user");
     }
 
@@ -11844,7 +11848,7 @@
         final CallerIdentity caller = getCallerIdentity();
         Preconditions.checkCallAuthorization(isProfileOwner(caller),
                 "Caller is not profile owner;"
-                        + " only profile owner may control the preferntial network service");
+                        + " only profile owner may control the preferential network service");
         synchronized (getLockObject()) {
             final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(
                     caller.getUserId());
@@ -11881,6 +11885,47 @@
     }
 
     @Override
+    public void setPreferentialNetworkServiceConfig(
+            PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) {
+        if (!mHasFeature) {
+            return;
+        }
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isProfileOwner(caller),
+                "Caller is not profile owner;"
+                        + " only profile owner may control the preferential network service");
+        synchronized (getLockObject()) {
+            final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(
+                    caller.getUserId());
+            if (!requiredAdmin.mPreferentialNetworkServiceConfig.equals(
+                    preferentialNetworkServiceConfig)) {
+                requiredAdmin.mPreferentialNetworkServiceConfig = preferentialNetworkServiceConfig;
+                saveSettingsLocked(caller.getUserId());
+            }
+        }
+        updateNetworkPreferenceForUser(caller.getUserId(), preferentialNetworkServiceConfig);
+        DevicePolicyEventLogger
+                .createEvent(DevicePolicyEnums.SET_PREFERENTIAL_NETWORK_SERVICE_ENABLED)
+                .setBoolean(preferentialNetworkServiceConfig.isEnabled())
+                .write();
+    }
+
+    @Override
+    public PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig() {
+        if (!mHasFeature) {
+            return PreferentialNetworkServiceConfig.DEFAULT;
+        }
+
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isProfileOwner(caller),
+                "Caller is not profile owner");
+        synchronized (getLockObject()) {
+            final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(caller.getUserId());
+            return requiredAdmin.mPreferentialNetworkServiceConfig;
+        }
+    }
+
+    @Override
     public void setLockTaskPackages(ComponentName who, String[] packages)
             throws SecurityException {
         Objects.requireNonNull(who, "ComponentName is null");
@@ -17536,12 +17581,53 @@
         if (!isManagedProfile(userId)) {
             return;
         }
-        int networkPreference = preferentialNetworkServiceEnabled
-                ? PROFILE_NETWORK_PREFERENCE_ENTERPRISE : PROFILE_NETWORK_PREFERENCE_DEFAULT;
+        ProfileNetworkPreference.Builder preferenceBuilder =
+                new ProfileNetworkPreference.Builder();
+        if (preferentialNetworkServiceEnabled) {
+            preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+            preferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
+        } else {
+            preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
+        }
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceBuilder.build());
         mInjector.binderWithCleanCallingIdentity(() ->
-                mInjector.getConnectivityManager().setProfileNetworkPreference(
-                        UserHandle.of(userId),
-                        networkPreference,
+                mInjector.getConnectivityManager().setProfileNetworkPreferences(
+                        UserHandle.of(userId), preferences,
+                        null /* executor */, null /* listener */));
+    }
+
+    private void updateNetworkPreferenceForUser(int userId,
+            PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) {
+        if (!isManagedProfile(userId)) {
+            return;
+        }
+        ProfileNetworkPreference.Builder preferenceBuilder =
+                new ProfileNetworkPreference.Builder();
+        if (preferentialNetworkServiceConfig.isEnabled()) {
+            if (preferentialNetworkServiceConfig.isFallbackToDefaultConnectionAllowed()) {
+                preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+            } else {
+                preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
+            }
+        } else {
+            preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
+        }
+        List<Integer> allowedUids = Arrays.stream(
+                preferentialNetworkServiceConfig.getIncludedUids()).boxed().collect(
+                        Collectors.toList());
+        List<Integer> excludedUids = Arrays.stream(
+                preferentialNetworkServiceConfig.getExcludedUids()).boxed().collect(
+                Collectors.toList());
+        preferenceBuilder.setIncludedUids(allowedUids);
+        preferenceBuilder.setExcludedUids(excludedUids);
+        preferenceBuilder.setPreferenceEnterpriseId(
+                preferentialNetworkServiceConfig.getNetworkId());
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceBuilder.build());
+        mInjector.binderWithCleanCallingIdentity(() ->
+                mInjector.getConnectivityManager().setProfileNetworkPreferences(
+                        UserHandle.of(userId), preferences,
                         null /* executor */, null /* listener */));
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2aee778..ad97dd1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -54,6 +54,7 @@
 import android.net.ConnectivityManager;
 import android.net.ConnectivityModuleConnector;
 import android.net.NetworkStackClient;
+import android.net.TrafficStats;
 import android.os.BaseBundle;
 import android.os.Binder;
 import android.os.Build;
@@ -1333,12 +1334,10 @@
         DynamicSystemService dynamicSystem = null;
         IStorageManager storageManager = null;
         NetworkManagementService networkManagement = null;
-        IpSecService ipSecService = null;
         VpnManagerService vpnManager = null;
         VcnManagementService vcnManagement = null;
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
-        NsdService serviceDiscovery = null;
         WindowManagerService wm = null;
         SerialService serial = null;
         NetworkTimeUpdateService networkTimeUpdater = null;
@@ -1806,16 +1805,6 @@
             }
             t.traceEnd();
 
-
-            t.traceBegin("StartIpSecService");
-            try {
-                ipSecService = IpSecService.create(context);
-                ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService);
-            } catch (Throwable e) {
-                reportWtf("starting IpSec Service", e);
-            }
-            t.traceEnd();
-
             t.traceBegin("StartFontManagerService");
             mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
             t.traceEnd();
@@ -1837,8 +1826,9 @@
 
             t.traceBegin("StartNetworkStatsService");
             try {
-                networkStats = NetworkStatsService.create(context, networkManagement);
+                networkStats = NetworkStatsService.create(context);
                 ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
+                TrafficStats.init(context);
             } catch (Throwable e) {
                 reportWtf("starting NetworkStats Service", e);
             }
@@ -1941,16 +1931,6 @@
             }
             t.traceEnd();
 
-            t.traceBegin("StartNsdService");
-            try {
-                serviceDiscovery = NsdService.create(context);
-                ServiceManager.addService(
-                        Context.NSD_SERVICE, serviceDiscovery);
-            } catch (Throwable e) {
-                reportWtf("starting Service Discovery Service", e);
-            }
-            t.traceEnd();
-
             t.traceBegin("StartSystemUpdateManagerService");
             try {
                 ServiceManager.addService(Context.SYSTEM_UPDATE_SERVICE,
@@ -2676,7 +2656,6 @@
         final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
         final MediaRouterService mediaRouterF = mediaRouter;
         final MmsServiceBroker mmsServiceF = mmsService;
-        final IpSecService ipSecServiceF = ipSecService;
         final VpnManagerService vpnManagerF = vpnManager;
         final VcnManagementService vcnManagementF = vcnManagement;
         final WindowManagerService windowManagerF = wm;
@@ -2766,15 +2745,6 @@
                         .networkScoreAndNetworkManagementServiceReady();
             }
             t.traceEnd();
-            t.traceBegin("MakeIpSecServiceReady");
-            try {
-                if (ipSecServiceF != null) {
-                    ipSecServiceF.systemReady();
-                }
-            } catch (Throwable e) {
-                reportWtf("making IpSec Service ready", e);
-            }
-            t.traceEnd();
             t.traceBegin("MakeNetworkStatsServiceReady");
             try {
                 if (networkStatsF != null) {
diff --git a/services/midi/OWNERS b/services/midi/OWNERS
new file mode 100644
index 0000000..f4d51f9
--- /dev/null
+++ b/services/midi/OWNERS
@@ -0,0 +1 @@
+philburk@google.com
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 62a16f7..c5f990d 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -60,6 +60,12 @@
     private static ProfcollectForwardingService sSelfService;
     private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper());
 
+    private IProviderStatusCallback mProviderStatusCallback = new IProviderStatusCallback.Stub() {
+        public void onProviderReady() {
+            mHandler.sendEmptyMessage(ProfcollectdHandler.MESSAGE_REGISTER_SCHEDULERS);
+        }
+    };
+
     public ProfcollectForwardingService(Context context) {
         super(context);
 
@@ -93,13 +99,23 @@
             }
             BackgroundThread.get().getThreadHandler().post(() -> {
                 if (serviceHasSupportedTraceProvider()) {
-                    registerObservers();
-                    ProfcollectBGJobService.schedule(getContext());
+                    registerProviderStatusCallback();
                 }
             });
         }
     }
 
+    private void registerProviderStatusCallback() {
+        if (mIProfcollect == null) {
+            return;
+        }
+        try {
+            mIProfcollect.registerProviderStatusCallback(mProviderStatusCallback);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, e.getMessage());
+        }
+    }
+
     private boolean serviceHasSupportedTraceProvider() {
         if (mIProfcollect == null) {
             return false;
@@ -141,6 +157,7 @@
         }
 
         public static final int MESSAGE_BINDER_CONNECT = 0;
+        public static final int MESSAGE_REGISTER_SCHEDULERS = 1;
 
         @Override
         public void handleMessage(android.os.Message message) {
@@ -148,6 +165,10 @@
                 case MESSAGE_BINDER_CONNECT:
                     connectNativeService();
                     break;
+                case MESSAGE_REGISTER_SCHEDULERS:
+                    registerObservers();
+                    ProfcollectBGJobService.schedule(getContext());
+                    break;
                 default:
                     throw new AssertionError("Unknown message: " + message);
             }
diff --git a/services/proguard.flags b/services/proguard.flags
index 5d01d3e..0e081f1 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -1,21 +1,105 @@
-# TODO(b/196084106): Refine and optimize this configuration. Note that this
+# TODO(b/210510433): Refine and optimize this configuration. Note that this
 # configuration is only used when `SOONG_CONFIG_ANDROID_SYSTEM_OPTIMIZE_JAVA=true`.
--keep,allowoptimization,allowaccessmodification class ** {
-  !synthetic *;
-}
 
-# Various classes subclassed in ethernet-service (avoid marking final).
--keep public class android.net.** { *; }
-
-# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing).
--keep public class com.android.server.utils.Slogf { *; }
+# Preserve line number information for debugging stack traces.
+-keepattributes SourceFile,LineNumberTable
 
 # Allows making private and protected methods/fields public as part of
 # optimization. This enables inlining of trivial getter/setter methods.
 -allowaccessmodification
 
-# Disallow accessmodification for soundtrigger classes. Logging via reflective
-# public member traversal can cause infinite loops. See b/210901706.
--keep,allowoptimization class com.android.server.soundtrigger_middleware.** {
-  !synthetic *;
+# Process entrypoint
+-keep class com.android.server.SystemServer {
+  public static void main(java.lang.String[]);
 }
+
+# APIs referenced by dependent JAR files and modules
+-keep @interface android.annotation.SystemApi
+-keep @android.annotation.SystemApi class * {
+  public protected *;
+}
+-keepclasseswithmembers class * {
+  @android.annotation.SystemApi *;
+}
+
+# Derivatives of SystemService and other services created via reflection
+-keep,allowoptimization,allowaccessmodification class * extends com.android.server.SystemService {
+  public <methods>;
+}
+-keep,allowoptimization,allowaccessmodification class * extends com.android.server.devicepolicy.BaseIDevicePolicyManager {
+  public <init>(...);
+}
+-keep,allowoptimization,allowaccessmodification class com.android.server.wallpaper.WallpaperManagerService {
+  public <init>(...);
+}
+
+# Binder interfaces
+-keep,allowoptimization,allowaccessmodification class * extends android.os.IInterface
+-keep,allowoptimization,allowaccessmodification class * extends android.os.IHwInterface
+
+# Global entities normally kept through explicit Manifest entries
+# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/AndroidManifest.xml,
+# by including that manifest with the library rule that triggers optimization.
+-keep,allowoptimization,allowaccessmodification class * extends android.app.backup.BackupAgent
+-keep,allowoptimization,allowaccessmodification class * extends android.content.BroadcastReceiver
+-keep,allowoptimization,allowaccessmodification class * extends android.content.ContentProvider
+
+# Various classes subclassed in or referenced via JNI in ethernet-service
+-keep public class android.net.** { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.net.module.util.* { *; }
+-keep,allowoptimization,allowaccessmodification public class com.android.server.net.IpConfigStore { *; }
+-keep,allowoptimization,allowaccessmodification public class com.android.server.net.BaseNetworkObserver { *; }
+
+# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing)
+-keep public class com.android.server.utils.Slogf { *; }
+
+# Notification extractors
+# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
+-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
+
+# JNI keep rules
+# TODO(b/210510433): Revisit and fix with @Keep, or consider auto-generating from
+# frameworks/base/services/core/jni/onload.cpp.
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.BroadcastRadioService { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.Convert { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.Tuner { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.TunerCallback { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.location.gnss.GnssConfiguration$HalInterfaceVersion { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.location.gnss.GnssPowerStats { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.location.gnss.hal.GnssNative { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.sensors.SensorManagerInternal$ProximityActiveListener { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.sensors.SensorService { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.soundtrigger_middleware.SoundTriggerMiddlewareImpl$AudioSessionProvider$AudioSession { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.soundtrigger_middleware.ExternalCaptureStateTracker { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.storage.AppFuseBridge { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.tv.TvInputHal { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaJackDetector { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbMidiDevice { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorController$OnVibrationCompleteListener { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorManagerService$OnSyncedVibrationCompleteListener { *; }
+-keepclasseswithmembers,allowoptimization,allowaccessmodification class com.android.server.** {
+  *** *FromNative(...);
+}
+-keep,allowoptimization,allowaccessmodification class com.android.server.input.InputManagerService {
+  <methods>;
+}
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbHostManager {
+  *** usbDeviceRemoved(...);
+  *** usbDeviceAdded(...);
+}
+-keep,allowoptimization,allowaccessmodification class **.*NativeWrapper* { *; }
+
+# Miscellaneous reflection keep rules
+# TODO(b/210510433): Revisit and fix with @Keep.
+-keep,allowoptimization,allowaccessmodification class com.android.server.usage.AppStandbyController {
+  public <init>(...);
+}
+-keep,allowoptimization,allowaccessmodification class android.hardware.usb.gadget.** { *; }
+
+# Needed when optimizations enabled
+# TODO(b/210510433): Revisit and fix with @Keep.
+-keep,allowoptimization,allowaccessmodification class com.android.server.SystemService { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.SystemService$TargetUser { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usage.StorageStatsManagerLocal { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.internal.util.** { *; }
+-keep,allowoptimization,allowaccessmodification class android.os.** { *; }
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index f182b66..428327c 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -25,6 +25,7 @@
         "test-apps/JobTestApp/src/**/*.java",
 
         "test-apps/SuspendTestApp/src/**/*.java",
+	":service-bluetooth-tests-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
     ],
     static_libs: [
         "frameworks-base-testutils",
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index bcb2cf8..187b012 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -93,6 +93,7 @@
     <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/>
     <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/>
     <uses-permission android:name="android.permission.KILL_UID"/>
+    <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK"/>
     <uses-permission
         android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
 
diff --git a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
deleted file mode 100644
index a1d4c20..0000000
--- a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static org.mockito.Mockito.*;
-
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.os.Looper;
-import android.provider.Settings;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-public class BluetoothAirplaneModeListenerTest {
-    private Context mContext;
-    private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
-    private BluetoothAdapter mBluetoothAdapter;
-    private BluetoothModeChangeHelper mHelper;
-
-    @Mock BluetoothManagerService mBluetoothManagerService;
-
-    @Before
-    public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getTargetContext();
-
-        mHelper = mock(BluetoothModeChangeHelper.class);
-        when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT))
-                .thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT);
-        doNothing().when(mHelper).setSettingsInt(anyString(), anyInt());
-        doNothing().when(mHelper).showToastMessage();
-        doNothing().when(mHelper).onAirplaneModeChanged(any(BluetoothManagerService.class));
-
-        mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
-                    mBluetoothManagerService, Looper.getMainLooper(), mContext);
-        mBluetoothAirplaneModeListener.start(mHelper);
-    }
-
-    @Test
-    public void testIgnoreOnAirplanModeChange() {
-        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-
-        when(mHelper.isBluetoothOn()).thenReturn(true);
-        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-
-        when(mHelper.isMediaProfileConnected()).thenReturn(true);
-        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-
-        when(mHelper.isAirplaneModeOn()).thenReturn(true);
-        Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
-    }
-
-    @Test
-    public void testHandleAirplaneModeChange_InvokeAirplaneModeChanged() {
-        mBluetoothAirplaneModeListener.handleAirplaneModeChange();
-        verify(mHelper).onAirplaneModeChanged(mBluetoothManagerService);
-    }
-
-    @Test
-    public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_NotPopToast() {
-        mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
-        when(mHelper.isBluetoothOn()).thenReturn(true);
-        when(mHelper.isMediaProfileConnected()).thenReturn(true);
-        when(mHelper.isAirplaneModeOn()).thenReturn(true);
-        mBluetoothAirplaneModeListener.handleAirplaneModeChange();
-
-        verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
-                BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
-        verify(mHelper, times(0)).showToastMessage();
-        verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
-    }
-
-    @Test
-    public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_PopToast() {
-        mBluetoothAirplaneModeListener.mToastCount = 0;
-        when(mHelper.isBluetoothOn()).thenReturn(true);
-        when(mHelper.isMediaProfileConnected()).thenReturn(true);
-        when(mHelper.isAirplaneModeOn()).thenReturn(true);
-        mBluetoothAirplaneModeListener.handleAirplaneModeChange();
-
-        verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
-                BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
-        verify(mHelper).showToastMessage();
-        verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
-    }
-
-    @Test
-    public void testIsPopToast_PopToast() {
-        mBluetoothAirplaneModeListener.mToastCount = 0;
-        Assert.assertTrue(mBluetoothAirplaneModeListener.shouldPopToast());
-        verify(mHelper).setSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT, 1);
-    }
-
-    @Test
-    public void testIsPopToast_NotPopToast() {
-        mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
-        Assert.assertFalse(mBluetoothAirplaneModeListener.shouldPopToast());
-        verify(mHelper, times(0)).setSettingsInt(anyString(), anyInt());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverTest.java
deleted file mode 100644
index 489e2f7..0000000
--- a/services/tests/servicestests/src/com/android/server/BootReceiverTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.server;
-
-import android.test.AndroidTestCase;
-
-/**
- * Tests for {@link com.android.server.BootReceiver}
- */
-public class BootReceiverTest extends AndroidTestCase {
-    public void testLogLinePotentiallySensitive() throws Exception {
-        /*
-         * Strings to be dropped from the log as potentially sensitive: register dumps, process
-         * names, hardware info.
-         */
-        final String[] becomeNull = {
-            "CPU: 4 PID: 120 Comm: kunit_try_catch Tainted: G        W         5.8.0-rc6+ #7",
-            "Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1 04/01/2014",
-            "[    0.083207] RSP: 0000:ffffffff8fe07ca8 EFLAGS: 00010046 ORIG_RAX: 0000000000000000",
-            "[    0.084709] RAX: 0000000000000000 RBX: ffffffffff240000 RCX: ffffffff815fcf01",
-            "[    0.086109] RDX: dffffc0000000000 RSI: 0000000000000001 RDI: ffffffffff240004",
-            "[    0.087509] RBP: ffffffff8fe07d60 R08: fffffbfff1fc0f21 R09: fffffbfff1fc0f21",
-            "[    0.088911] R10: ffffffff8fe07907 R11: fffffbfff1fc0f20 R12: ffffffff8fe07d38",
-            "R13: 0000000000000001 R14: 0000000000000001 R15: ffffffff8fe07e80",
-            "x29: ffff00003ce07150 x28: ffff80001aa29cc0",
-            "x1 : 0000000000000000 x0 : ffff00000f628000",
-        };
-
-        /* Strings to be left unchanged, including non-sensitive registers and parts of reports. */
-        final String[] leftAsIs = {
-            "FS:  0000000000000000(0000) GS:ffffffff92409000(0000) knlGS:0000000000000000",
-            "[ 69.2366] [ T6006]c7   6006  =======================================================",
-            "[ 69.245688] [ T6006] BUG: KFENCE: out-of-bounds in kfence_handle_page_fault",
-            "[ 69.257816] [ T6006]c7   6006  Out-of-bounds access at 0xffffffca75c45000 ",
-            "[ 69.273536] [ T6006]c7   6006   __do_kernel_fault+0xa8/0x11c",
-            "pc : __mutex_lock+0x428/0x99c ",
-            "sp : ffff00003ce07150",
-            "Call trace:",
-            "",
-        };
-
-        final String[][] stripped = {
-            { "Detected corrupted memory at 0xffffffffb6797ff9 [ 0xac . . . . . . ]:",
-              "Detected corrupted memory at 0xffffffffb6797ff9" },
-        };
-        for (int i = 0; i < becomeNull.length; i++) {
-            assertEquals(BootReceiver.stripSensitiveData(becomeNull[i]), null);
-        }
-
-        for (int i = 0; i < leftAsIs.length; i++) {
-            assertEquals(BootReceiver.stripSensitiveData(leftAsIs[i]), leftAsIs[i]);
-        }
-
-        for (int i = 0; i < stripped.length; i++) {
-            assertEquals(BootReceiver.stripSensitiveData(stripped[i][0]), stripped[i][1]);
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
index 6a7d298..68994e6 100644
--- a/services/tests/servicestests/src/com/android/server/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -1,6 +1,6 @@
 per-file *Alarm* = file:/apex/jobscheduler/OWNERS
 per-file *AppOp* = file:/core/java/android/permission/OWNERS
-per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
+per-file *Bluetooth* = file:platform/packages/modules/Bluetooth:master:/framework/java/android/bluetooth/OWNERS
 per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
 per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
 per-file BatteryServiceTest.java = file:platform/hardware/interfaces:/health/aidl/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index 9e1445c..bdea679 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -30,7 +30,7 @@
 import android.content.Intent;
 import android.media.AudioManager;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -100,7 +100,7 @@
 
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
-                    BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource"));
         Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS);
         verify(mSpyDevInventory, times(1)).setBluetoothActiveDevice(
                 any(AudioDeviceBroker.BtDeviceInfo.class)
@@ -208,13 +208,13 @@
         // first connection: ensure the device is connected as a starting condition for the test
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
-                    BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource"));
         Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
 
         // disconnection
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(null, mFakeBtDevice,
-                    BtProfileConnectionInfo.a2dpInfo(false, -1), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(false, -1), "testSource"));
         if (delayAfterDisconnection > 0) {
             Thread.sleep(delayAfterDisconnection);
         }
@@ -222,7 +222,7 @@
         // reconnection
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
-                    BtProfileConnectionInfo.a2dpInfo(true, 2), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(true, 2), "testSource"));
         Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS);
 
         // Verify disconnection has been cancelled and we're seeing two connections attempts,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 3ac30d02..3511fc1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -37,7 +37,11 @@
 import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
 import static android.app.admin.PasswordMetrics.computeForPasswordOrPin;
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
 import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
@@ -87,6 +91,7 @@
 import android.app.admin.DevicePolicyManagerLiteInternal;
 import android.app.admin.FactoryResetProtectionPolicy;
 import android.app.admin.PasswordMetrics;
+import android.app.admin.PreferentialNetworkServiceConfig;
 import android.app.admin.SystemUpdatePolicy;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -99,7 +104,7 @@
 import android.content.pm.UserInfo;
 import android.graphics.Color;
 import android.hardware.usb.UsbManager;
-import android.net.ConnectivityManager;
+import android.net.ProfileNetworkPreference;
 import android.net.Uri;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
@@ -4044,12 +4049,15 @@
         mServiceContext.permissions.add(permission.INTERACT_ACROSS_USERS_FULL);
 
         dpms.handleStartUser(managedProfileUserId);
-        verify(getServices().connectivityManager, times(1)).setProfileNetworkPreference(
-                eq(UserHandle.of(managedProfileUserId)),
-                anyInt(),
-                any(),
-                any()
-        );
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                .setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT)
+                .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                null, null);
     }
 
     @Test
@@ -4061,12 +4069,15 @@
         mServiceContext.permissions.add(permission.INTERACT_ACROSS_USERS_FULL);
 
         dpms.handleStopUser(managedProfileUserId);
-        verify(getServices().connectivityManager, times(1)).setProfileNetworkPreference(
-                eq(UserHandle.of(managedProfileUserId)),
-                eq(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT),
-                any(),
-                any()
-        );
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT)
+                        .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                        null, null);
     }
 
     @Test
@@ -4084,21 +4095,188 @@
 
         dpm.setPreferentialNetworkServiceEnabled(false);
         assertThat(dpm.isPreferentialNetworkServiceEnabled()).isFalse();
-        verify(getServices().connectivityManager, times(1)).setProfileNetworkPreference(
-                eq(UserHandle.of(managedProfileUserId)),
-                eq(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT),
-                any(),
-                any()
-        );
+
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT)
+                        .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                        null, null);
 
         dpm.setPreferentialNetworkServiceEnabled(true);
         assertThat(dpm.isPreferentialNetworkServiceEnabled()).isTrue();
-        verify(getServices().connectivityManager, times(1)).setProfileNetworkPreference(
-                eq(UserHandle.of(managedProfileUserId)),
-                eq(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE),
-                any(),
-                any()
-        );
+
+        ProfileNetworkPreference preferenceDetails2 =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE)
+                        .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+                        .build();
+        List<ProfileNetworkPreference> preferences2 = new ArrayList<>();
+        preferences2.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences2,
+                        null, null);
+    }
+
+    @Test
+    public void testSetPreferentialNetworkServiceConfig_noProfileOwner() throws Exception {
+        assertExpectException(SecurityException.class, null,
+                () -> dpm.setPreferentialNetworkServiceConfig(
+                        PreferentialNetworkServiceConfig.DEFAULT));
+    }
+
+    @Test
+    public void testIsPreferentialNetworkServiceEnabled_noProfileOwner() throws Exception {
+        assertExpectException(SecurityException.class, null,
+                () -> dpm.isPreferentialNetworkServiceEnabled());
+    }
+
+    @Test
+    public void testSetPreferentialNetworkServiceConfig_invalidConfig() throws Exception {
+        final int managedProfileUserId = 15;
+        final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+        addManagedProfile(admin1, managedProfileAdminUid, admin1);
+        mContext.binder.callingUid = managedProfileAdminUid;
+
+        PreferentialNetworkServiceConfig.Builder preferentialNetworkServiceConfigBuilder =
+                new PreferentialNetworkServiceConfig.Builder();
+        assertExpectException(NullPointerException.class, null,
+                () -> preferentialNetworkServiceConfigBuilder.setIncludedUids(null));
+        assertExpectException(NullPointerException.class, null,
+                () -> preferentialNetworkServiceConfigBuilder.setExcludedUids(null));
+        assertExpectException(IllegalArgumentException.class, null,
+                () -> preferentialNetworkServiceConfigBuilder.setNetworkId(6));
+        int[] includedUids = new int[]{1, 2};
+        int[] excludedUids = new int[]{3, 4};
+        preferentialNetworkServiceConfigBuilder.setIncludedUids(includedUids);
+        preferentialNetworkServiceConfigBuilder.setExcludedUids(excludedUids);
+
+        assertExpectException(IllegalStateException.class, null,
+                () -> preferentialNetworkServiceConfigBuilder.build());
+    }
+
+    @Test
+    public void testSetPreferentialNetworkServiceConfig_defaultPreference() throws Exception {
+        final int managedProfileUserId = 15;
+        final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+        addManagedProfile(admin1, managedProfileAdminUid, admin1);
+        mContext.binder.callingUid = managedProfileAdminUid;
+
+        dpm.setPreferentialNetworkServiceConfig(PreferentialNetworkServiceConfig.DEFAULT);
+        assertThat(dpm.isPreferentialNetworkServiceEnabled()).isFalse();
+        assertThat(dpm.getPreferentialNetworkServiceConfig()
+                .isEnabled()).isFalse();
+
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT)
+                        .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                        null, null);
+    }
+
+    @Test
+    public void testSetPreferentialNetworkServiceConfig_enterprisePreference() throws Exception {
+        PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
+                (new PreferentialNetworkServiceConfig.Builder())
+                        .setEnabled(true)
+                        .setNetworkId(NET_ENTERPRISE_ID_1)
+                        .build();
+
+        final int managedProfileUserId = 15;
+        final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+        addManagedProfile(admin1, managedProfileAdminUid, admin1);
+        mContext.binder.callingUid = managedProfileAdminUid;
+
+        dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled);
+        assertThat(dpm.getPreferentialNetworkServiceConfig()
+                .isEnabled()).isTrue();
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE)
+                        .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+                        .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                        null, null);
+    }
+
+    @Test
+    public void testSetPreferentialNetworkServiceConfig_enterprisePreferenceIncludedUids()
+            throws Exception {
+        final int managedProfileUserId = 15;
+        final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+        addManagedProfile(admin1, managedProfileAdminUid, admin1);
+        mContext.binder.callingUid = managedProfileAdminUid;
+
+        PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
+                (new PreferentialNetworkServiceConfig.Builder())
+                        .setEnabled(true)
+                        .setNetworkId(NET_ENTERPRISE_ID_1)
+                        .setFallbackToDefaultConnectionAllowed(false)
+                        .setIncludedUids(new int[]{1, 2})
+                        .build();
+        dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled);
+        assertThat(dpm.getPreferentialNetworkServiceConfig()
+                .isEnabled()).isTrue();
+        List<Integer> includedList = new ArrayList<>();
+        includedList.add(1);
+        includedList.add(2);
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK)
+                        .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+                        .setIncludedUids(includedList)
+                        .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                        null, null);
+    }
+
+    @Test
+    public void testSetPreferentialNetworkServiceConfig_enterprisePreferenceExcludedUids()
+            throws Exception {
+        final int managedProfileUserId = 15;
+        final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+        addManagedProfile(admin1, managedProfileAdminUid, admin1);
+        mContext.binder.callingUid = managedProfileAdminUid;
+
+        PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
+                (new PreferentialNetworkServiceConfig.Builder())
+                        .setEnabled(true)
+                        .setNetworkId(NET_ENTERPRISE_ID_1)
+                        .setFallbackToDefaultConnectionAllowed(false)
+                        .setExcludedUids(new int[]{1, 2})
+                        .build();
+
+        dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled);
+        assertThat(dpm.getPreferentialNetworkServiceConfig()
+                .isEnabled()).isTrue();
+        List<Integer> excludedUids = new ArrayList<>();
+        excludedUids.add(1);
+        excludedUids.add(2);
+        ProfileNetworkPreference preferenceDetails =
+                new ProfileNetworkPreference.Builder()
+                        .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK)
+                        .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+                        .setExcludedUids(excludedUids)
+                        .build();
+        List<ProfileNetworkPreference> preferences = new ArrayList<>();
+        preferences.clear();
+        preferences.add(preferenceDetails);
+        verify(getServices().connectivityManager, times(1))
+                .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+                        null, null);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 01bd04c..77e49ad 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -43,6 +43,7 @@
 import android.hardware.hdmi.HdmiPortInfo;
 import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
 import android.hardware.hdmi.IHdmiControlStatusChangeListener;
+import android.hardware.hdmi.IHdmiVendorCommandListener;
 import android.os.Binder;
 import android.os.IPowerManager;
 import android.os.IThermalService;
@@ -886,6 +887,117 @@
     }
 
     @Test
+    public void addVendorCommandListener_receiveCallback_VendorCmdNoIdTest() {
+        int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
+        int sourceAddress = Constants.ADDR_TV;
+        byte[] params = {0x00, 0x01, 0x02, 0x03};
+        int vendorId = 0x123456;
+        mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+
+        VendorCommandListener vendorCmdListener =
+                new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
+        mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage vendorCommandNoId =
+                HdmiCecMessageBuilder.buildVendorCommand(sourceAddress, destAddress, params);
+        mNativeWrapper.onCecMessage(vendorCommandNoId);
+        mTestLooper.dispatchAll();
+        assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue();
+        assertThat(vendorCmdListener.mParamsCorrect).isTrue();
+        assertThat(vendorCmdListener.mHasVendorId).isFalse();
+    }
+
+    @Test
+    public void addVendorCommandListener_receiveCallback_VendorCmdWithIdTest() {
+        int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
+        int sourceAddress = Constants.ADDR_TV;
+        byte[] params = {0x00, 0x01, 0x02, 0x03};
+        int vendorId = 0x123456;
+        mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+
+        VendorCommandListener vendorCmdListener =
+                new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
+        mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage vendorCommandWithId =
+                HdmiCecMessageBuilder.buildVendorCommandWithId(
+                        sourceAddress, destAddress, vendorId, params);
+        mNativeWrapper.onCecMessage(vendorCommandWithId);
+        mTestLooper.dispatchAll();
+        assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue();
+        assertThat(vendorCmdListener.mParamsCorrect).isTrue();
+        assertThat(vendorCmdListener.mHasVendorId).isTrue();
+    }
+
+    @Test
+    public void addVendorCommandListener_noCallback_VendorCmdDiffIdTest() {
+        int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
+        int sourceAddress = Constants.ADDR_TV;
+        byte[] params = {0x00, 0x01, 0x02, 0x03};
+        int vendorId = 0x123456;
+        int diffVendorId = 0x345678;
+        mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+
+        VendorCommandListener vendorCmdListener =
+                new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
+        mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
+        mTestLooper.dispatchAll();
+
+        HdmiCecMessage vendorCommandWithDiffId =
+                HdmiCecMessageBuilder.buildVendorCommandWithId(
+                        sourceAddress, destAddress, diffVendorId, params);
+        mNativeWrapper.onCecMessage(vendorCommandWithDiffId);
+        mTestLooper.dispatchAll();
+        assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isFalse();
+    }
+
+    private static class VendorCommandListener extends IHdmiVendorCommandListener.Stub {
+        boolean mVendorCommandCallbackReceived = false;
+        boolean mParamsCorrect = false;
+        boolean mHasVendorId = false;
+
+        int mSourceAddress;
+        int mDestAddress;
+        byte[] mParams;
+        int mVendorId;
+
+        VendorCommandListener(int sourceAddress, int destAddress, byte[] params, int vendorId) {
+            this.mSourceAddress = sourceAddress;
+            this.mDestAddress = destAddress;
+            this.mParams = params.clone();
+            this.mVendorId = vendorId;
+        }
+
+        @Override
+        public void onReceived(
+                int sourceAddress, int destAddress, byte[] params, boolean hasVendorId) {
+            mVendorCommandCallbackReceived = true;
+            if (mSourceAddress == sourceAddress && mDestAddress == destAddress) {
+                byte[] expectedParams;
+                if (hasVendorId) {
+                    // If the command has vendor ID, we have to add it to mParams.
+                    expectedParams = new byte[params.length];
+                    expectedParams[0] = (byte) ((mVendorId >> 16) & 0xFF);
+                    expectedParams[1] = (byte) ((mVendorId >> 8) & 0xFF);
+                    expectedParams[2] = (byte) (mVendorId & 0xFF);
+                    System.arraycopy(mParams, 0, expectedParams, 3, mParams.length);
+                } else {
+                    expectedParams = params.clone();
+                }
+                if (Arrays.equals(expectedParams, params)) {
+                    mParamsCorrect = true;
+                }
+            }
+            mHasVendorId = hasVendorId;
+        }
+
+        @Override
+        public void onControlStateChanged(boolean enabled, int reason) {}
+    }
+
+    @Test
     public void dispatchMessageToLocalDevice_broadcastMessage_returnsHandled() {
         HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby(
                 Constants.ADDR_TV,
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index b811e28..94cf20f 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -49,15 +49,11 @@
 import static android.net.NetworkPolicyManager.uidPoliciesToString;
 import static android.net.NetworkPolicyManager.uidRulesToString;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
-import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.TAG_ALL;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkTemplate.buildTemplateCarrierMetered;
-import static android.net.NetworkTemplate.buildTemplateWifi;
-import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.net.NetworkTemplate.MATCH_CARRIER;
+import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_WIFI;
 import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
@@ -98,6 +94,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -108,6 +105,8 @@
 import android.app.IUidObserver;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.Context;
 import android.content.Intent;
@@ -125,8 +124,6 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkPolicy;
 import android.net.NetworkStateSnapshot;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.TelephonyNetworkSpecifier;
 import android.net.wifi.WifiInfo;
@@ -138,7 +135,6 @@
 import android.os.PowerSaveState;
 import android.os.RemoteException;
 import android.os.SimpleClock;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
@@ -208,6 +204,7 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
@@ -232,10 +229,12 @@
     private static final int TEST_SUB_ID = 42;
     private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS);
 
-
-    private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_WIFI_NETWORK_KEY);
+    private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI)
+            .setWifiNetworkKeys(Set.of(TEST_WIFI_NETWORK_KEY)).build();
     private static NetworkTemplate sTemplateCarrierMetered =
-            buildTemplateCarrierMetered(TEST_IMSI);
+            new NetworkTemplate.Builder(MATCH_CARRIER)
+                    .setSubscriberIds(Set.of(TEST_IMSI))
+                    .setMeteredness(METERED_YES).build();
 
     /**
      * Path on assets where files used by {@link NetPolicyXml} are located.
@@ -263,12 +262,13 @@
     private @Mock CarrierConfigManager mCarrierConfigManager;
     private @Mock TelephonyManager mTelephonyManager;
     private @Mock UserManager mUserManager;
+    private @Mock NetworkStatsManager mStatsManager;
+    private TestDependencies mDeps;
 
     private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
             ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
 
     private ActivityManagerInternal mActivityManagerInternal;
-    private NetworkStatsManagerInternal mStatsService;
 
     private IUidObserver mUidObserver;
     private INetworkManagementEventObserver mNetworkObserver;
@@ -335,8 +335,47 @@
                 .setBatterySaverEnabled(false).build();
         final PowerManagerInternal pmInternal = addLocalServiceMock(PowerManagerInternal.class);
         when(pmInternal.getLowPowerState(anyInt())).thenReturn(state);
+    }
 
-        mStatsService = addLocalServiceMock(NetworkStatsManagerInternal.class);
+    private class TestDependencies extends NetworkPolicyManagerService.Dependencies {
+        private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>();
+
+        TestDependencies(Context context) {
+            super(context);
+        }
+
+        @Override
+        long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
+            int total = 0;
+            for (int i = 0; i < mMockedStats.size(); i++) {
+                NetworkStats.Bucket bucket = mMockedStats.valueAt(i);
+                total += bucket.getRxBytes() + bucket.getTxBytes();
+            }
+            return total;
+        }
+
+        @Override
+        List<NetworkStats.Bucket> getNetworkUidBytes(NetworkTemplate template, long start,
+                long end) {
+            final List<NetworkStats.Bucket> ret = new ArrayList<>();
+            for (int i = 0; i < mMockedStats.size(); i++) {
+                ret.add(mMockedStats.valueAt(i));
+            }
+            return ret;
+        }
+
+        private void setMockedTotalBytes(int uid, long rxBytes, long txBytes) {
+            final NetworkStats.Bucket bucket = mock(NetworkStats.Bucket.class);
+            when(bucket.getUid()).thenReturn(uid);
+            when(bucket.getRxBytes()).thenReturn(rxBytes);
+            when(bucket.getTxBytes()).thenReturn(txBytes);
+            mMockedStats.set(uid, bucket);
+        }
+
+        private void increaseMockedTotalBytes(int uid, long rxBytes, long txBytes) {
+            final NetworkStats.Bucket bucket = mMockedStats.get(uid);
+            setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes);
+        }
     }
 
     @Before
@@ -376,6 +415,8 @@
                         return mConnManager;
                     case Context.USER_SERVICE:
                         return mUserManager;
+                    case Context.NETWORK_STATS_SERVICE:
+                        return mStatsManager;
                     default:
                         return super.getSystemService(name);
                 }
@@ -400,8 +441,9 @@
         }).when(mActivityManager).registerUidObserver(any(), anyInt(), anyInt(), any(String.class));
 
         mFutureIntent = newRestrictBackgroundChangedFuture();
+        mDeps = new TestDependencies(mServiceContext);
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
-                mNetworkManager, mIpm, mClock, mPolicyDir, true);
+                mNetworkManager, mIpm, mClock, mPolicyDir, true, mDeps);
         mService.bindConnectivityManager();
         mPolicyListener = new NetworkPolicyListenerAnswer(mService);
 
@@ -456,6 +498,15 @@
         verify(mNetworkManager).registerObserver(networkObserver.capture());
         mNetworkObserver = networkObserver.getValue();
 
+        // Catch UsageCallback during systemReady(). Simulate NetworkStatsService triggered
+        // stats updated callback to signal its readiness.
+        final ArgumentCaptor<NetworkStatsManager.UsageCallback> usageObserver =
+                ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class);
+        verify(mStatsManager, times(2))
+                .registerUsageCallback(any(), anyLong(), any(), usageObserver.capture());
+        usageObserver.getValue().onThresholdReached(
+                new NetworkTemplate.Builder(MATCH_MOBILE).build());
+
         NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, "");
         mDefaultWarningBytes = defaultPolicy.warningBytes;
         mDefaultLimitBytes = defaultPolicy.limitBytes;
@@ -479,7 +530,6 @@
         LocalServices.removeServiceForTest(DeviceIdleInternal.class);
         LocalServices.removeServiceForTest(AppStandbyInternal.class);
         LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
-        LocalServices.removeServiceForTest(NetworkStatsManagerInternal.class);
     }
 
     @After
@@ -1108,42 +1158,20 @@
         when(mConnManager.getAllNetworkStateSnapshots()).thenReturn(snapshots);
 
         // pretend that 512 bytes total have happened
-        stats = new NetworkStats(getElapsedRealtime(), 1)
-                .insertEntry(TEST_IFACE, 256L, 2L, 256L, 2L);
-        when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START, CYCLE_END))
-                .thenReturn(stats.getTotalBytes());
+        mDeps.setMockedTotalBytes(UID_A, 256L, 256L);
 
         mPolicyListener.expect().onMeteredIfacesChanged(any());
         setNetworkPolicies(new NetworkPolicy(
-                sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
+                sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, DataUnit.MEBIBYTES.toBytes(1),
+                DataUnit.MEBIBYTES.toBytes(2), false));
         mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
 
         verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
-                (2 * MB_IN_BYTES) - 512);
+                DataUnit.MEBIBYTES.toBytes(2) - 512);
     }
 
     @Test
     public void testNotificationWarningLimitSnooze() throws Exception {
-        // Create a place to store fake usage
-        final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
-        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
-                .thenAnswer(new Answer<Long>() {
-                    @Override
-                    public Long answer(InvocationOnMock invocation) throws Throwable {
-                        final NetworkStatsHistory.Entry entry = history.getValues(
-                                invocation.getArgument(1), invocation.getArgument(2), null);
-                        return entry.rxBytes + entry.txBytes;
-                    }
-                });
-        when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
-                .thenAnswer(new Answer<NetworkStats>() {
-                    @Override
-                    public NetworkStats answer(InvocationOnMock invocation) throws Throwable {
-                        return stats;
-                    }
-                });
-
         // Get active mobile network in place
         expectMobileDefaults();
         mService.updateNetworks();
@@ -1161,9 +1189,7 @@
 
         // Normal usage means no notification
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(360), 0);
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
@@ -1178,9 +1204,7 @@
 
         // Push over warning
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1799), 0L, 0L, 0L, 0));
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(1799), 0);
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
@@ -1196,9 +1220,7 @@
 
         // Push over warning, but with a config that isn't from an identified carrier
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1799), 0L, 0L, 0L, 0));
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(1799), 0);
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
@@ -1215,9 +1237,7 @@
 
         // Push over limit
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1810), 0L, 0L, 0L, 0));
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(1810), 0);
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
@@ -1235,7 +1255,7 @@
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
 
-            mService.snoozeLimit(NetworkTemplate.buildTemplateCarrierMetered(TEST_IMSI));
+            mService.snoozeLimit(sTemplateCarrierMetered);
             mService.updateNetworks();
 
             verify(tmSub, atLeastOnce()).setPolicyDataEnabled(true);
@@ -1248,26 +1268,6 @@
 
     @Test
     public void testNotificationRapid() throws Exception {
-        // Create a place to store fake usage
-        final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
-        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
-                .thenAnswer(new Answer<Long>() {
-                    @Override
-                    public Long answer(InvocationOnMock invocation) throws Throwable {
-                        final NetworkStatsHistory.Entry entry = history.getValues(
-                                invocation.getArgument(1), invocation.getArgument(2), null);
-                        return entry.rxBytes + entry.txBytes;
-                    }
-                });
-        when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
-                .thenAnswer(new Answer<NetworkStats>() {
-                    @Override
-                    public NetworkStats answer(InvocationOnMock invocation) throws Throwable {
-                        return stats;
-                    }
-                });
-
         // Get active mobile network in place
         expectMobileDefaults();
         mService.updateNetworks();
@@ -1285,9 +1285,7 @@
 
         // Using 20% data in 20% time is normal
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(360), 0);
 
             reset(mNotifManager);
             mService.updateNetworks();
@@ -1297,16 +1295,9 @@
         // Using 80% data in 20% time is alarming; but spread equally among
         // three UIDs means we get generic alert
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
-            stats.clear();
-            stats.insertEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
-                    DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
-            stats.insertEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
-                    DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
-            stats.insertEntry(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
-                    DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(480), 0);
+            mDeps.setMockedTotalBytes(UID_B, DataUnit.MEGABYTES.toBytes(480), 0);
+            mDeps.setMockedTotalBytes(UID_C, DataUnit.MEGABYTES.toBytes(480), 0);
 
             reset(mNotifManager);
             mService.updateNetworks();
@@ -1325,14 +1316,9 @@
         // Using 80% data in 20% time is alarming; but mostly done by one UID
         // means we get specific alert
         {
-            history.clear();
-            history.recordData(start, end,
-                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
-            stats.clear();
-            stats.insertEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
-                    DataUnit.MEGABYTES.toBytes(960), 0, 0, 0, 0);
-            stats.insertEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
-                    DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
+            mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(960), 0);
+            mDeps.setMockedTotalBytes(UID_B, DataUnit.MEGABYTES.toBytes(480), 0);
+            mDeps.setMockedTotalBytes(UID_C, 0, 0);
 
             reset(mNotifManager);
             mService.updateNetworks();
@@ -1362,13 +1348,10 @@
 
         // bring up wifi network with metered policy
         snapshots = List.of(buildWifi());
-        stats = new NetworkStats(getElapsedRealtime(), 1)
-                .insertEntry(TEST_IFACE, 0L, 0L, 0L, 0L);
+        mDeps.setMockedTotalBytes(UID_A, 0L, 0L);
 
         {
             when(mConnManager.getAllNetworkStateSnapshots()).thenReturn(snapshots);
-            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
-                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
 
             mPolicyListener.expect().onMeteredIfacesChanged(any());
             setNetworkPolicies(new NetworkPolicy(
@@ -1647,18 +1630,6 @@
         final NetworkPolicyManagerInternal internal = LocalServices
                 .getService(NetworkPolicyManagerInternal.class);
 
-        // Create a place to store fake usage
-        final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
-        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
-                .thenAnswer(invocation -> {
-                    final NetworkStatsHistory.Entry entry = history.getValues(
-                            invocation.getArgument(1), invocation.getArgument(2), null);
-                    return entry.rxBytes + entry.txBytes;
-                });
-        when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
-                .thenReturn(stats);
-
         // Get active mobile network in place
         expectMobileDefaults();
         mService.updateNetworks();
@@ -1669,9 +1640,7 @@
         setCurrentTimeMillis(end);
 
         // Get some data usage in place
-        history.clear();
-        history.recordData(start, end,
-                new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
+        mDeps.setMockedTotalBytes(UID_A, DataUnit.MEGABYTES.toBytes(360), 0);
 
         // No data plan
         {
@@ -1786,22 +1755,11 @@
                 true);
     }
 
-    private void increaseMockedTotalBytes(NetworkStats stats, long rxBytes, long txBytes) {
-        stats.insertEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
-                rxBytes, 1, txBytes, 1, 0);
-        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
-                .thenReturn(stats.getTotalBytes());
-        when(mStatsService.getNetworkUidBytes(any(), anyLong(), anyLong()))
-                .thenReturn(stats);
-    }
-
     private void triggerOnStatsProviderWarningOrLimitReached() throws InterruptedException {
-        final NetworkPolicyManagerInternal npmi = LocalServices
-                .getService(NetworkPolicyManagerInternal.class);
-        npmi.onStatsProviderWarningOrLimitReached("TEST");
+        mService.notifyStatsProviderWarningOrLimitReached();
         // Wait for processing of MSG_STATS_PROVIDER_WARNING_OR_LIMIT_REACHED.
         postMsgAndWaitForCompletion();
-        verify(mStatsService).forceUpdate();
+        verify(mStatsManager).forceUpdate();
         // Wait for processing of MSG_*_INTERFACE_QUOTAS.
         postMsgAndWaitForCompletion();
     }
@@ -1814,13 +1772,12 @@
     public void testStatsProviderWarningAndLimitReached() throws Exception {
         final int CYCLE_DAY = 15;
 
-        final NetworkStats stats = new NetworkStats(0L, 1);
-        increaseMockedTotalBytes(stats, 2999, 2000);
+        mDeps.setMockedTotalBytes(UID_A, 2999, 2000);
 
         // Get active mobile network in place
         expectMobileDefaults();
         mService.updateNetworks();
-        verify(mStatsService).setStatsProviderWarningAndLimitAsync(TEST_IFACE, Long.MAX_VALUE,
+        verify(mStatsManager).setStatsProviderWarningAndLimitAsync(TEST_IFACE, Long.MAX_VALUE,
                 Long.MAX_VALUE);
 
         // Set warning to 7KB and limit to 10KB.
@@ -1830,32 +1787,32 @@
         postMsgAndWaitForCompletion();
 
         // Verifies that remaining quotas are set to providers.
-        verify(mStatsService).setStatsProviderWarningAndLimitAsync(TEST_IFACE, 2001L, 5001L);
-        reset(mStatsService);
+        verify(mStatsManager).setStatsProviderWarningAndLimitAsync(TEST_IFACE, 2001L, 5001L);
+        reset(mStatsManager);
 
         // Increase the usage and simulates that limit reached fires earlier by provider,
         // but actually the quota is not yet reached. Verifies that the limit reached leads to
         // a force update and new quotas should be set.
-        increaseMockedTotalBytes(stats, 1000, 999);
+        mDeps.increaseMockedTotalBytes(UID_A, 1000, 999);
         triggerOnStatsProviderWarningOrLimitReached();
-        verify(mStatsService).setStatsProviderWarningAndLimitAsync(TEST_IFACE, 2L, 3002L);
-        reset(mStatsService);
+        verify(mStatsManager).setStatsProviderWarningAndLimitAsync(TEST_IFACE, 2L, 3002L);
+        reset(mStatsManager);
 
         // Increase the usage and simulate warning reached, the new warning should be unlimited
         // since service will disable warning quota to stop lower layer from keep triggering
         // warning reached event.
-        increaseMockedTotalBytes(stats, 1000L, 1000);
+        mDeps.increaseMockedTotalBytes(UID_A, 1000L, 1000);
         triggerOnStatsProviderWarningOrLimitReached();
-        verify(mStatsService).setStatsProviderWarningAndLimitAsync(
+        verify(mStatsManager).setStatsProviderWarningAndLimitAsync(
                 TEST_IFACE, Long.MAX_VALUE, 1002L);
-        reset(mStatsService);
+        reset(mStatsManager);
 
         // Increase the usage that over the warning and limit, the new limit should set to 1 to
         // block the network traffic.
-        increaseMockedTotalBytes(stats, 1000L, 1000);
+        mDeps.increaseMockedTotalBytes(UID_A, 1000L, 1000);
         triggerOnStatsProviderWarningOrLimitReached();
-        verify(mStatsService).setStatsProviderWarningAndLimitAsync(TEST_IFACE, Long.MAX_VALUE, 1L);
-        reset(mStatsService);
+        verify(mStatsManager).setStatsProviderWarningAndLimitAsync(TEST_IFACE, Long.MAX_VALUE, 1L);
+        reset(mStatsManager);
     }
 
     private void enableRestrictedMode(boolean enable) throws Exception {
@@ -2001,7 +1958,7 @@
         assertEquals("Unexpected number of network policies", 1, policies.length);
         NetworkPolicy actualPolicy = policies[0];
         assertEquals("Unexpected template match rule in network policies",
-                NetworkTemplate.MATCH_WIFI,
+                MATCH_WIFI,
                 actualPolicy.template.getMatchRule());
         assertEquals("Unexpected subscriberIds size in network policies",
                 actualPolicy.template.getSubscriberIds().size(), 0);
@@ -2072,7 +2029,10 @@
 
     private static NetworkPolicy buildFakeCarrierPolicy(int cycleDay, long warningBytes,
             long limitBytes, boolean inferred) {
-        final NetworkTemplate template = buildTemplateCarrierMetered(FAKE_SUBSCRIBER_ID);
+        // TODO: Refactor this to use sTemplateCarrierMetered.
+        final NetworkTemplate template = new NetworkTemplate.Builder(MATCH_CARRIER)
+                .setSubscriberIds(Set.of(FAKE_SUBSCRIBER_ID))
+                .setMeteredness(METERED_YES).build();
         return new NetworkPolicy(template, cycleDay, TimeZone.getDefault().getID(), warningBytes,
                 limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
     }
@@ -2099,7 +2059,7 @@
     private static NetworkStateSnapshot buildWifi() {
         WifiInfo mockWifiInfo = mock(WifiInfo.class);
         when(mockWifiInfo.makeCopy(anyLong())).thenReturn(mockWifiInfo);
-        when(mockWifiInfo.getCurrentNetworkKey()).thenReturn(TEST_WIFI_NETWORK_KEY);
+        when(mockWifiInfo.getNetworkKey()).thenReturn(TEST_WIFI_NETWORK_KEY);
         final LinkProperties prop = new LinkProperties();
         prop.setInterfaceName(TEST_IFACE);
         final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
@@ -2145,7 +2105,7 @@
     }
 
     private void verifyAdvisePersistThreshold() throws Exception {
-        verify(mStatsService).advisePersistThreshold(anyLong());
+        verify(mStatsManager).setDefaultGlobalAlert(anyLong());
     }
 
     private static class TestAbstractFuture<T> extends AbstractFuture<T> {
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index 26b34fd..304fe5a 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -30,6 +30,7 @@
 import android.hardware.power.stats.State;
 import android.hardware.power.stats.StateResidency;
 import android.hardware.power.stats.StateResidencyResult;
+import android.os.Looper;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -145,12 +146,12 @@
         }
 
         @Override
-        PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
-                String meterFilename, String meterCacheFilename,
+        PowerStatsLogger createPowerStatsLogger(Context context, Looper looper,
+                File dataStoragePath, String meterFilename, String meterCacheFilename,
                 String modelFilename, String modelCacheFilename,
                 String residencyFilename, String residencyCacheFilename,
                 IPowerStatsHALWrapper powerStatsHALWrapper) {
-            mPowerStatsLogger = new PowerStatsLogger(context, dataStoragePath,
+            mPowerStatsLogger = new PowerStatsLogger(context, looper, dataStoragePath,
                 meterFilename, meterCacheFilename,
                 modelFilename, modelCacheFilename,
                 residencyFilename, residencyCacheFilename,
diff --git a/services/tests/servicestests/src/com/android/server/wm/OWNERS b/services/tests/servicestests/src/com/android/server/wm/OWNERS
new file mode 100644
index 0000000..361760d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 6f04f17..29fa2d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -37,6 +37,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.os.Process.NOBODY_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.InsetsState.ITYPE_IME;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -127,6 +128,8 @@
 import android.view.IRemoteAnimationRunner.Stub;
 import android.view.IWindowManager;
 import android.view.IWindowSession;
+import android.view.InsetsSource;
+import android.view.InsetsState;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 import android.view.Surface;
@@ -2884,6 +2887,41 @@
         assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
     }
 
+    @UseTestDisplay(addWindows = W_INPUT_METHOD)
+    @Test
+    public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+
+        InsetsSource imeSource = new InsetsSource(ITYPE_IME);
+        app.getInsetsState().addSource(imeSource);
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.updateImeInputAndControlTarget(app);
+
+        InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
+        assertFalse(state.getSource(ITYPE_IME).isVisible());
+        assertTrue(state.getSource(ITYPE_IME).getFrame().isEmpty());
+
+        // Simulate app is closing and expect IME insets is frozen.
+        mDisplayContent.mOpeningApps.clear();
+        app.mActivityRecord.commitVisibility(false, false);
+        app.mActivityRecord.onWindowsGone();
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Simulate app re-start input or turning screen off/on then unlocked by un-secure
+        // keyguard to back to the app, expect IME insets is not frozen
+        imeSource.setFrame(new Rect(100, 400, 500, 500));
+        app.getInsetsState().addSource(imeSource);
+        app.getInsetsState().setSourceVisible(ITYPE_IME, true);
+        mDisplayContent.updateImeInputAndControlTarget(app);
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Verify when IME is visible and the app can receive the right IME insets from policy.
+        makeWindowVisibleAndDrawn(app, mImeWindow);
+        state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
+        assertTrue(state.getSource(ITYPE_IME).isVisible());
+        assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
+    }
+
     private void assertHasStartingWindow(ActivityRecord atoken) {
         assertNotNull(atoken.mStartingSurface);
         assertNotNull(atoken.mStartingData);
diff --git a/services/translation/OWNERS b/services/translation/OWNERS
index a1e663a..440f9a8 100644
--- a/services/translation/OWNERS
+++ b/services/translation/OWNERS
@@ -1,8 +1,3 @@
 # Bug component: 994311
 
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include /core/java/android/view/translation/OWNERS
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8cb0909..21f789f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -492,6 +492,7 @@
 
         // current USB state
         private boolean mHostConnected;
+        private boolean mUsbAccessoryConnected;
         private boolean mSourcePower;
         private boolean mSinkPower;
         private boolean mConfigured;
@@ -961,10 +962,10 @@
                     break;
                 case MSG_UPDATE_HOST_STATE:
                     Iterator devices = (Iterator) msg.obj;
-                    boolean connected = (msg.arg1 == 1);
+                    mUsbAccessoryConnected = (msg.arg1 == 1);
 
                     if (DEBUG) {
-                        Slog.i(TAG, "HOST_STATE connected:" + connected);
+                        Slog.i(TAG, "HOST_STATE connected:" + mUsbAccessoryConnected);
                     }
 
                     mHideUsbNotification = false;
@@ -1218,7 +1219,7 @@
             } else if (mSourcePower) {
                 titleRes = com.android.internal.R.string.usb_supplying_notification_title;
                 id = SystemMessage.NOTE_USB_SUPPLYING;
-            } else if (mHostConnected && mSinkPower && mUsbCharging) {
+            } else if (mHostConnected && mSinkPower && (mUsbCharging || mUsbAccessoryConnected)) {
                 titleRes = com.android.internal.R.string.usb_charging_notification_title;
                 id = SystemMessage.NOTE_USB_CHARGING;
             }
diff --git a/services/wallpapereffectsgeneration/OWNERS b/services/wallpapereffectsgeneration/OWNERS
new file mode 100644
index 0000000..d2d3e2c0
--- /dev/null
+++ b/services/wallpapereffectsgeneration/OWNERS
@@ -0,0 +1,4 @@
+susharon@google.com
+shanh@google.com
+huiwu@google.com
+srazdan@google.com
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 1252965..9a991a1 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -107,6 +107,25 @@
         }
     }
 
+    /**
+     * Convenience method for running the provided action in the provided
+     * executor enclosed in
+     * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity}
+     *
+     * Any exception thrown by the given action will need to be handled by caller.
+     *
+     */
+    public static void runWithCleanCallingIdentity(
+            @NonNull Runnable action, @NonNull Executor executor) {
+        if (action != null) {
+            if (executor != null) {
+                executor.execute(() -> runWithCleanCallingIdentity(action));
+            } else {
+                runWithCleanCallingIdentity(action);
+            }
+        }
+    }
+
 
     /**
      * Convenience method for running the provided action enclosed in
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b109c46..8d3eee0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -168,7 +168,10 @@
     /**
      * This flag specifies whether VoLTE availability is based on provisioning. By default this is
      * false.
+     * Used for UCE to determine if EAB provisioning checks should be based on provisioning.
+     * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead.
      */
+    @Deprecated
     public static final String
             KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
 
@@ -349,6 +352,12 @@
             KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
 
     /**
+     * Flag indicating if the carrier supports tethering of mobile data.
+     */
+    public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL =
+            "carrier_supports_tethering_bool";
+
+    /**
      * Flag indicating whether radio is to be restarted on error PDP_FAIL_REGULAR_DEACTIVATION
      * This is false by default.
      *
@@ -858,7 +867,12 @@
     /**
      * Flag specifying whether provisioning is required for VoLTE, Video Telephony, and WiFi
      * Calling.
+
+     * Combines VoLTE, VT, VoWiFI calling provisioning into one parameter.
+     * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for
+     * finer-grained control.
      */
+    @Deprecated
     public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
             = "carrier_volte_provisioning_required_bool";
 
@@ -872,7 +886,11 @@
      * and enable the UT over IMS capability for the subscription when the subscription is loaded.
      *
      * The default value for this key is {@code false}.
+     *
+     * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for
+     * determining if UT requires provisioning.
      */
+    @Deprecated
     public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL =
             "carrier_ut_provisioning_required_bool";
 
@@ -2459,6 +2477,10 @@
      *
      * Note: If {@code *} is specified for the original code, any ImsReasonInfo with the matching
      * {@code MESSAGE} will be remapped to {@code NEW_CODE}.
+     * If {@code *} is specified for the message, any ImsReasonInfo with the matching
+     * {@code ORIGINAL_CODE} will be remapped to {@code NEW_CODE}.
+     * The wildcard for {@code ORIGINAL_CODE} takes precedence to the wildcard for {@code MESSAGE}.
+     * A mapping with both wildcards has no effect.
      *
      * Example: "501|call completion elsewhere|1014"
      * When the {@link ImsReasonInfo#getCode()} is {@link ImsReasonInfo#CODE_USER_TERMINATED} and
@@ -3701,7 +3723,7 @@
     /**
      * SMDP+ server address for downloading opportunistic eSIM profile.
      * FQDN (Fully Qualified Domain Name) of the SM-DP+ (e.g., smdp.gsma.com) restricted to the
-     * Alphanumeric mode character set defined in table 5 of ISO/IEC 18004 [15] excluding '$'.
+     * Alphanumeric mode character set defined in table 5 of ISO/IEC 18004 excluding '$'.
      */
     public static final String KEY_SMDP_SERVER_ADDRESS_STRING =
             "smdp_server_address_string";
@@ -3745,6 +3767,17 @@
             "opportunistic_carrier_ids_int_array";
 
     /**
+     * Boolean configuration to control auto provisioning eSIM download in
+     * OpportunisticNetworkService using only WiFi or both WiFi/Data.
+     * True will download esim only via WiFi.
+     * False will use both WiFi and Data connection.
+     *
+     * @hide
+     */
+    public static final String KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL =
+            "opportunistic_esim_download_via_wifi_only_bool";
+
+    /**
      * Controls RSRP threshold at which OpportunisticNetworkService will decide whether
      * the opportunistic network is good enough for internet data.
      */
@@ -3851,101 +3884,242 @@
     public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG =
             "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";
+    /** @hide */
+    public static class OpportunisticNetwork {
+        /**
+         * Prefix of all {@code OpportunisticNetwork.KEY_*} constants.
+         *
+         * @hide
+         */
+        public static final String PREFIX = "opportunistic.";
 
-    /**
-    * 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 at which 5G opportunistic network will be considered
+         * good enough for internet data. Note other factors may be considered for the final
+         * decision.
+         *
+         * <p>The value of {@link CellSignalStrengthNr#getSsRsrp} will be compared with this
+         * threshold.
+         *
+         * @hide
+         */
+        public static final String KEY_ENTRY_THRESHOLD_SS_RSRP_INT =
+                PREFIX + "entry_threshold_ss_rsrp_int";
 
-    /**
-    * 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";
+        /**
+         * Similar to {@link #KEY_ENTRY_THRESHOLD_SS_RSRP_INT} but supports different
+         * thresholds for different 5G bands. For bands not specified here, the threshold
+         * will be {@link #KEY_ENTRY_THRESHOLD_SS_RSRP_INT}.
+         *
+         * <p>For each key-value in the bundle: the key is the band number in string, which
+         * shall be a decimal integer as defined in {@code NgranBands.BAND_*} constants;
+         * the value is the threshold in int.
+         *
+         * @hide
+         */
+        public static final String KEY_ENTRY_THRESHOLD_SS_RSRP_INT_BUNDLE =
+                PREFIX + "entry_threshold_ss_rsrp_int_bundle";
 
-    /**
-    * 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 SS-RSRQ threshold in dB at which 5G opportunistic network will be considered
+         * good enough for internet data. Note other factors may be considered for the final
+         * decision.
+         *
+         * <p>The value of {@link CellSignalStrengthNr#getSsRsrq} will be compared with this
+         * threshold.
+         *
+         * @hide
+         */
+        public static final String KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE =
+                PREFIX + "entry_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";
+        /**
+         * Similar to {@link #KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE} but supports different
+         * thresholds for different 5G bands. For bands not specified here, the threshold
+         * will be {@link #KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE}.
+         *
+         * <p>For each key-value in the bundle: the key is the band number in string, which
+         * shall be a decimal integer as defined in {@code NgranBands.BAND_*} constants;
+         * the value is the threshold in double.
+         *
+         * @hide
+         */
+        public static final String KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE =
+                PREFIX + "entry_threshold_ss_rsrq_double_bundle";
 
-    /**
-     * 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 SS-RSRP threshold in dBm below which 5G opportunistic network available will not
+         * be considered good enough for internet data. Note other factors may be considered
+         * for the final decision.
+         *
+         * @hide
+         */
+        public static final String KEY_EXIT_THRESHOLD_SS_RSRP_INT =
+                PREFIX + "exit_threshold_ss_rsrp_int";
 
-    /**
-    * 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";
+        /**
+         * Similar to {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT} but supports different
+         * thresholds for different 5G bands. For bands not specified here, the threshold
+         * will be {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT}.
+         *
+         * <p>The syntax of its value is similar to
+         * {@link #KEY_ENTRY_THRESHOLD_SS_RSRP_INT_BUNDLE}.
+         *
+         * @hide
+         */
+        public static final String KEY_EXIT_THRESHOLD_SS_RSRP_INT_BUNDLE =
+                PREFIX + "exit_threshold_ss_rsrp_int_bundle";
 
-    /**
-     * 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 SS-RSRQ threshold in dB below which 5G opportunistic network available will not
+         * be considered good enough for internet data. Note other factors may be considered
+         * for the final decision.
+         *
+         * @hide
+         */
+        public static final String KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE =
+                PREFIX + "exit_threshold_ss_rsrq_double";
 
-    /**
-     * 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";
+        /**
+         * Similar to {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE} but supports different
+         * thresholds for different 5G bands. For bands not specified here, the threshold
+         * will be {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE}.
+         *
+         * <p>The syntax of its value is similar to
+         * {@link #KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE}.
+         *
+         * @hide
+         */
+        public static final String KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE =
+                PREFIX + "exit_threshold_ss_rsrq_double_bundle";
+
+        /**
+         * Controls hysteresis time in milliseconds for which will be waited before switching
+         * data to a 5G opportunistic network.
+         *
+         * @hide
+         */
+        public static final String KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG =
+                PREFIX + "5g_data_switch_hysteresis_time_long";
+
+        /**
+         * Similar to {@link #KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} but supports
+         * different values for different 5G bands. For bands not specified here, the threshold
+         * will be {@link #KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG}.
+         *
+         * <p>For each key-value in the bundle: the key is the band number in string, which
+         * shall be a decimal integer as defined in {@code NgranBands.BAND_*} constants;
+         * the value is the time in long.
+         *
+         * @hide
+         */
+        public static final String KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG_BUNDLE =
+                PREFIX + "5g_data_switch_hysteresis_time_long_bundle";
+
+        /**
+         * 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_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG =
+                PREFIX + "5g_data_switch_exit_hysteresis_time_long";
+
+        /**
+         * Similar to {@link #KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG} but supports
+         * different values for different 5G bands. For bands not specified here, the threshold
+         * will be {@link #KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG}.
+         *
+         * <p>The syntax is similar to
+         * {@link KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG_BUNDLE}.
+         *
+         * @hide
+         */
+        public static final String KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG_BUNDLE =
+                PREFIX + "5g_data_switch_exit_hysteresis_time_long_bundle";
+
+        /**
+         * Controls back off time in milliseconds for switching back to
+         * 5G opportunistic subscription. This time will be added to
+         * {@link #KEY_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
+         * {@link #KEY_5G_PING_PONG_TIME_LONG}.
+         * If ping pong situation continuous {@link #KEY_5G_NETWORK_BACKOFF_TIME_LONG}
+         * will be added to previously determined hysteresis time.
+         *
+         * @hide
+         */
+        public static final String KEY_5G_BACKOFF_TIME_LONG =
+                PREFIX + "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
+         * {@link #KEY_5G_PING_PONG_TIME_LONG} and
+         * {@link #KEY_5G_BACKOFF_TIME_LONG}.
+         *
+         * @hide
+         */
+        public static final String KEY_5G_MAX_BACKOFF_TIME_LONG =
+                PREFIX + "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
+         * {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT} or
+         * {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE} within
+         * {@link #KEY_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_5G_PING_PONG_TIME_LONG =
+                PREFIX + "5g_ping_pong_time_long";
+
+        private static PersistableBundle getDefaults() {
+            PersistableBundle defaults = new PersistableBundle();
+            // Default value is -111 dBm for all bands.
+            sDefaults.putInt(KEY_ENTRY_THRESHOLD_SS_RSRP_INT, -111);
+            sDefaults.putPersistableBundle(KEY_ENTRY_THRESHOLD_SS_RSRP_INT_BUNDLE,
+                                           PersistableBundle.EMPTY);
+            // Default value is -18.5 dB for all bands.
+            sDefaults.putDouble(KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
+            sDefaults.putPersistableBundle(
+                    KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE,
+                    PersistableBundle.EMPTY);
+            // Default value is -120 dBm for all bands.
+            sDefaults.putInt(KEY_EXIT_THRESHOLD_SS_RSRP_INT, -120);
+            sDefaults.putPersistableBundle(KEY_EXIT_THRESHOLD_SS_RSRP_INT_BUNDLE,
+                                           PersistableBundle.EMPTY);
+            // Default value is -18.5 dB for all bands.
+            sDefaults.putDouble(KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
+            sDefaults.putPersistableBundle(
+                    KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE,
+                    PersistableBundle.EMPTY);
+            // Default value is 2 seconds for all bands.
+            defaults.putLong(KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG, 2000);
+            defaults.putPersistableBundle(
+                    KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG_BUNDLE,
+                    PersistableBundle.EMPTY);
+            // Default value is 2 seconds for all bands.
+            defaults.putLong(KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000);
+            defaults.putPersistableBundle(
+                    KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG_BUNDLE,
+                    PersistableBundle.EMPTY);
+            // Default value is 10 seconds.
+            sDefaults.putLong(KEY_5G_BACKOFF_TIME_LONG, 10000);
+            // Default value is 60 seconds.
+            sDefaults.putLong(KEY_5G_MAX_BACKOFF_TIME_LONG, 60000);
+            // Default value is 60 seconds.
+            sDefaults.putLong(KEY_5G_PING_PONG_TIME_LONG, 60000);
+            return defaults;
+        }
+    }
+
     /**
      * Controls whether 4G opportunistic networks should be scanned for possible data switch.
      *
@@ -4398,12 +4572,10 @@
             "carrier_auto_cancel_cs_notification";
 
     /**
-     * Passing this value as {@link KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the
+     * Passing this value as {@link #KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the
      * subscription from a group instead of adding it to a group.
      *
-     * TODO: Expose in a future release.
-     *
-     * @hide
+     * <p>This value will work all the way back to {@link android.os.Build.VERSION_CODES#Q}.
      */
     public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000";
 
@@ -4416,9 +4588,7 @@
      * <p>If set to {@link #REMOVE_GROUP_UUID_STRING}, then the subscription will be removed from
      * its current group.
      *
-     * TODO: unhide this key.
-     *
-     * @hide
+     * <p>This key will work all the way back to {@link android.os.Build.VERSION_CODES#Q}.
      */
     public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING =
             "subscription_group_uuid_string";
@@ -4443,17 +4613,15 @@
             "data_switch_validation_min_gap_long";
 
     /**
-    * A boolean property indicating whether this subscription should be managed as an opportunistic
-    * subscription.
-    *
-    * If true, then this subscription will be selected based on available coverage and will not be
-    * available for a user in settings menus for selecting macro network providers. If unset,
-    * defaults to “false”.
-    *
-    * TODO: unhide this key.
-    *
-    * @hide
-    */
+     * A boolean property indicating whether this subscription should be managed as an opportunistic
+     * subscription.
+     *
+     * If true, then this subscription will be selected based on available coverage and will not be
+     * available for a user in settings menus for selecting macro network providers. If unset,
+     * defaults to “false”.
+     *
+     * <p>This key will work all the way back to {@link android.os.Build.VERSION_CODES#Q}.
+     */
     public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL =
             "is_opportunistic_subscription_bool";
 
@@ -4592,6 +4760,15 @@
                 KEY_PREFIX + "enable_presence_group_subscribe_bool";
 
         /**
+         * Flag indicating whether or not to use SIP URI when send a presence subscribe.
+         * When {@code true}, the device sets the To and Contact header to be SIP URI using
+         * the TelephonyManager#getIsimDomain" API.
+         * If {@code false}, the device uses a TEL URI.
+         */
+        public static final String KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL =
+                KEY_PREFIX + "use_sip_uri_for_presence_subscribe_bool";
+
+        /**
          * An integer key associated with the period of time in seconds the non-rcs capability
          * information of each contact is cached on the device.
          * <p>
@@ -4633,6 +4810,134 @@
         public static final String KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG =
                 KEY_PREFIX + "rcs_request_retry_interval_millis_long";
 
+        /**
+         * A bundle which specifies the MMTEL capability and registration technology
+         * that requires provisioning. If a tuple is not present, the
+         * framework will not require that the tuple requires provisioning before
+         * enabling the capability.
+         * <p> Possible keys in this bundle are
+         * <ul>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_UT_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_SMS_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY}</li>
+         * </ul>
+         * <p> The values are defined in
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+         */
+        public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE =
+                KEY_PREFIX + "mmtel_requires_provisioning_bundle";
+
+        /**
+         * List of different RAT technologies on which Provisioning for Voice calling (IR.92)
+         * is supported.
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY =
+                KEY_PREFIX + "capability_type_voice_int_array";
+
+        /**
+         * List of different RAT technologies on which Provisioning for Video Telephony (IR.94)
+         * is supported.
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY =
+                KEY_PREFIX + "capability_type_video_int_array";
+
+        /**
+         * List of different RAT technologies on which Provisioning for XCAP over Ut for
+         * supplementary services. (IR.92) is supported.
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY =
+                KEY_PREFIX + "capability_type_ut_int_array";
+
+        /**
+         * List of different RAT technologies on which Provisioning for SMS (IR.92) is supported.
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY =
+                KEY_PREFIX + "capability_type_sms_int_array";
+
+        /**
+         * List of different RAT technologies on which Provisioning for Call Composer
+         * (section 2.4 of RCC.20) is supported.
+         * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_CALL_COMPOSER
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY =
+                KEY_PREFIX + "capability_type_call_composer_int_array";
+
+        /**
+         * A bundle which specifies the RCS capability and registration technology
+         * that requires provisioning. If a tuple is not present, the
+         * framework will not require that the tuple requires provisioning before
+         * enabling the capability.
+         * <p> Possible keys in this bundle are
+         * <ul>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY}</li>
+         *     <li>{@link #KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY}</li>
+         * </ul>
+         * <p> The values are defined in
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+         */
+        public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE =
+                KEY_PREFIX + "rcs_requires_provisioning_bundle";
+
+        /**
+         * This carrier supports User Capability Exchange using SIP OPTIONS as defined by the
+         * framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS.
+         * If not set, this RcsFeature should not service capability requests.
+         * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY =
+                KEY_PREFIX + "capability_type_options_uce_int_array";
+
+        /**
+         * This carrier supports User Capability Exchange using a presence server as defined by the
+         * framework. If set, the RcsFeature should support capability exchange using a presence
+         * server. If not set, this RcsFeature should not publish capabilities or service capability
+         * requests using presence.
+         * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE
+         * <p>Possible values are,
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+         * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+         */
+        public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY =
+                KEY_PREFIX + "capability_type_presence_uce_int_array";
+
         private Ims() {}
 
         private static PersistableBundle getDefaults() {
@@ -4645,6 +4950,7 @@
             defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
             defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
             defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, false);
+            defaults.putBoolean(KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL, false);
             defaults.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 30 * 24 * 60 * 60);
             defaults.putBoolean(KEY_RCS_REQUEST_FORBIDDEN_BY_SIP_489_BOOL, false);
             defaults.putLong(KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG, 20 * 60 * 1000);
@@ -4669,6 +4975,17 @@
                     "+g.gsma.rcs.botversion=\"#=1,#=2\"",
                     "+g.gsma.rcs.cpimext"});
 
+            /**
+             * @see #KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
+             */
+            defaults.putPersistableBundle(
+                    KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE, new PersistableBundle());
+            /**
+             * @see #KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+             */
+            defaults.putPersistableBundle(
+                    KEY_RCS_REQUIRES_PROVISIONING_BUNDLE, new PersistableBundle());
+
             return defaults;
         }
     }
@@ -4724,7 +5041,7 @@
         /**
          * A priority list of ePDG addresses to be used. Possible values are {@link
          * #EPDG_ADDRESS_STATIC}, {@link #EPDG_ADDRESS_PLMN}, {@link #EPDG_ADDRESS_PCO}, {@link
-         * #EPDG_ADDRESS_CELLULAR_LOC}
+         * #EPDG_ADDRESS_CELLULAR_LOC}, {@link #EPDG_ADDRESS_VISITED_COUNTRY}
          */
         public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
                 KEY_PREFIX + "epdg_address_priority_int_array";
@@ -4879,6 +5196,10 @@
         /** Specifies the PCO id for IPv4 Epdg server address */
         public static final String KEY_EPDG_PCO_ID_IPV4_INT = KEY_PREFIX + "epdg_pco_id_ipv4_int";
 
+        /** Controls if the IKE tunnel setup supports EAP-AKA fast reauth */
+        public static final String KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL =
+                KEY_PREFIX + "supports_eap_aka_fast_reauth_bool";
+
         /** @hide */
         @IntDef({AUTHENTICATION_METHOD_EAP_ONLY, AUTHENTICATION_METHOD_CERT})
         public @interface AuthenticationMethodType {}
@@ -4899,7 +5220,8 @@
             EPDG_ADDRESS_STATIC,
             EPDG_ADDRESS_PLMN,
             EPDG_ADDRESS_PCO,
-            EPDG_ADDRESS_CELLULAR_LOC
+            EPDG_ADDRESS_CELLULAR_LOC,
+            EPDG_ADDRESS_VISITED_COUNTRY
         })
         public @interface EpdgAddressType {}
 
@@ -4913,6 +5235,8 @@
         public static final int EPDG_ADDRESS_PCO = 2;
         /** Use cellular location to chose epdg server */
         public static final int EPDG_ADDRESS_CELLULAR_LOC = 3;
+        /* Use Visited Country FQDN rule*/
+        public static final int EPDG_ADDRESS_VISITED_COUNTRY = 4;
 
         /** @hide */
         @IntDef({ID_TYPE_FQDN, ID_TYPE_RFC822_ADDR, ID_TYPE_KEY_ID})
@@ -5022,6 +5346,7 @@
             defaults.putBoolean(KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL, false);
             defaults.putInt(KEY_EPDG_PCO_ID_IPV6_INT, 0);
             defaults.putInt(KEY_EPDG_PCO_ID_IPV4_INT, 0);
+            defaults.putBoolean(KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL, false);
 
             return defaults;
         }
@@ -5409,6 +5734,7 @@
         sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
         sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false);
         sDefaults.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
+        sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
         sDefaults.putBoolean(KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL, false);
         sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[]{});
         sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
@@ -5803,6 +6129,7 @@
         sDefaults.putInt(KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 5);
         sDefaults.putInt(KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 60);
         sDefaults.putIntArray(KEY_OPPORTUNISTIC_CARRIER_IDS_INT_ARRAY, new int[] {0});
+        sDefaults.putBoolean(KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL, false);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
         sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_MODERATE */
@@ -5819,6 +6146,7 @@
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
         /* Default value is 3 seconds. */
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000);
+        sDefaults.putAll(OpportunisticNetwork.getDefaults());
         sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
         sDefaults.putBoolean(KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL, true);
         /* Default value is 60 seconds. */
@@ -5827,29 +6155,11 @@
         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.putInt(KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG, 60000);
-        sDefaults.putInt(
+        sDefaults.putLong(KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG, 60000L);
+        sDefaults.putLong(
                 KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG,
-                120000);
+                120000L);
         sDefaults.putAll(ImsServiceEntitlement.getDefaults());
         sDefaults.putAll(Gps.getDefaults());
         sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index fc76f99..6b9871c 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -160,6 +160,26 @@
         return new SipDelegateManager(mContext, subscriptionId, sRcsCache, sTelephonyCache);
     }
 
+
+    /**
+     * Create an instance of {@link ProvisioningManager} for the subscription id specified.
+     * <p>
+     * Provides a ProvisioningManager instance to carrier apps to update carrier provisioning
+     * information, as well as provides a callback so that apps can listen for changes
+     * in MMTEL/RCS provisioning
+     * @param subscriptionId The ID of the subscription that this ProvisioningManager will use.
+     * @throws IllegalArgumentException if the subscription is invalid.
+     * @return a ProvisioningManager instance with the specific subscription ID.
+     */
+    @NonNull
+    public ProvisioningManager getProvisioningManager(int subscriptionId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+            throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
+        }
+
+        return new ProvisioningManager(subscriptionId);
+    }
+
     private static IImsRcsController getIImsRcsControllerInterface() {
         return IImsRcsController.Stub.asInterface(
                 TelephonyFrameworkInitializer
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 846e6f3..9fd2ae4 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -767,6 +768,10 @@
      *
      * @return long name of operator, null if unregistered or unknown
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorAlphaLong() {
         return mOperatorAlphaLong;
     }
@@ -782,6 +787,10 @@
      * @return long name of operator
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorAlphaLong} instead.")
     public String getVoiceOperatorAlphaLong() {
@@ -800,6 +809,10 @@
      *
      * @return short name of operator, null if unregistered or unknown
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorAlphaShort() {
         return mOperatorAlphaShort;
     }
@@ -815,6 +828,10 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
     public String getVoiceOperatorAlphaShort() {
@@ -832,6 +849,10 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
     public String getDataOperatorAlphaShort() {
@@ -853,6 +874,10 @@
      * @return name of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorAlpha() {
         if (TextUtils.isEmpty(mOperatorAlphaLong)) {
             return mOperatorAlphaShort;
@@ -878,6 +903,10 @@
      * The country code can be decoded using
      * {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public String getOperatorNumeric() {
         return mOperatorNumeric;
     }
@@ -893,6 +922,10 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getVoiceOperatorNumeric() {
         return mOperatorNumeric;
@@ -909,6 +942,10 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
             publicAlternatives = "Use {@link #getOperatorNumeric} instead.")
     public String getDataOperatorNumeric() {
@@ -1758,8 +1795,17 @@
     /**
      * Get the CDMA NID (Network Identification Number), a number uniquely identifying a network
      * within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
+     *
+     * <p>Require at least {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. Otherwise return
+     * {@link #UNKNOWN_ID}.
+     *
      * @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public int getCdmaNetworkId() {
         return this.mNetworkId;
     }
@@ -1767,8 +1813,17 @@
     /**
      * Get the CDMA SID (System Identification Number), a number uniquely identifying a wireless
      * system. (Defined in 3GPP2 C.S0023 3.4.8)
+     *
+     * <p>Require at least {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. Otherwise return
+     * {@link #UNKNOWN_ID}.
+     *
      * @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_COARSE_LOCATION
+    })
     public int getCdmaSystemId() {
         return this.mSystemId;
     }
@@ -2069,6 +2124,8 @@
         state.mOperatorAlphaLong = null;
         state.mOperatorAlphaShort = null;
         state.mOperatorNumeric = null;
+        state.mSystemId = UNKNOWN_ID;
+        state.mNetworkId = UNKNOWN_ID;
 
         return state;
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f728324..4e32a55 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3820,6 +3820,11 @@
      * {@link #PHONE_NUMBER_SOURCE_UICC UICC} and decide if the previously set phone number
      * of source {@link #PHONE_NUMBER_SOURCE_CARRIER carrier} should be updated.
      *
+     * <p>The API provides no guarantees of what format the number is in: the format can vary
+     * depending on the {@code source} and the network etc. Programmatic parsing should be done
+     * cautiously, for example, after formatting the number to a consistent format with
+     * {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}.
+     *
      * <p>Note the assumption is that one subscription (which usually means one SIM) has
      * only one phone number. The multiple sources backup each other so hopefully at least one
      * is availavle. For example, for a carrier that doesn't typically set phone numbers
@@ -3878,6 +3883,11 @@
      * from available sources in the following order: {@link #PHONE_NUMBER_SOURCE_CARRIER}
      * > {@link #PHONE_NUMBER_SOURCE_UICC} > {@link #PHONE_NUMBER_SOURCE_IMS}.
      *
+     * <p>The API provides no guarantees of what format the number is in: the format can vary
+     * depending on the underlying source and the network etc. Programmatic parsing should be done
+     * cautiously, for example, after formatting the number to a consistent format with
+     * {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}.
+     *
      * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
      *                       for the default one.
      * @return the phone number, or an empty string if not available.
@@ -3916,6 +3926,9 @@
      * <p>The API is suitable for carrier apps to provide a phone number, for example when
      * it's not possible to update {@link #PHONE_NUMBER_SOURCE_UICC UICC} directly.
      *
+     * <p>It's recommended that the phone number is formatted to well-known formats,
+     * for example, by {@link PhoneNumberUtils} {@code formatNumber*} methods.
+     *
      * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
      *                       for the default one.
      * @param number the phone number, or an empty string to remove the previously set number.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9ac9d66..390ffc7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8765,7 +8765,8 @@
      * @param allowedNetworkTypes The bitmask of allowed network types.
      * @return true on success; false on any failure.
      * @hide
-     * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead.
+     * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead with reason
+     * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}.
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -8799,10 +8800,7 @@
 
     /**
      * To indicate allowed network type change is requested by user.
-     *
-     * @hide
      */
-    @SystemApi
     public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0;
 
     /**
@@ -8821,10 +8819,7 @@
      * Carrier configuration won't affect the settings configured through
      * other reasons and will result in allowing network types that are in both
      * configurations (i.e intersection of both sets).
-     *
-     * @hide
      */
-    @SystemApi
     public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2;
 
     /**
@@ -8838,35 +8833,23 @@
     /**
      * Set the allowed network types of the device and provide the reason triggering the allowed
      * network change.
+     * <p>Requires permission: android.Manifest.MODIFY_PHONE_STATE or
+     * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * This can be called for following reasons
      * <ol>
      * <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER}
-     * <li>Allowed network types control by power manager
-     * {@link #ALLOWED_NETWORK_TYPES_REASON_POWER}
      * <li>Allowed network types control by carrier {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}
-     * <li>Allowed network types control by the user-controlled "Allow 2G" toggle
-     * {@link #ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}
      * </ol>
      * This API will result in allowing an intersection of allowed network types for all reasons,
      * including the configuration done through other reasons.
      *
-     * The functionality of this API with the parameter
-     * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} is the same as the API
-     * {@link TelephonyManager#setAllowedNetworkTypes}. Use this API instead of
-     * {@link TelephonyManager#setAllowedNetworkTypes}.
-     * <p>
-     * If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
-     * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
-     * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
-     * setPreferredNetworkTypesBitmap is used instead.
-     *
      * @param reason the reason the allowed network type change is taking place
-     * @param allowedNetworkTypes The bitmask of allowed network types.
+     * @param allowedNetworkTypes The bitmask of allowed network type
      * @throws IllegalStateException if the Telephony process is not currently available.
      * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
-     * @hide
+     * @throws SecurityException if the caller does not have the required privileges
      */
-    @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     @RequiresFeature(
             enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
@@ -8896,18 +8879,19 @@
      *
      * {@link #getAllowedNetworkTypesForReason} returns allowed network type for a
      * specific reason.
+     * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or
+     * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param reason the reason the allowed network type change is taking place
      * @return the allowed network type bitmask
      * @throws IllegalStateException    if the Telephony process is not currently available.
      * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
-     * @hide
+     * @throws SecurityException if the caller does not have the required permission/privileges
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @RequiresFeature(
             enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
             value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK)
-    @SystemApi
     public @NetworkTypeBitMask long getAllowedNetworkTypesForReason(
             @AllowedNetworkTypesReason int reason) {
         if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -11487,7 +11471,11 @@
 
         private final int mErrorCode;
 
-        /** @hide */
+        /**
+         * An exception with ModemActivityInfo specific error codes.
+         *
+         * @param errorCode a ModemActivityInfoError code.
+         */
         public ModemActivityInfoException(@ModemActivityInfoError int errorCode) {
             mErrorCode = errorCode;
         }
@@ -12123,12 +12111,15 @@
         if (carriers == null || !SubscriptionManager.isValidPhoneId(slotIndex)) {
             return -1;
         }
-        // Execute the method setCarrierRestrictionRules with an empty excluded list and
-        // indicating priority for the allowed list.
+        // Execute the method setCarrierRestrictionRules with an empty excluded list.
+        // If the allowed list is empty, it means that all carriers are allowed (default allowed),
+        // otherwise it means that only specified carriers are allowed (default not allowed).
         CarrierRestrictionRules carrierRestrictionRules = CarrierRestrictionRules.newBuilder()
                 .setAllowedCarriers(carriers)
                 .setDefaultCarrierRestriction(
-                    CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED)
+                    carriers.isEmpty()
+                        ? CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED
+                        : CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED)
                 .build();
 
         int result = setCarrierRestrictionRules(carrierRestrictionRules);
@@ -13022,127 +13013,88 @@
     // 2G
     /**
      * network type bitmask unknown.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L;
     /**
      * network type bitmask indicating the support of radio tech GSM.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_GSM = (1 << (NETWORK_TYPE_GSM -1));
     /**
      * network type bitmask indicating the support of radio tech GPRS.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_GPRS = (1 << (NETWORK_TYPE_GPRS -1));
     /**
      * network type bitmask indicating the support of radio tech EDGE.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EDGE = (1 << (NETWORK_TYPE_EDGE -1));
     /**
      * network type bitmask indicating the support of radio tech CDMA(IS95A/IS95B).
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_CDMA = (1 << (NETWORK_TYPE_CDMA -1));
     /**
      * network type bitmask indicating the support of radio tech 1xRTT.
-     * @hide
      */
-    @SystemApi
+    @SuppressLint("AllUpper")
     public static final long NETWORK_TYPE_BITMASK_1xRTT = (1 << (NETWORK_TYPE_1xRTT - 1));
     // 3G
     /**
      * network type bitmask indicating the support of radio tech EVDO 0.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EVDO_0 = (1 << (NETWORK_TYPE_EVDO_0 -1));
     /**
      * network type bitmask indicating the support of radio tech EVDO A.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EVDO_A = (1 << (NETWORK_TYPE_EVDO_A - 1));
     /**
      * network type bitmask indicating the support of radio tech EVDO B.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EVDO_B = (1 << (NETWORK_TYPE_EVDO_B -1));
     /**
      * network type bitmask indicating the support of radio tech EHRPD.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_EHRPD = (1 << (NETWORK_TYPE_EHRPD -1));
     /**
      * network type bitmask indicating the support of radio tech HSUPA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSUPA = (1 << (NETWORK_TYPE_HSUPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSDPA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSDPA = (1 << (NETWORK_TYPE_HSDPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSPA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSPA = (1 << (NETWORK_TYPE_HSPA -1));
     /**
      * network type bitmask indicating the support of radio tech HSPAP.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_HSPAP = (1 << (NETWORK_TYPE_HSPAP -1));
     /**
      * network type bitmask indicating the support of radio tech UMTS.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_UMTS = (1 << (NETWORK_TYPE_UMTS -1));
     /**
      * network type bitmask indicating the support of radio tech TD_SCDMA.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << (NETWORK_TYPE_TD_SCDMA -1));
     // 4G
     /**
      * network type bitmask indicating the support of radio tech LTE.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_LTE = (1 << (NETWORK_TYPE_LTE -1));
     /**
      * network type bitmask indicating the support of radio tech LTE CA (carrier aggregation).
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_LTE_CA = (1 << (NETWORK_TYPE_LTE_CA -1));
 
     /**
      * network type bitmask indicating the support of radio tech NR(New Radio) 5G.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_NR = (1 << (NETWORK_TYPE_NR -1));
 
     /**
      * network type bitmask indicating the support of radio tech IWLAN.
-     * @hide
      */
-    @SystemApi
     public static final long NETWORK_TYPE_BITMASK_IWLAN = (1 << (NETWORK_TYPE_IWLAN -1));
 
     /** @hide */
@@ -13197,12 +13149,11 @@
     /**
      * @return Modem supported radio access family bitmask
      *
-     * <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+     * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or
      * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
-     * @hide
+     *
+     * @throws SecurityException if the caller does not have the required permission
      */
-    @SystemApi
-    @TestApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @NetworkTypeBitMask long getSupportedRadioAccessFamily() {
         try {
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 051d6c5..13d8c7b 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -259,9 +259,10 @@
     }
 
     /**
-     * Unthrottles the APN on the current transport.  There is no matching "APN throttle" method.
-     * Instead, the APN is throttled when {@link IDataService#setupDataCall} fails within
-     * the time specified by {@link DataCallResponse#getRetryDurationMillis}.
+     * Unthrottles the APN on the current transport.
+     * The APN is throttled when {@link IDataService#setupDataCall} fails within
+     * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain
+     * throttled until this method is called.
      * <p/>
      * see: {@link DataCallResponse#getRetryDurationMillis}
      *
@@ -282,9 +283,9 @@
 
     /**
      * Unthrottles the DataProfile on the current transport.
-     * There is no matching "DataProfile throttle" method.
-     * Instead, the DataProfile is throttled when {@link IDataService#setupDataCall} fails within
-     * the time specified by {@link DataCallResponse#getRetryDurationMillis}.
+     * The DataProfile is throttled when {@link IDataService#setupDataCall} fails within
+     * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain
+     * throttled until this method is called.
      * <p/>
      * see: {@link DataCallResponse#getRetryDurationMillis}
      *
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index dfe5e6c9..d65286f 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -27,10 +27,12 @@
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsVideoCallProvider;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Provides the call initiation/termination, and media exchange between two IMS endpoints.
@@ -522,6 +524,7 @@
     private final IImsCallSession miSession;
     private boolean mClosed = false;
     private Listener mListener;
+    private Executor mListenerExecutor = Runnable::run;
 
     /** @hide */
     public ImsCallSession(IImsCallSession iSession) {
@@ -538,9 +541,9 @@
     }
 
     /** @hide */
-    public ImsCallSession(IImsCallSession iSession, Listener listener) {
+    public ImsCallSession(IImsCallSession iSession, Listener listener, Executor executor) {
         this(iSession);
-        setListener(listener);
+        setListener(listener, executor);
     }
 
     /**
@@ -738,10 +741,14 @@
      * override the previous listener.
      *
      * @param listener to listen to the session events of this object
+     * @param executor an Executor that will execute callbacks
      * @hide
      */
-    public void setListener(Listener listener) {
+    public void setListener(Listener listener, Executor executor) {
         mListener = listener;
+        if (executor != null) {
+            mListenerExecutor = executor;
+        }
     }
 
     /**
@@ -1205,44 +1212,56 @@
          */
         @Override
         public void callSessionInitiating(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionInitiating(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionInitiating(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionProgressing(ImsStreamMediaProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionProgressing(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionProgressing(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInitiated(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionStarted(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionStarted(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInitiatingFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionTerminated(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1250,44 +1269,56 @@
          */
         @Override
         public void callSessionHeld(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionHeld(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHeld(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionHoldReceived(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionHoldReceived(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHoldReceived(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionResumed(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionResumed(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionResumed(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionResumeReceived(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionResumeReceived(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionResumeReceived(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1310,15 +1341,17 @@
          */
         @Override
         public void callSessionMergeComplete(IImsCallSession newSession) {
-            if (mListener != null) {
-                if (newSession != null) {
-                    // New session created after conference
-                    mListener.callSessionMergeComplete(new ImsCallSession(newSession));
-               } else {
-                   // Session already exists. Hence no need to pass
-                   mListener.callSessionMergeComplete(null);
-               }
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    if (newSession != null) {
+                        // New session created after conference
+                        mListener.callSessionMergeComplete(new ImsCallSession(newSession));
+                    } else {
+                        // Session already exists. Hence no need to pass
+                        mListener.callSessionMergeComplete(null);
+                    }
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1328,9 +1361,11 @@
          */
         @Override
         public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1338,23 +1373,29 @@
          */
         @Override
         public void callSessionUpdated(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionUpdated(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUpdated(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionUpdateReceived(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1363,26 +1404,33 @@
         @Override
         public void callSessionConferenceExtended(IImsCallSession newSession,
                 ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionConferenceExtended(ImsCallSession.this,
-                        new ImsCallSession(newSession), profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceExtended(ImsCallSession.this,
+                            new ImsCallSession(newSession), profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceExtendFailed(
+                            ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionConferenceExtendReceived(IImsCallSession newSession,
                 ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
-                        new ImsCallSession(newSession), profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
+                            new ImsCallSession(newSession), profile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1391,32 +1439,41 @@
          */
         @Override
         public void callSessionInviteParticipantsRequestDelivered() {
-            if (mListener != null) {
-                mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionInviteParticipantsRequestDelivered(
+                            ImsCallSession.this);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
-                        reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
+                            reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionRemoveParticipantsRequestDelivered() {
-            if (mListener != null) {
-                mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
-                        reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
+                            reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1424,9 +1481,11 @@
          */
         @Override
         public void callSessionConferenceStateUpdated(ImsConferenceState state) {
-            if (mListener != null) {
-                mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1434,9 +1493,12 @@
          */
         @Override
         public void callSessionUssdMessageReceived(int mode, String ussdMessage) {
-            if (mListener != null) {
-                mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode,
+                            ussdMessage);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1452,10 +1514,12 @@
          */
         @Override
         public void callSessionMayHandover(int srcNetworkType, int targetNetworkType) {
-            if (mListener != null) {
-                mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
-                        targetNetworkType);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
+                            targetNetworkType);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1464,10 +1528,12 @@
         @Override
         public void callSessionHandover(int srcNetworkType, int targetNetworkType,
                 ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
-                        targetNetworkType, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
+                            targetNetworkType, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1476,10 +1542,12 @@
         @Override
         public void callSessionHandoverFailed(int srcNetworkType, int targetNetworkType,
                 ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
-                        targetNetworkType, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
+                            targetNetworkType, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1487,9 +1555,11 @@
          */
         @Override
         public void callSessionTtyModeReceived(int mode) {
-            if (mListener != null) {
-                mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1499,16 +1569,22 @@
          *      otherwise.
          */
         public void callSessionMultipartyStateChanged(boolean isMultiParty) {
-            if (mListener != null) {
-                mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionMultipartyStateChanged(ImsCallSession.this,
+                            isMultiParty);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) {
-            if (mListener != null) {
-                mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionSuppServiceReceived(ImsCallSession.this,
+                            suppServiceInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1516,9 +1592,12 @@
          */
         @Override
         public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) {
-            if (mListener != null) {
-                mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttModifyRequestReceived(ImsCallSession.this,
+                            callProfile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1526,9 +1605,11 @@
          */
         @Override
         public void callSessionRttModifyResponseReceived(int status) {
-            if (mListener != null) {
-                mListener.callSessionRttModifyResponseReceived(status);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttModifyResponseReceived(status);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1536,9 +1617,11 @@
          */
         @Override
         public void callSessionRttMessageReceived(String rttMessage) {
-            if (mListener != null) {
-                mListener.callSessionRttMessageReceived(rttMessage);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttMessageReceived(rttMessage);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1546,23 +1629,29 @@
          */
         @Override
         public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionRttAudioIndicatorChanged(profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttAudioIndicatorChanged(profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionTransferred() {
-            if (mListener != null) {
-                mListener.callSessionTransferred(ImsCallSession.this);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTransferred(ImsCallSession.this);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionTransferFailed(@Nullable ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1571,9 +1660,11 @@
          */
         @Override
         public void callSessionDtmfReceived(char dtmf) {
-            if (mListener != null) {
-                mListener.callSessionDtmfReceived(dtmf);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionDtmfReceived(dtmf);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1581,9 +1672,11 @@
          */
         @Override
         public void callQualityChanged(CallQuality callQuality) {
-            if (mListener != null) {
-                mListener.callQualityChanged(callQuality);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callQualityChanged(callQuality);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1593,10 +1686,12 @@
         @Override
         public void callSessionRtpHeaderExtensionsReceived(
                 @NonNull List<RtpHeaderExtension> extensions) {
-            if (mListener != null) {
-                mListener.callSessionRtpHeaderExtensionsReceived(
-                        new ArraySet<RtpHeaderExtension>(extensions));
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRtpHeaderExtensionsReceived(
+                            new ArraySet<RtpHeaderExtension>(extensions));
+                }
+            }, mListenerExecutor);
         }
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 9ab5aeb..be233b8 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -17,6 +17,7 @@
 package android.telephony.ims;
 
 import android.annotation.LongDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -41,14 +42,22 @@
 import android.telephony.ims.stub.SipTransportImplBase;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 
 import com.android.ims.internal.IImsFeatureStatusCallback;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
@@ -172,8 +181,28 @@
     // call ImsFeature#onFeatureRemoved.
     private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
 
-    private IImsServiceControllerListener mListener;
+    // A map of slot id -> boolean array, where each entry in the boolean array corresponds to an
+    // ImsFeature that was created for a slot id and not a sub id for backwards compatibility
+    // purposes.
+    private final SparseArray<SparseBooleanArray> mCreateImsFeatureWithSlotIdFlagMap =
+            new SparseArray<>();
 
+    private IImsServiceControllerListener mListener;
+    private Executor mExecutor;
+
+    /**
+     * Create a new ImsService.
+     * <p>
+     * Method stubs called from the framework will be called asynchronously. Vendor specifies the
+     * {@link Executor} that the methods stubs will be called. If mExecutor is set to null by
+     * vendor use Runnable::run.
+     */
+    public ImsService() {
+        mExecutor = ImsService.this.getExecutor();
+        if (mExecutor == null) {
+            mExecutor = Runnable::run;
+        }
+    }
 
     /**
      * Listener that notifies the framework of ImsService changes.
@@ -200,79 +229,163 @@
         }
 
         @Override
-        public IImsMmTelFeature createMmTelFeature(int slotId) {
-            return createMmTelFeatureInternal(slotId);
+        public IImsMmTelFeature createMmTelFeature(int slotId, int subId) {
+            MmTelFeature f  = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
+            if (f == null) {
+                return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId, subId),
+                        "createMmTelFeature");
+            } else {
+                return f.getBinder();
+            }
         }
 
         @Override
-        public IImsRcsFeature createRcsFeature(int slotId) {
-            return createRcsFeatureInternal(slotId);
+        public IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
+            MmTelFeature f  = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
+            if (f == null) {
+                return executeMethodAsyncForResult(() -> createEmergencyOnlyMmTelFeatureInternal(
+                        slotId), "createEmergencyOnlyMmTelFeature");
+            } else {
+                return f.getBinder();
+            }
+        }
+
+        @Override
+        public IImsRcsFeature createRcsFeature(int slotId, int subId) {
+            RcsFeature f  = (RcsFeature) getImsFeature(slotId, ImsFeature.FEATURE_RCS);
+            if (f == null) {
+                return executeMethodAsyncForResult(() ->
+                        createRcsFeatureInternal(slotId, subId), "createRcsFeature");
+            } else {
+                return f.getBinder();
+            }
         }
 
         @Override
         public void addFeatureStatusCallback(int slotId, int featureType,
                 IImsFeatureStatusCallback c) {
-            ImsService.this.addImsFeatureStatusCallback(slotId, featureType, c);
+            executeMethodAsync(() -> ImsService.this.addImsFeatureStatusCallback(
+                    slotId, featureType, c), "addFeatureStatusCallback");
         }
 
         @Override
         public void removeFeatureStatusCallback(int slotId, int featureType,
                 IImsFeatureStatusCallback c) {
-            ImsService.this.removeImsFeatureStatusCallback(slotId, featureType, c);
+            executeMethodAsync(() -> ImsService.this.removeImsFeatureStatusCallback(
+                    slotId, featureType, c), "removeFeatureStatusCallback");
         }
 
         @Override
-        public void removeImsFeature(int slotId, int featureType) {
-            ImsService.this.removeImsFeature(slotId, featureType);
+        public void removeImsFeature(int slotId, int featureType, boolean changeSubId) {
+            if (changeSubId && isImsFeatureCreatedForSlot(slotId, featureType)) {
+                Log.w(LOG_TAG, "Do not remove Ims feature for compatibility");
+                return;
+            }
+            executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType),
+                    "removeImsFeature");
+            setImsFeatureCreatedForSlot(slotId, featureType, false);
         }
 
         @Override
         public ImsFeatureConfiguration querySupportedImsFeatures() {
-            return ImsService.this.querySupportedImsFeatures();
+            return executeMethodAsyncForResult(() -> ImsService.this.querySupportedImsFeatures(),
+                    "ImsFeatureConfiguration");
         }
 
         @Override
         public long getImsServiceCapabilities() {
-            long caps = ImsService.this.getImsServiceCapabilities();
-            long sanitizedCaps = sanitizeCapabilities(caps);
-            if (caps != sanitizedCaps) {
-                Log.w(LOG_TAG, "removing invalid bits from field: 0x"
-                        + Long.toHexString(caps ^ sanitizedCaps));
-            }
-            return sanitizedCaps;
+            return executeMethodAsyncForResult(() -> {
+                long caps = ImsService.this.getImsServiceCapabilities();
+                long sanitizedCaps = sanitizeCapabilities(caps);
+                if (caps != sanitizedCaps) {
+                    Log.w(LOG_TAG, "removing invalid bits from field: 0x"
+                            + Long.toHexString(caps ^ sanitizedCaps));
+                }
+                return sanitizedCaps;
+            }, "getImsServiceCapabilities");
         }
 
         @Override
         public void notifyImsServiceReadyForFeatureCreation() {
-            ImsService.this.readyForFeatureCreation();
+            executeMethodAsync(() -> ImsService.this.readyForFeatureCreation(),
+                    "notifyImsServiceReadyForFeatureCreation");
         }
 
         @Override
-        public IImsConfig getConfig(int slotId) {
-            ImsConfigImplBase c = ImsService.this.getConfig(slotId);
-            return c != null ? c.getIImsConfig() : null;
+        public IImsConfig getConfig(int slotId, int subId) {
+            return executeMethodAsyncForResult(() -> {
+                ImsConfigImplBase c =
+                        ImsService.this.getConfigForSubscription(slotId, subId);
+                if (c != null) {
+                    c.setDefaultExecutor(mExecutor);
+                    return c.getIImsConfig();
+                } else {
+                    return null;
+                }
+            }, "getConfig");
         }
 
         @Override
-        public IImsRegistration getRegistration(int slotId) {
-            ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
-            return r != null ? r.getBinder() : null;
+        public IImsRegistration getRegistration(int slotId, int subId) {
+            return executeMethodAsyncForResult(() -> {
+                ImsRegistrationImplBase r =
+                        ImsService.this.getRegistrationForSubscription(slotId, subId);
+                if (r != null) {
+                    r.setDefaultExecutor(mExecutor);
+                    return r.getBinder();
+                } else {
+                    return null;
+                }
+            }, "getRegistration");
         }
 
         @Override
         public ISipTransport getSipTransport(int slotId) {
-            SipTransportImplBase s = ImsService.this.getSipTransport(slotId);
-            return s != null ? s.getBinder() : null;
+            return executeMethodAsyncForResult(() -> {
+                SipTransportImplBase s =  ImsService.this.getSipTransport(slotId);
+                if (s != null) {
+                    s.setDefaultExecutor(mExecutor);
+                    return s.getBinder();
+                } else {
+                    return null;
+                }
+            }, "getSipTransport");
         }
 
         @Override
-        public void enableIms(int slotId) {
-            ImsService.this.enableIms(slotId);
+        public void enableIms(int slotId, int subId) {
+            executeMethodAsync(() ->
+                    ImsService.this.enableImsForSubscription(slotId, subId), "enableIms");
         }
 
         @Override
-        public void disableIms(int slotId) {
-            ImsService.this.disableIms(slotId);
+        public void disableIms(int slotId, int subId) {
+            executeMethodAsync(() ->
+                    ImsService.this.disableImsForSubscription(slotId, subId), "disableIms");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                return null;
+            }
         }
     };
 
@@ -288,18 +401,11 @@
         return null;
     }
 
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public SparseArray<ImsFeature> getFeatures(int slotId) {
-        return mFeaturesBySlot.get(slotId);
-    }
-
-    private IImsMmTelFeature createMmTelFeatureInternal(int slotId) {
-        MmTelFeature f = createMmTelFeature(slotId);
+    private IImsMmTelFeature createMmTelFeatureInternal(int slotId, int subscriptionId) {
+        MmTelFeature f = createMmTelFeatureForSubscription(slotId, subscriptionId);
         if (f != null) {
             setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
+            f.setDefaultExecutor(mExecutor);
             return f.getBinder();
         } else {
             Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
@@ -307,9 +413,22 @@
         }
     }
 
-    private IImsRcsFeature createRcsFeatureInternal(int slotId) {
-        RcsFeature f = createRcsFeature(slotId);
+    private IImsMmTelFeature createEmergencyOnlyMmTelFeatureInternal(int slotId) {
+        MmTelFeature f = createEmergencyOnlyMmTelFeature(slotId);
         if (f != null) {
+            setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
+            f.setDefaultExecutor(mExecutor);
+            return f.getBinder();
+        } else {
+            Log.e(LOG_TAG, "createEmergencyOnlyMmTelFeatureInternal: null feature returned.");
+            return null;
+        }
+    }
+
+    private IImsRcsFeature createRcsFeatureInternal(int slotId, int subI) {
+        RcsFeature f = createRcsFeatureForSubscription(slotId, subI);
+        if (f != null) {
+            f.setDefaultExecutor(mExecutor);
             setupFeature(f, slotId, ImsFeature.FEATURE_RCS);
             return f.getBinder();
         } else {
@@ -388,6 +507,49 @@
             f.onFeatureRemoved();
             features.remove(featureType);
         }
+
+    }
+
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public ImsFeature getImsFeature(int slotId, int featureType) {
+        synchronized (mFeaturesBySlot) {
+            // Get SparseArray for Features, by querying slot Id
+            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+            if (features == null) {
+                return null;
+            }
+            return features.get(featureType);
+        }
+    }
+
+    private void setImsFeatureCreatedForSlot(int slotId,
+            @ImsFeature.FeatureType int featureType, boolean createdForSlot) {
+        synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
+            getImsFeatureCreatedForSlot(slotId).put(featureType, createdForSlot);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean isImsFeatureCreatedForSlot(int slotId,
+            @ImsFeature.FeatureType int featureType) {
+        synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
+            return getImsFeatureCreatedForSlot(slotId).get(featureType);
+        }
+    }
+
+    private SparseBooleanArray getImsFeatureCreatedForSlot(int slotId) {
+        SparseBooleanArray createFlag = mCreateImsFeatureWithSlotIdFlagMap.get(slotId);
+        if (createFlag == null) {
+            createFlag = new SparseBooleanArray();
+            mCreateImsFeatureWithSlotIdFlagMap.put(slotId, createFlag);
+        }
+        return createFlag;
     }
 
     /**
@@ -446,27 +608,95 @@
     }
 
     /**
+     * The framework has enabled IMS for the subscription specified, the ImsService should register
+     * for IMS and perform all appropriate initialization to bring up all ImsFeatures.
+     *
+     * @param slotId The slot ID that IMS will be enabled for.
+     * @param subscriptionId The subscription ID that IMS will be enabled for.
+     */
+    public void enableImsForSubscription(int slotId, int subscriptionId) {
+        enableIms(slotId);
+    }
+
+    /**
+     * The framework has disabled IMS for the subscription specified. The ImsService must deregister
+     * for IMS and set capability status to false for all ImsFeatures.
+     * @param slotId The slot ID that IMS will be disabled for.
+     * @param subscriptionId The subscription ID that IMS will be disabled for.
+     */
+    public void disableImsForSubscription(int slotId, int subscriptionId) {
+        disableIms(slotId);
+    }
+
+    /**
      * The framework has enabled IMS for the slot specified, the ImsService should register for IMS
      * and perform all appropriate initialization to bring up all ImsFeatures.
+     * @deprecated Use {@link #enableImsForSubscription} instead.
      */
+    @Deprecated
     public void enableIms(int slotId) {
     }
 
     /**
      * The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS
      * and set capability status to false for all ImsFeatures.
+     * @deprecated Use {@link #disableImsForSubscription} instead.
      */
+    @Deprecated
     public void disableIms(int slotId) {
     }
 
     /**
      * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
+     * specified subscription.
+     *
+     * @param subscriptionId The subscription ID that the MMTEL Feature is being created for.
+     * @return The newly created {@link MmTelFeature} associated with the subscription or null if
+     * the feature is not supported.
+     */
+    public @Nullable MmTelFeature createMmTelFeatureForSubscription(int slotId,
+            int subscriptionId) {
+        setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
+        return createMmTelFeature(slotId);
+    }
+
+    /**
+     * When called, the framework is requesting that a new {@link RcsFeature} is created for the
+     * specified subscription.
+     *
+     * @param subscriptionId The subscription ID that the RCS Feature is being created for.
+     * @return The newly created {@link RcsFeature} associated with the subscription or null if the
+     * feature is not supported.
+     */
+    public @Nullable RcsFeature createRcsFeatureForSubscription(int slotId, int subscriptionId) {
+        setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_RCS, true);
+        return createRcsFeature(slotId);
+    }
+
+    /**
+     * When called, the framework is requesting that a new emergency-only {@link MmTelFeature} is
+     * created for the specified slot. For emergency calls, there is no known Subscription Id.
+     *
+     * @param slotId The slot ID that the MMTEL Feature is being created for.
+     * @return An MmTelFeature instance to be used for the slot ID when there is not
+     * subscription inserted. Only requested when there is no subscription active on
+     * the specified slot.
+     */
+    public @Nullable MmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
+        setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
+        return createMmTelFeature(slotId);
+    }
+
+    /**
+     * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
      * specified slot.
+     * @deprecated Use {@link #createMmTelFeatureForSubscription} instead
      *
      * @param slotId The slot ID that the MMTEL Feature is being created for.
      * @return The newly created {@link MmTelFeature} associated with the slot or null if the
      * feature is not supported.
      */
+    @Deprecated
     public MmTelFeature createMmTelFeature(int slotId) {
         return null;
     }
@@ -474,32 +704,62 @@
     /**
      * When called, the framework is requesting that a new {@link RcsFeature} is created for the
      * specified slot.
+     * @deprecated Use {@link #createRcsFeatureForSubscription} instead
      *
      * @param slotId The slot ID that the RCS Feature is being created for.
      * @return The newly created {@link RcsFeature} associated with the slot or null if the feature
      * is not supported.
      */
+    @Deprecated
     public RcsFeature createRcsFeature(int slotId) {
         return null;
     }
 
     /**
+     * Return the {@link ImsConfigImplBase} implementation associated with the provided
+     * subscription. This will be used by the platform to get/set specific IMS related
+     * configurations.
+     *
+     * @param subscriptionId The subscription ID that the IMS configuration is associated with.
+     * @return ImsConfig implementation that is associated with the specified subscription.
+     */
+    public @NonNull ImsConfigImplBase getConfigForSubscription(int slotId, int subscriptionId) {
+        return getConfig(slotId);
+    }
+
+    /**
+     * Return the {@link ImsRegistrationImplBase} implementation associated with the provided
+     * subscription.
+     *
+     * @param subscriptionId The subscription ID that is associated with the IMS Registration.
+     * @return the ImsRegistration implementation associated with the subscription.
+     */
+    public @NonNull ImsRegistrationImplBase getRegistrationForSubscription(int slotId,
+            int subscriptionId) {
+        return getRegistration(slotId);
+    }
+
+    /**
      * Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This
      * will be used by the platform to get/set specific IMS related configurations.
+     * @deprecated use {@link #getConfigForSubscription} instead.
      *
      * @param slotId The slot that the IMS configuration is associated with.
      * @return ImsConfig implementation that is associated with the specified slot.
      */
+    @Deprecated
     public ImsConfigImplBase getConfig(int slotId) {
         return new ImsConfigImplBase();
     }
 
     /**
      * Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot.
+     * @deprecated use  {@link #getRegistrationForSubscription} instead.
      *
      * @param slotId The slot that is associated with the IMS Registration.
      * @return the ImsRegistration implementation associated with the slot.
      */
+    @Deprecated
     public ImsRegistrationImplBase getRegistration(int slotId) {
         return new ImsRegistrationImplBase();
     }
@@ -562,4 +822,15 @@
         result.append("}");
         return result.toString();
     }
+
+    /**
+     * The ImsService will now be able to define an Executor that the ImsService can be used to
+     * execute the methods. By default all ImsService level method calls will use this Executor.
+     * The ImsService has set the default executor as Runnable::run,
+     * Should be override or default executor will be used.
+     *  @return an Executor used to execute methods called remotely by the framework.
+     */
+    public @NonNull Executor getExecutor() {
+        return Runnable::run;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index abc5606..5aef8a6 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -33,6 +33,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyManager;
+import android.telephony.ims.aidl.IFeatureProvisioningCallback;
 import android.telephony.ims.aidl.IImsConfigCallback;
 import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.ims.feature.MmTelFeature;
@@ -53,17 +54,11 @@
  * IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning
  * applications and may vary. It is up to the carrier and OEM applications to ensure that the
  * correct provisioning keys are being used when integrating with a vendor's ImsService.
- *
- * Note: For compatibility purposes, the integer values [0 - 99] used in
- * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys
- * previously defined in the Android framework. Please do not redefine new provisioning keys in this
- * range or it may generate collisions with existing keys. Some common constants have also been
- * defined in this class to make integrating with other system apps easier.
- * @hide
  */
-@SystemApi
 public class ProvisioningManager {
 
+    private static final String TAG = "ProvisioningManager";
+
     /**@hide*/
     @StringDef(prefix = "STRING_QUERY_RESULT_ERROR_", value = {
             STRING_QUERY_RESULT_ERROR_GENERIC,
@@ -74,14 +69,18 @@
 
     /**
      * The query from {@link #getProvisioningStringValue(int)} has resulted in an unspecified error.
+     * @hide
      */
+    @SystemApi
     public static final String STRING_QUERY_RESULT_ERROR_GENERIC =
             "STRING_QUERY_RESULT_ERROR_GENERIC";
 
     /**
      * The query from {@link #getProvisioningStringValue(int)} has resulted in an error because the
      * ImsService implementation was not ready for provisioning queries.
+     * @hide
      */
+    @SystemApi
     public static final String STRING_QUERY_RESULT_ERROR_NOT_READY =
             "STRING_QUERY_RESULT_ERROR_NOT_READY";
 
@@ -93,12 +92,16 @@
 
     /**
      * The integer result of provisioning for the queried key is disabled.
+     * @hide
      */
+    @SystemApi
     public static final int PROVISIONING_VALUE_DISABLED = 0;
 
     /**
      * The integer result of provisioning for the queried key is enabled.
+     * @hide
      */
+    @SystemApi
     public static final int PROVISIONING_VALUE_ENABLED = 1;
 
 
@@ -443,27 +446,31 @@
 
     /**
      * Override the user-defined WiFi Roaming enabled setting for this subscription, defined in
-     * {@link SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI}, for the purposes of provisioning
-     * the subscription for WiFi Calling.
+     * {@link android.telephony.SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI},
+     * for the purposes of provisioning the subscription for WiFi Calling.
      *
-     * @see #getProvisioningIntValue(int)
      * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     * @hide
      */
+    @SystemApi
     public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26;
 
     /**
      * Override the user-defined WiFi mode for this subscription, defined in
-     * {@link SubscriptionManager#WFC_MODE_CONTENT_URI}, for the purposes of provisioning
-     * this subscription for WiFi Calling.
+     * {@link android.telephony.SubscriptionManager#WFC_MODE_CONTENT_URI},
+     * for the purposes of provisioning this subscription for WiFi Calling.
      *
      * Valid values for this key are:
      * {@link ImsMmTelManager#WIFI_MODE_WIFI_ONLY},
      * {@link ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED}, or
      * {@link ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED}.
      *
-     * @see #getProvisioningIntValue(int)
      * @see #setProvisioningIntValue(int, int)
+     * @see #getProvisioningIntValue(int)
+     * @hide
      */
+    @SystemApi
     public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27;
 
     /**
@@ -862,7 +869,9 @@
      * <p>Value is in String format.
      * @see #setProvisioningStringValue(int, String)
      * @see #getProvisioningStringValue(int)
+     * @hide
      */
+    @SystemApi
     public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67;
 
     /**
@@ -884,7 +893,9 @@
 
     /**
      * Callback for IMS provisioning changes.
+     * @hide
      */
+    @SystemApi
     public static class Callback {
 
         private static class CallbackBinder extends IImsConfigCallback.Stub {
@@ -954,11 +965,105 @@
         }
     }
 
+    /**
+     * Callback for IMS provisioning feature changes.
+     */
+    public static class FeatureProvisioningCallback {
+
+        private static class CallbackBinder extends IFeatureProvisioningCallback.Stub {
+
+            private final FeatureProvisioningCallback mFeatureProvisioningCallback;
+            private Executor mExecutor;
+
+            private CallbackBinder(FeatureProvisioningCallback featureProvisioningCallback) {
+                mFeatureProvisioningCallback = featureProvisioningCallback;
+            }
+
+            @Override
+            public final void onFeatureProvisioningChanged(
+                    int capability, int tech, boolean isProvisioned) {
+                final long callingIdentity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() ->
+                            mFeatureProvisioningCallback.onFeatureProvisioningChanged(
+                                    capability, tech, isProvisioned));
+                } finally {
+                    restoreCallingIdentity(callingIdentity);
+                }
+            }
+
+            @Override
+            public final void onRcsFeatureProvisioningChanged(
+                    int capability, int tech, boolean isProvisioned) {
+                final long callingIdentity = Binder.clearCallingIdentity();
+                try {
+                    mExecutor.execute(() ->
+                            mFeatureProvisioningCallback.onRcsFeatureProvisioningChanged(
+                                    capability, tech, isProvisioned));
+                } finally {
+                    restoreCallingIdentity(callingIdentity);
+                }
+            }
+
+            private void setExecutor(Executor executor) {
+                mExecutor = executor;
+            }
+        }
+
+        private final CallbackBinder mBinder = new CallbackBinder(this);
+
+        /**
+         * The IMS MMTEL provisioning has changed for a specific capability and IMS
+         * registration technology.
+         * @param capability The MMTEL capability that provisioning has changed for.
+         * @param tech The IMS registration technology associated with the MMTEL capability that
+         * provisioning has changed for.
+         * @param isProvisioned {@code true} if the capability is provisioned for the technology
+         * specified, or {@code false} if the capability is not provisioned for the technology
+         * specified.
+         */
+        public void onFeatureProvisioningChanged(
+                @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+                @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+                boolean isProvisioned) {
+            // Base Implementation
+        }
+
+        /**
+         * The IMS RCS provisioning has changed for a specific capability and IMS
+         * registration technology.
+         * @param capability The RCS capability that provisioning has changed for.
+         * @param tech The IMS registration technology associated with the RCS capability that
+         * provisioning has changed for.
+         * @param isProvisioned {@code true} if the capability is provisioned for the technology
+         * specified, or {@code false} if the capability is not provisioned for the technology
+         * specified.
+         */
+        public void onRcsFeatureProvisioningChanged(
+                @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+                @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+                boolean isProvisioned) {
+            // Base Implementation
+        }
+
+        /**@hide*/
+        public final IFeatureProvisioningCallback getBinder() {
+            return mBinder;
+        }
+
+        /**@hide*/
+        public void setExecutor(Executor executor) {
+            mBinder.setExecutor(executor);
+        }
+    }
+
     private int mSubId;
 
     /**
      * The callback for RCS provisioning changes.
+     * @hide
      */
+    @SystemApi
     public static class RcsProvisioningCallback {
         private static class CallbackBinder extends IRcsConfigCallback.Stub {
 
@@ -1096,7 +1201,9 @@
      * @param subId The ID of the subscription that this ProvisioningManager will use.
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
      * @throws IllegalArgumentException if the subscription is invalid.
+     * @hide
      */
+    @SystemApi
     public static @NonNull ProvisioningManager createForSubscriptionId(int subId) {
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid subscription ID");
@@ -1105,7 +1212,9 @@
         return new ProvisioningManager(subId);
     }
 
-    private ProvisioningManager(int subId) {
+    /**@hide*/
+    //@SystemApi
+    public ProvisioningManager(int subId) {
         mSubId = subId;
     }
 
@@ -1114,6 +1223,12 @@
      *
      * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
      * etc...), this callback will automatically be removed.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+     * </ul>
+     *
      * @param executor The {@link Executor} to call the callback methods on
      * @param callback The provisioning callbackto be registered.
      * @see #unregisterProvisioningChangedCallback(Callback)
@@ -1124,7 +1239,9 @@
      * the {@link ImsService} associated with the subscription is not available. This can happen if
      * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
      * reason.
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull Callback callback) throws ImsException {
@@ -1142,12 +1259,20 @@
      * Unregister an existing {@link Callback}. When the subscription associated with this
      * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be
      * removed. If this method is called for an inactive subscription, it will result in a no-op.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+     * </ul>
+     *
      * @param callback The existing {@link Callback} to be removed.
      * @see #registerProvisioningChangedCallback(Executor, Callback)
      *
      * @throws IllegalArgumentException if the subscription associated with this callback is
      * invalid.
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
         try {
@@ -1158,6 +1283,62 @@
     }
 
     /**
+     * Register a new {@link FeatureProvisioningCallback}, which is used to listen for
+     * IMS feature provisioning updates.
+     * <p>
+     * When the subscription associated with this callback is removed (SIM removed,
+     * ESIM swap,etc...), this callback will automatically be removed.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @param executor The executor that the callback methods will be called on.
+     * @param callback The callback instance being registered.
+     * @throws ImsException if the subscription associated with this callback is
+     * valid, but the {@link ImsService the service crashed, for example. See
+     * {@link ImsException#getCode()} for a more detailed reason.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public void registerFeatureProvisioningChangedCallback(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull FeatureProvisioningCallback callback) throws ImsException {
+        callback.setExecutor(executor);
+        try {
+            getITelephony().registerFeatureProvisioningChangedCallback(mSubId,
+                    callback.getBinder());
+        } catch (ServiceSpecificException e) {
+            throw new ImsException(e.getMessage(), e.errorCode);
+        } catch (RemoteException | IllegalStateException e) {
+            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Unregisters a previously registered {@link FeatureProvisioningCallback}
+     * instance.  When the subscription associated with this
+     * callback is removed (SIM removed, ESIM swap, etc...), this callback will
+     * automatically be removed. If this method is called for an inactive
+     * subscription, it will result in a no-op.
+     *
+     * @param callback The existing {@link FeatureProvisioningCallback} to be removed.
+     * @see #registerFeatureProvisioningChangedCallback(Executor, FeatureProvisioningCallback)
+     */
+    public void unregisterFeatureProvisioningChangedCallback(
+            @NonNull FeatureProvisioningCallback callback) {
+        try {
+            getITelephony().unregisterFeatureProvisioningChangedCallback(mSubId,
+                    callback.getBinder());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * Query for the integer value associated with the provided key.
      *
      * This operation is blocking and should not be performed on the UI thread.
@@ -1166,7 +1347,9 @@
      * @return an integer value for the provided key, or
      * {@link ImsConfigImplBase#CONFIG_RESULT_UNKNOWN} if the key doesn't exist.
      * @throws IllegalArgumentException if the key provided was invalid.
+     * @hide
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public int getProvisioningIntValue(int key) {
@@ -1186,7 +1369,9 @@
      * @return a String value for the provided key, {@code null} if the key doesn't exist, or
      * {@link StringResultError} if there was an error getting the value for the provided key.
      * @throws IllegalArgumentException if the key provided was invalid.
+     * @hide
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @Nullable @StringResultError String getProvisioningStringValue(int key) {
@@ -1207,7 +1392,15 @@
      * @param key An integer that represents the provisioning key, which is defined by the OEM.
      * @param value a integer value for the provided key.
      * @return the result of setting the configuration value.
+     * @hide
+     *
+     * Note: For compatibility purposes, the integer values [0 - 99] used in
+     * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys
+     * previously defined in the Android framework. Please do not redefine new provisioning keys
+     * in this range or it may generate collisions with existing keys. Some common constants have
+     * also been defined in this class to make integrating with other system apps easier.
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) {
@@ -1227,7 +1420,9 @@
      *     should be appropriately namespaced to avoid collision.
      * @param value a String value for the provided key.
      * @return the result of setting the configuration value.
+     * @hide
      */
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
@@ -1247,8 +1442,14 @@
      * does not support the capability/technology combination specified, this operation will be a
      * no-op.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL
-     * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
+     * <p>Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>or that the calling app has carrier privileges (see</li>
+     *     <li>{@link TelephonyManager#hasCarrierPrivileges}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
      * @param isProvisioned true if the device is provisioned for UT over IMS, false otherwise.
      */
     @WorkerThread
@@ -1256,9 +1457,10 @@
     public void setProvisioningStatusForCapability(
             @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int tech,  boolean isProvisioned) {
+
         try {
             getITelephony().setImsProvisioningStatusForCapability(mSubId, capability, tech,
-                    isProvisioned);
+                        isProvisioned);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -1272,14 +1474,21 @@
      * {@link ImsRegistrationImplBase.ImsRegistrationTech} combination specified, this method will
      * always return {@code true}.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL
-     * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
      * @return true if the device is provisioned for the capability or does not require
      * provisioning, false if the capability does require provisioning and has not been
      * provisioned yet.
      */
     @WorkerThread
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
     public boolean getProvisioningStatusForCapability(
             @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
@@ -1297,17 +1506,93 @@
      * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method will always return
      * {@code true}.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+     * @see CarrierConfigManager.Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
      * @return true if the device is provisioned for the capability or does not require
      * provisioning, false if the capability does require provisioning and has not been
      * provisioned yet.
+     * @deprecated Use {@link #getRcsProvisioningStatusForCapability(int, int)} instead,
+     * as this only retrieves provisioning information for
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}
+     * @hide
      */
+    @Deprecated
+    @SystemApi
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public boolean getRcsProvisioningStatusForCapability(
             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
         try {
-            return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability);
+            return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability,
+            ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Get the provisioning status for the IMS RCS capability specified.
+     *
+     * If provisioning is not required for the queried
+     * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method
+     * will always return {@code true}.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+     * @return true if the device is provisioned for the capability or does not require
+     * provisioning, false if the capability does require provisioning and has not been
+     * provisioned yet.
+     */
+    @WorkerThread
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public boolean getRcsProvisioningStatusForCapability(
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+        try {
+            return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, tech);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Set the provisioning status for the IMS RCS capability using the specified subscription.
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE}</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+
+     * Provisioning may or may not be required, depending on the carrier configuration. If
+     * provisioning is not required for the carrier associated with this subscription or the device
+     * does not support the capability/technology combination specified, this operation will be a
+     * no-op.
+     *
+     * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+     * @param isProvisioned true if the device is provisioned for the RCS capability specified,
+     *                      false otherwise.
+     * @deprecated Use {@link #setRcsProvisioningStatusForCapability(int, int, boolean)} instead,
+     * as this method only sets provisioning information for
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @WorkerThread
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void setRcsProvisioningStatusForCapability(
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            boolean isProvisioned) {
+        try {
+            getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
+                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isProvisioned);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -1321,7 +1606,14 @@
      * does not support the capability/technology combination specified, this operation will be a
      * no-op.
      *
-     * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+     * <p> Requires Permission:
+     * <ul>
+     *     <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
      * @param isProvisioned true if the device is provisioned for the RCS capability specified,
      *                      false otherwise.
      */
@@ -1329,31 +1621,92 @@
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void setRcsProvisioningStatusForCapability(
             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
-            boolean isProvisioned) {
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) {
         try {
             getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
-                    isProvisioned);
+                    tech, isProvisioned);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
     }
 
     /**
+     * Indicates whether provisioning for the MMTEL capability and IMS registration technology
+     * specified is required or not
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li> or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @return true if provisioning is required for the MMTEL capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public boolean isProvisioningRequiredForCapability(
+            @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+        try {
+            return getITelephony().isProvisioningRequiredForCapability(mSubId, capability, tech);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+
+    /**
+     * Indicates whether provisioning for the RCS capability and IMS registration technology
+     * specified is required or not
+     *
+     * <p> Requires Permission:
+     * <ul>
+     *     <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+     *     <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+     *     <li> or that the caller has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
+     * @return true if provisioning is required for the RCS capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public boolean isRcsProvisioningRequiredForCapability(
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+        try {
+            return getITelephony().isRcsProvisioningRequiredForCapability(mSubId, capability, tech);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+
+    /**
      * Notify the framework that an RCS autoconfiguration XML file has been received for
      * provisioning.
-     * <p>
-     * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has
-     * carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * <p>Requires Permission:
+     * <ul>
+     *     <li>{@link Manifest.permission#MODIFY_PHONE_STATE},</li>
+     *     <li>or that the calling app has carrier privileges (see
+     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+     * </ul>
+     *
      * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
      * @param isCompressed The XML file is compressed in gzip format and must be decompressed
      *         before being read.
-     *
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
         if (config == null) {
             throw new IllegalArgumentException("Must include a non-null config XML file.");
         }
+
         try {
             getITelephony().notifyRcsAutoConfigurationReceived(mSubId, config, isCompressed);
         } catch (RemoteException e) {
@@ -1372,7 +1725,9 @@
      * <p>Contains {@link #EXTRA_SUBSCRIPTION_ID} to specify the subscription index for which
      * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
      * status.
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE =
@@ -1380,7 +1735,9 @@
 
     /**
      * Integer extra to specify subscription index.
+     * @hide
      */
+    @SystemApi
     public static final String EXTRA_SUBSCRIPTION_ID =
             "android.telephony.ims.extra.SUBSCRIPTION_ID";
 
@@ -1390,22 +1747,30 @@
      * <p>The value can be {@link #STATUS_CAPABLE}, {@link #STATUS_DEVICE_NOT_CAPABLE},
      * {@link #STATUS_CARRIER_NOT_CAPABLE}, or bitwise OR of
      * {@link #STATUS_DEVICE_NOT_CAPABLE} and {@link #STATUS_CARRIER_NOT_CAPABLE}.
+     * @hide
      */
+    @SystemApi
     public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
 
     /**
      * RCS VoLTE single registration is supported by the device and carrier.
+     * @hide
      */
+    @SystemApi
     public static final int STATUS_CAPABLE                       = 0;
 
     /**
      * RCS VoLTE single registration is not supported by the device.
+     * @hide
      */
+    @SystemApi
     public static final int STATUS_DEVICE_NOT_CAPABLE            = 0x01;
 
     /**
      * RCS VoLTE single registration is not supported by the carrier
+     * @hide
      */
+    @SystemApi
     public static final int STATUS_CARRIER_NOT_CAPABLE           = 0x01 << 1;
 
     /**
@@ -1415,11 +1780,14 @@
      * provisioning is done using autoconfiguration, then these parameters shall be
      * sent in the HTTP get request to fetch the RCS provisioning. RCS client
      * configuration must be provided by the application before registering for the
-     * provisioning status events {@link #registerRcsProvisioningCallback()}
+     * provisioning status events
+     * {@link #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)}
      * When the IMS/RCS service receives the RCS client configuration, it will detect
      * the change in the configuration, and trigger the auto-configuration as needed.
      * @param rcc RCS client configuration {@link RcsClientConfiguration}
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void setRcsClientConfiguration(
             @NonNull RcsClientConfiguration rcc) throws ImsException {
@@ -1440,18 +1808,21 @@
      * <ul>
      *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
      *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
-     *     <li>or that the caller has carrier privileges (see
+     *     <li>or that the calling app has carrier privileges (see
      *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
      * </ul>
+     *
      * @return true if IMS single registration is capable at this time, or false otherwise
-     * @throws ImsException If the remote ImsService is not available for
-     * any reason or the subscription associated with this instance is no
-     * longer active. See {@link ImsException#getCode()} for more
-     * information.
+     * @throws ImsException If the remote ImsService is not available for any reason or
+     * the subscription associated with this instance is no longer active.
+     * See {@link ImsException#getCode()} for more information.
      * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this
      * device supports IMS single registration.
+     * @hide
      */
-    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
         try {
@@ -1478,8 +1849,6 @@
     * <ul>
     *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
     *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
-    *     <li>or that the caller has carrier privileges (see
-    *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
     * </ul>
     *
     * @param executor The {@link Executor} to call the callback methods on
@@ -1497,8 +1866,11 @@
     * params (See {@link #setRcsClientConfiguration}) and re register the
     * callback.
     * See {@link ImsException#getCode()} for a more detailed reason.
+    * @hide
     */
-    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void registerRcsProvisioningCallback(
             @NonNull @CallbackExecutor Executor executor,
@@ -1525,8 +1897,6 @@
      * <ul>
      *     <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
      *     <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
-     *     <li>or that the caller has carrier privileges (see
-     *         {@link TelephonyManager#hasCarrierPrivileges()}).</li>
      * </ul>
      *
      * @param callback The existing {@link RcsProvisioningCallback} to be
@@ -1534,8 +1904,11 @@
      * @see #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)
      * @throws IllegalArgumentException if the subscription associated with
      * this callback is invalid.
+     * @hide
      */
-    @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
             Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
     public void unregisterRcsProvisioningCallback(
             @NonNull RcsProvisioningCallback callback) {
@@ -1556,9 +1929,10 @@
      * {@link RcsProvisioningCallback} may expect to receive
      * {@link RcsProvisioningCallback#onConfigurationReset}, then
      * {@link RcsProvisioningCallback#onConfigurationChanged} when the new
-     * RCS configuration is received and notified by
-     * {@link #notifyRcsAutoConfigurationReceived}
+     * RCS configuration is received and notified by {@link #notifyRcsAutoConfigurationReceived}
+     * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
     public void triggerRcsReconfiguration() {
         try {
diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
index c25ace0..f367e40 100644
--- a/telephony/java/android/telephony/ims/RcsClientConfiguration.java
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
@@ -34,7 +34,7 @@
 
     /**@hide*/
     @StringDef(prefix = "RCS_PROFILE_",
-            value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3})
+            value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3, RCS_PROFILE_2_4})
     public @interface StringRcsProfile {}
 
     /**
@@ -45,6 +45,10 @@
      * RCS profile UP 2.3
      */
     public static final String RCS_PROFILE_2_3 = "UP_2.3";
+    /**
+     * RCS profile UP 2.4
+     */
+    public static final String RCS_PROFILE_2_4 = "UP_2.4";
 
     private String mRcsVersion;
     private String mRcsProfile;
@@ -58,8 +62,8 @@
      * @param rcsVersion The parameter identifies the RCS version supported
      * by the client. Refer to GSMA RCC.07 "rcs_version" parameter.
      * @param rcsProfile Identifies a fixed set of RCS services that are
-     * supported by the client. See {@link #RCS_PROFILE_1_0 } or
-     * {@link #RCS_PROFILE_2_3 }
+     * supported by the client. See {@link #RCS_PROFILE_1_0 },
+     * {@link #RCS_PROFILE_2_3 } or {@link #RCS_PROFILE_2_4 }
      * @param clientVendor Identifies the vendor providing the RCS client.
      * @param clientVersion Identifies the RCS client version. Refer to GSMA
      * RCC.07 "client_version" parameter.
@@ -80,8 +84,8 @@
      * @param rcsVersion The parameter identifies the RCS version supported
      * by the client. Refer to GSMA RCC.07 "rcs_version" parameter.
      * @param rcsProfile Identifies a fixed set of RCS services that are
-     * supported by the client. See {@link #RCS_PROFILE_1_0 } or
-     * {@link #RCS_PROFILE_2_3 }
+     * supported by the client. See {@link #RCS_PROFILE_1_0 },
+     * {@link #RCS_PROFILE_2_3 } or {@link #RCS_PROFILE_2_4 }
      * @param clientVendor Identifies the vendor providing the RCS client.
      * @param clientVersion Identifies the RCS client version. Refer to GSMA
      * RCC.07 "client_version" parameter.
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 9112118..9c36db8 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -221,6 +221,15 @@
         }
 
         /**
+         * Set the entity URI related to the contact whose capabilities were requested.
+         * @param entityUri the 'pres' URL of the PRESENTITY publishing presence document.
+         */
+        public @NonNull PresenceBuilder setEntityUri(@NonNull Uri entityUri) {
+            mCapabilities.mEntityUri = entityUri;
+            return this;
+        }
+
+        /**
          * @return the RcsContactUceCapability instance.
          */
         public @NonNull RcsContactUceCapability build() {
@@ -232,6 +241,7 @@
     private @SourceType int mSourceType;
     private @CapabilityMechanism int mCapabilityMechanism;
     private @RequestResult int mRequestResult;
+    private Uri mEntityUri;
 
     private final Set<String> mFeatureTags = new HashSet<>();
     private final List<RcsContactPresenceTuple> mPresenceTuples = new ArrayList<>();
@@ -248,6 +258,7 @@
         mCapabilityMechanism = in.readInt();
         mSourceType = in.readInt();
         mRequestResult = in.readInt();
+        mEntityUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
         List<String> featureTagList = new ArrayList<>();
         in.readStringList(featureTagList);
         mFeatureTags.addAll(featureTagList);
@@ -260,6 +271,7 @@
         out.writeInt(mCapabilityMechanism);
         out.writeInt(mSourceType);
         out.writeInt(mRequestResult);
+        out.writeParcelable(mEntityUri, flags);
         out.writeStringList(new ArrayList<>(mFeatureTags));
         out.writeParcelableList(mPresenceTuples, flags);
     }
@@ -361,6 +373,15 @@
         return mContactUri;
     }
 
+    /**
+     * Retrieve the entity URI of the contact whose presence information is being requested for.
+     * @return the URI representing the 'pres' URL of the PRESENTITY publishing presence document
+     * or {@code null} if the entity uri does not exist in the presence document.
+     */
+    public @Nullable Uri getEntityUri() {
+        return mEntityUri;
+    }
+
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder("RcsContactUceCapability");
@@ -382,6 +403,13 @@
         builder.append(mSourceType);
         builder.append(", requestResult=");
         builder.append(mRequestResult);
+        if (Build.IS_ENG) {
+            builder.append("entity uri=");
+            builder.append(mEntityUri != null ? mEntityUri : "null");
+        } else {
+            builder.append("entity uri (isNull)=");
+            builder.append(mEntityUri != null ? "XXX" : "null");
+        }
 
         if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
             builder.append(", presenceTuples={");
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 61de3ac..154bb11 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -268,6 +268,13 @@
     @SystemApi
     public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
 
+    /**
+     * A capability update has been requested due to IMS being registered over INTERNET PDN.
+     * @hide
+     */
+    @SystemApi
+    public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12;
+
     /**@hide*/
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "ERROR_", value = {
@@ -282,7 +289,8 @@
             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
             CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
-            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
+            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED,
+            CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN
     })
     public @interface StackPublishTriggerType {}
 
diff --git a/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl
new file mode 100644
index 0000000..63ec4aa
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.telephony.ims.aidl;
+
+/**
+ * Provides callback interface for FeatureProvisioning when a value has changed.
+ *
+ * {@hide}
+ */
+oneway interface IFeatureProvisioningCallback {
+    void onFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned);
+    void onRcsFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index c6966b3..ae6166f 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -32,18 +32,19 @@
  */
 interface IImsServiceController {
     void setListener(IImsServiceControllerListener l);
-    IImsMmTelFeature createMmTelFeature(int slotId);
-    IImsRcsFeature createRcsFeature(int slotId);
+    IImsMmTelFeature createMmTelFeature(int slotId, int subId);
+    IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId);
+    IImsRcsFeature createRcsFeature(int slotId, int subId);
     ImsFeatureConfiguration querySupportedImsFeatures();
     long getImsServiceCapabilities();
     void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
     void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
     // Synchronous call to ensure the ImsService is ready before continuing with feature creation.
     void notifyImsServiceReadyForFeatureCreation();
-    void removeImsFeature(int slotId, int featureType);
-    IImsConfig getConfig(int slotId);
-    IImsRegistration getRegistration(int slotId);
+    void removeImsFeature(int slotId, int featureType, boolean changeSubId);
+    IImsConfig getConfig(int slotId, int subId);
+    IImsRegistration getRegistration(int slotId, int subId);
     ISipTransport getSipTransport(int slotId);
-    oneway void enableIms(int slotId);
-    oneway void disableIms(int slotId);
+    oneway void enableIms(int slotId, int subId);
+    oneway void disableIms(int slotId, int subId);
 }
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 9a3f592..ad2e9e1 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -40,16 +40,25 @@
 import android.telephony.ims.stub.ImsSmsImplBase;
 import android.telephony.ims.stub.ImsUtImplBase;
 import android.util.ArraySet;
+import android.util.Log;
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsUt;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
 
 /**
  * Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
@@ -60,6 +69,7 @@
 public class MmTelFeature extends ImsFeature {
 
     private static final String LOG_TAG = "MmTelFeature";
+    private Executor mExecutor;
 
     /**
      * @hide
@@ -68,160 +78,261 @@
     public MmTelFeature() {
     }
 
+    /**
+     * Create a new MmTelFeature using the Executor specified for methods being called by the
+     * framework.
+     * @param executor The executor for the framework to use when executing the methods overridden
+     * by the implementation of MmTelFeature.
+     * @hide
+     */
+    @SystemApi
+    public MmTelFeature(@NonNull Executor executor) {
+        super();
+        mExecutor = executor;
+    }
+
     private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
 
         @Override
         public void setListener(IImsMmTelListener l) {
-            MmTelFeature.this.setListener(l);
+            executeMethodAsyncNoException(() -> MmTelFeature.this.setListener(l), "setListener");
         }
 
         @Override
         public int getFeatureState() throws RemoteException {
-            try {
-                return MmTelFeature.this.getFeatureState();
-            } catch (Exception e) {
-                throw new RemoteException(e.getMessage());
-            }
+            return executeMethodAsyncForResult(() -> MmTelFeature.this.getFeatureState(),
+                    "getFeatureState");
         }
 
-
         @Override
         public ImsCallProfile createCallProfile(int callSessionType, int callType)
                 throws RemoteException {
-            synchronized (mLock) {
-                try {
-                    return MmTelFeature.this.createCallProfile(callSessionType, callType);
-                } catch (Exception e) {
-                    throw new RemoteException(e.getMessage());
-                }
-            }
+            return executeMethodAsyncForResult(() -> MmTelFeature.this.createCallProfile(
+                    callSessionType, callType), "createCallProfile");
         }
 
         @Override
         public void changeOfferedRtpHeaderExtensionTypes(List<RtpHeaderExtensionType> types)
                 throws RemoteException {
-            synchronized (mLock) {
-                try {
-                    MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(new ArraySet<>(types));
-                } catch (Exception e) {
-                    throw new RemoteException(e.getMessage());
-                }
-            }
+            executeMethodAsync(() -> MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(
+                    new ArraySet<>(types)), "changeOfferedRtpHeaderExtensionTypes");
         }
 
         @Override
         public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
-            synchronized (mLock) {
-                return createCallSessionInterface(profile);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsCallSession result = executeMethodAsyncForResult(() -> {
+                try {
+                    return createCallSessionInterface(profile);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "createCallSession");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public int shouldProcessCall(String[] numbers) {
-            synchronized (mLock) {
-                return MmTelFeature.this.shouldProcessCall(numbers);
+            Integer result = executeMethodAsyncForResultNoException(() ->
+                    MmTelFeature.this.shouldProcessCall(numbers), "shouldProcessCall");
+            if (result != null) {
+                return result.intValue();
+            } else {
+                return PROCESS_CALL_CSFB;
             }
         }
 
         @Override
         public IImsUt getUtInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getUtInterface();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsUt result = executeMethodAsyncForResult(() -> {
+                try {
+                    return MmTelFeature.this.getUtInterface();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "getUtInterface");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public IImsEcbm getEcbmInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getEcbmInterface();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsEcbm result = executeMethodAsyncForResult(() -> {
+                try {
+                    return MmTelFeature.this.getEcbmInterface();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "getEcbmInterface");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
-            synchronized (mLock) {
-                try {
-                    MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
-                } catch (Exception e) {
-                    throw new RemoteException(e.getMessage());
-                }
-            }
+            executeMethodAsync(() -> MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage),
+                    "setUiTtyMode");
         }
 
         @Override
         public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
-            synchronized (mLock) {
-                return MmTelFeature.this.getMultiEndpointInterface();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            IImsMultiEndpoint result = executeMethodAsyncForResult(() -> {
+                try {
+                    return MmTelFeature.this.getMultiEndpointInterface();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return null;
+                }
+            }, "getMultiEndpointInterface");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
             }
+
+            return result;
         }
 
         @Override
         public int queryCapabilityStatus() {
-            return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+            Integer result = executeMethodAsyncForResultNoException(() -> MmTelFeature.this
+                    .queryCapabilityStatus().mCapabilities, "queryCapabilityStatus");
+
+            if (result != null) {
+                return result.intValue();
+            } else {
+                return 0;
+            }
         }
 
         @Override
         public void addCapabilityCallback(IImsCapabilityCallback c) {
-            // no need to lock, structure already handles multithreading.
-            MmTelFeature.this.addCapabilityCallback(c);
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .addCapabilityCallback(c), "addCapabilityCallback");
         }
 
         @Override
         public void removeCapabilityCallback(IImsCapabilityCallback c) {
-            // no need to lock, structure already handles multithreading.
-            MmTelFeature.this.removeCapabilityCallback(c);
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .removeCapabilityCallback(c), "removeCapabilityCallback");
         }
 
         @Override
         public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
                 IImsCapabilityCallback c) {
-            MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .requestChangeEnabledCapabilities(request, c),
+                    "changeCapabilitiesConfiguration");
         }
 
         @Override
         public void queryCapabilityConfiguration(int capability, int radioTech,
                 IImsCapabilityCallback c) {
-            queryCapabilityConfigurationInternal(capability, radioTech, c);
+            executeMethodAsyncNoException(() -> queryCapabilityConfigurationInternal(
+                    capability, radioTech, c), "queryCapabilityConfiguration");
         }
 
         @Override
         public void setSmsListener(IImsSmsListener l) {
-            MmTelFeature.this.setSmsListener(l);
+            executeMethodAsyncNoException(() -> MmTelFeature.this.setSmsListener(l),
+                    "setSmsListener");
         }
 
         @Override
         public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
                 byte[] pdu) {
-            synchronized (mLock) {
-                MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
-            }
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms");
         }
 
         @Override
         public void acknowledgeSms(int token, int messageRef, int result) {
-            synchronized (mLock) {
-                MmTelFeature.this.acknowledgeSms(token, messageRef, result);
-            }
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .acknowledgeSms(token, messageRef, result), "acknowledgeSms");
         }
 
         @Override
         public void acknowledgeSmsReport(int token, int messageRef, int result) {
-            synchronized (mLock) {
-                MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
-            }
+            executeMethodAsyncNoException(() -> MmTelFeature.this
+                    .acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport");
         }
 
         @Override
         public String getSmsFormat() {
-            synchronized (mLock) {
-                return MmTelFeature.this.getSmsFormat();
-            }
+            return executeMethodAsyncForResultNoException(() -> MmTelFeature.this
+                    .getSmsFormat(), "getSmsFormat");
         }
 
         @Override
         public void onSmsReady() {
-            synchronized (mLock) {
-                MmTelFeature.this.onSmsReady();
+            executeMethodAsyncNoException(() -> MmTelFeature.this.onSmsReady(),
+                    "onSmsReady");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResultNoException(Supplier<T> r,
+                String errorLogName) {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                return null;
             }
         }
     };
@@ -283,6 +394,13 @@
         public @interface MmTelCapability {}
 
         /**
+         * Undefined capability type for initialization
+         * This is used to check the upper range of MmTel capability
+         * {@hide}
+         */
+        public static final int CAPABILITY_TYPE_NONE = 0;
+
+        /**
          * This MmTelFeature supports Voice calling (IR.92)
          */
         public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
@@ -308,6 +426,12 @@
         public static final int CAPABILITY_TYPE_CALL_COMPOSER = 1 << 4;
 
         /**
+         * This is used to check the upper range of MmTel capability
+         * {@hide}
+         */
+        public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_CALL_COMPOSER + 1;
+
+        /**
          * @hide
          */
         @Override
@@ -672,7 +796,12 @@
     public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
             throws RemoteException {
         ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
-        return s != null ? s.getServiceImpl() : null;
+        if (s != null) {
+            s.setDefaultExecutor(mExecutor);
+            return s.getServiceImpl();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -713,7 +842,12 @@
      */
     protected IImsUt getUtInterface() throws RemoteException {
         ImsUtImplBase utImpl = getUt();
-        return utImpl != null ? utImpl.getInterface() : null;
+        if (utImpl != null) {
+            utImpl.setDefaultExecutor(mExecutor);
+            return utImpl.getInterface();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -721,7 +855,12 @@
      */
     protected IImsEcbm getEcbmInterface() throws RemoteException {
         ImsEcbmImplBase ecbmImpl = getEcbm();
-        return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null;
+        if (ecbmImpl != null) {
+            ecbmImpl.setDefaultExecutor(mExecutor);
+            return ecbmImpl.getImsEcbm();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -729,7 +868,12 @@
      */
     public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
         ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
-        return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null;
+        if (multiendpointImpl != null) {
+            multiendpointImpl.setDefaultExecutor(mExecutor);
+            return multiendpointImpl.getIImsMultiEndpoint();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -859,4 +1003,16 @@
     public final IImsMmTelFeature getBinder() {
         return mImsMMTelBinder;
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of MmTelFeature.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mExecutor == null) {
+            mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 18cc37d..70e4ef1 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -59,9 +59,7 @@
 /**
  * Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
  * this class and provide implementations of the RcsFeature methods that they support.
- * @hide
  */
-@SystemApi
 public class RcsFeature extends ImsFeature {
 
     private static final String LOG_TAG = "RcsFeature";
@@ -70,7 +68,7 @@
         // Reference the outer class in order to have better test coverage metrics instead of
         // creating a inner class referencing the outer class directly.
         private final RcsFeature mReference;
-        private final Executor mExecutor;
+        private Executor mExecutor;
 
         RcsFeatureBinder(RcsFeature classRef, @CallbackExecutor Executor executor) {
             mReference = classRef;
@@ -186,14 +184,14 @@
      * Contains the capabilities defined and supported by a {@link RcsFeature} in the
      * form of a bitmask. The capabilities that are used in the RcsFeature are
      * defined as:
-     * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
-     * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
+     * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
+     * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
      *
      * The enabled capabilities of this RcsFeature will be set by the framework
-     * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
+     * using {#changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
      * After the capabilities have been set, the RcsFeature may then perform the necessary bring up
      * of the capability and notify the capability status as true using
-     * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
+     * {#notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
      * framework that the capability is available for usage.
      */
     public static class RcsImsCapabilities extends Capabilities {
@@ -227,10 +225,18 @@
         public static final int CAPABILITY_TYPE_PRESENCE_UCE =  1 << 1;
 
         /**
+         * This is used to check the upper range of RCS capability
+         * {@hide}
+         */
+        public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_PRESENCE_UCE + 1;
+
+        /**
          * Create a new {@link RcsImsCapabilities} instance with the provided capabilities.
          * @param capabilities The capabilities that are supported for RCS in the form of a
          * bitfield.
+         * @hide
          */
+        @SystemApi
         public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             super(capabilities);
         }
@@ -243,23 +249,35 @@
             super(capabilities.getMask());
         }
 
+        /**
+         * @hide
+         */
         @Override
+        @SystemApi
         public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             super.addCapabilities(capabilities);
         }
 
+        /**
+         * @hide
+         */
         @Override
+        @SystemApi
         public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             super.removeCapabilities(capabilities);
         }
 
+        /**
+         * @hide
+         */
         @Override
+        @SystemApi
         public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
             return super.isCapable(capabilities);
         }
     }
 
-    private final Executor mExecutor;
+    private Executor mExecutor;
     private final RcsFeatureBinder mImsRcsBinder;
     private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
     private CapabilityExchangeEventListener mCapExchangeEventListener;
@@ -270,13 +288,11 @@
      * Method stubs called from the framework will be called asynchronously. To specify the
      * {@link Executor} that the methods stubs will be called, use
      * {@link RcsFeature#RcsFeature(Executor)} instead.
-     *
-     * @deprecated Use {@link #RcsFeature(Executor)} to create the RcsFeature.
+     * @hide
      */
-    @Deprecated
+    @SystemApi
     public RcsFeature() {
         super();
-        mExecutor = Runnable::run;
         // Run on the Binder threads that call them.
         mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
     }
@@ -286,7 +302,9 @@
      * framework.
      * @param executor The executor for the framework to use when executing the methods overridden
      * by the implementation of RcsFeature.
+     * @hide
      */
+    @SystemApi
     public RcsFeature(@NonNull Executor executor) {
         super();
         if (executor == null) {
@@ -305,7 +323,7 @@
      * @hide
      */
     @Override
-    public void initialize(Context context, int slotId) {
+    public void initialize(@NonNull Context context, @NonNull int slotId) {
         super.initialize(context, slotId);
         // Notify that the RcsFeature is ready.
         mExecutor.execute(() -> onFeatureReady());
@@ -317,8 +335,10 @@
      * requests. To change the status of the capabilities
      * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called.
      * @return A copy of the current RcsFeature capability status.
+     * @hide
      */
     @Override
+    @SystemApi
     public @NonNull final RcsImsCapabilities queryCapabilityStatus() {
         return new RcsImsCapabilities(super.queryCapabilityStatus());
     }
@@ -328,7 +348,9 @@
      * this signals to the framework that the capability has been initialized and is ready.
      * Call {@link #queryCapabilityStatus()} to return the current capability status.
      * @param capabilities The current capability status of the RcsFeature.
+     * @hide
      */
+    @SystemApi
     public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) {
         if (capabilities == null) {
             throw new IllegalArgumentException("RcsImsCapabilities must be non-null!");
@@ -345,7 +367,9 @@
      * @param capability The capability that we are querying the configuration for.
      * @param radioTech The radio technology type that we are querying.
      * @return true if the capability is enabled, false otherwise.
+     * @hide
      */
+    @SystemApi
     public boolean queryCapabilityConfiguration(
             @RcsUceAdapter.RcsImsCapabilityFlag int capability,
             @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
@@ -368,8 +392,10 @@
      * be called for each capability change that resulted in an error.
      * @param request The request to change the capability.
      * @param callback To notify the framework that the result of the capability changes.
+     * @hide
      */
     @Override
+    @SystemApi
     public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
             @NonNull CapabilityCallbackProxy callback) {
         // Base Implementation - Override to provide functionality
@@ -389,7 +415,9 @@
      * event to the framework.
      * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
      * exchange if it is supported by the device.
+     * @hide
      */
+    @SystemApi
     public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
             @NonNull CapabilityExchangeEventListener listener) {
         // Base Implementation, override to implement functionality
@@ -399,20 +427,28 @@
     /**
      * Remove the given CapabilityExchangeImplBase instance.
      * @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed.
+     * @hide
      */
+    @SystemApi
     public void destroyCapabilityExchangeImpl(
             @NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
         // Override to implement the process of destroying RcsCapabilityExchangeImplBase instance.
     }
 
-    /**{@inheritDoc}*/
+    /**{@inheritDoc}
+     * @hide
+     */
     @Override
+    @SystemApi
     public void onFeatureRemoved() {
 
     }
 
-    /**{@inheritDoc}*/
+    /**{@inheritDoc}
+     * @hide
+     */
     @Override
+    @SystemApi
     public void onFeatureReady() {
 
     }
@@ -477,4 +513,17 @@
             return mCapabilityExchangeImpl;
         }
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of RcsFeature.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mImsRcsBinder.mExecutor == null) {
+            mExecutor = executor;
+            mImsRcsBinder.mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index a3a6cb8..e810095 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -30,12 +30,20 @@
 import android.telephony.ims.RtpHeaderExtensionType;
 import android.telephony.ims.aidl.IImsCallSessionListener;
 import android.util.ArraySet;
+import android.util.Log;
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsVideoCallProvider;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Base implementation of IImsCallSession, which implements stub versions of the methods available.
@@ -48,6 +56,8 @@
 // DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
 // will break other implementations of ImsCallSession maintained by other ImsServices.
 public class ImsCallSessionImplBase implements AutoCloseable {
+
+    private static final String LOG_TAG = "ImsCallSessionImplBase";
     /**
      * Notify USSD Mode.
      */
@@ -110,185 +120,235 @@
         }
     }
 
+    private Executor mExecutor = Runnable::run;
+
     // Non-final for injection by tests
     private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
         @Override
         public void close() {
-            ImsCallSessionImplBase.this.close();
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.close(), "close");
         }
 
         @Override
         public String getCallId() {
-            return ImsCallSessionImplBase.this.getCallId();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallId(),
+                    "getCallId");
         }
 
         @Override
         public ImsCallProfile getCallProfile() {
-            return ImsCallSessionImplBase.this.getCallProfile();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallProfile(),
+                    "getCallProfile");
         }
 
         @Override
         public ImsCallProfile getLocalCallProfile() {
-            return ImsCallSessionImplBase.this.getLocalCallProfile();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+                    .getLocalCallProfile(), "getLocalCallProfile");
         }
 
         @Override
         public ImsCallProfile getRemoteCallProfile() {
-            return ImsCallSessionImplBase.this.getRemoteCallProfile();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+                    .getRemoteCallProfile(), "getRemoteCallProfile");
         }
 
         @Override
         public String getProperty(String name) {
-            return ImsCallSessionImplBase.this.getProperty(name);
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getProperty(name),
+                    "getProperty");
         }
 
         @Override
         public int getState() {
-            return ImsCallSessionImplBase.this.getState();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getState(),
+                    "getState");
         }
 
         @Override
         public boolean isInCall() {
-            return ImsCallSessionImplBase.this.isInCall();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isInCall(),
+                    "isInCall");
         }
 
         @Override
         public void setListener(IImsCallSessionListener listener) {
-            ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(
+                    new ImsCallSessionListener(listener)), "setListener");
         }
 
         @Override
         public void setMute(boolean muted) {
-            ImsCallSessionImplBase.this.setMute(muted);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.setMute(muted), "setMute");
         }
 
         @Override
         public void start(String callee, ImsCallProfile profile) {
-            ImsCallSessionImplBase.this.start(callee, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.start(callee, profile), "start");
         }
 
         @Override
         public void startConference(String[] participants, ImsCallProfile profile) throws
                 RemoteException {
-            ImsCallSessionImplBase.this.startConference(participants, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.startConference(participants,
+                    profile), "startConference");
         }
 
         @Override
         public void accept(int callType, ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.accept(callType, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.accept(callType, profile),
+                    "accept");
         }
 
         @Override
         public void deflect(String deflectNumber) {
-            ImsCallSessionImplBase.this.deflect(deflectNumber);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.deflect(deflectNumber),
+                    "deflect");
         }
 
         @Override
         public void reject(int reason) {
-            ImsCallSessionImplBase.this.reject(reason);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.reject(reason), "reject");
         }
 
         @Override
         public void transfer(@NonNull String number, boolean isConfirmationRequired) {
-            ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.transfer(number,
+                    isConfirmationRequired), "transfer");
         }
 
         @Override
         public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
-            ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
-            otherSession.setServiceImpl(transferToSession);
-            ImsCallSessionImplBase.this.transfer(otherSession);
+            executeMethodAsync(() -> {
+                ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
+                otherSession.setServiceImpl(transferToSession);
+                ImsCallSessionImplBase.this.transfer(otherSession);
+            }, "consultativeTransfer");
         }
 
         @Override
         public void terminate(int reason) {
-            ImsCallSessionImplBase.this.terminate(reason);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.terminate(reason), "terminate");
         }
 
         @Override
         public void hold(ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.hold(profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.hold(profile), "hold");
         }
 
         @Override
         public void resume(ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.resume(profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.resume(profile), "resume");
         }
 
         @Override
         public void merge() {
-            ImsCallSessionImplBase.this.merge();
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.merge(), "merge");
         }
 
         @Override
         public void update(int callType, ImsStreamMediaProfile profile) {
-            ImsCallSessionImplBase.this.update(callType, profile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.update(callType, profile),
+                    "update");
         }
 
         @Override
         public void extendToConference(String[] participants) {
-            ImsCallSessionImplBase.this.extendToConference(participants);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.extendToConference(participants),
+                    "extendToConference");
         }
 
         @Override
         public void inviteParticipants(String[] participants) {
-            ImsCallSessionImplBase.this.inviteParticipants(participants);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.inviteParticipants(participants),
+                    "inviteParticipants");
         }
 
         @Override
         public void removeParticipants(String[] participants) {
-            ImsCallSessionImplBase.this.removeParticipants(participants);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.removeParticipants(participants),
+                    "removeParticipants");
         }
 
         @Override
         public void sendDtmf(char c, Message result) {
-            ImsCallSessionImplBase.this.sendDtmf(c, result);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendDtmf(c, result), "sendDtmf");
         }
 
         @Override
         public void startDtmf(char c) {
-            ImsCallSessionImplBase.this.startDtmf(c);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.startDtmf(c), "startDtmf");
         }
 
         @Override
         public void stopDtmf() {
-            ImsCallSessionImplBase.this.stopDtmf();
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.stopDtmf(), "stopDtmf");
         }
 
         @Override
         public void sendUssd(String ussdMessage) {
-            ImsCallSessionImplBase.this.sendUssd(ussdMessage);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendUssd(ussdMessage), "sendUssd");
         }
 
         @Override
         public IImsVideoCallProvider getVideoCallProvider() {
-            return ImsCallSessionImplBase.this.getVideoCallProvider();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+                    .getVideoCallProvider(), "getVideoCallProvider");
         }
 
         @Override
         public boolean isMultiparty() {
-            return ImsCallSessionImplBase.this.isMultiparty();
+            return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isMultiparty(),
+                    "isMultiparty");
         }
 
         @Override
         public void sendRttModifyRequest(ImsCallProfile toProfile) {
-            ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile),
+                    "sendRttModifyRequest");
         }
 
         @Override
         public void sendRttModifyResponse(boolean status) {
-            ImsCallSessionImplBase.this.sendRttModifyResponse(status);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyResponse(status),
+                    "sendRttModifyResponse");
         }
 
         @Override
         public void sendRttMessage(String rttMessage) {
-            ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttMessage(rttMessage),
+                    "sendRttMessage");
         }
 
         @Override
         public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) {
-            ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
-                    new ArraySet<RtpHeaderExtension>(extensions));
+            executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
+                    new ArraySet<RtpHeaderExtension>(extensions)), "sendRtpHeaderExtensions");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                return null;
+            }
         }
     };
 
@@ -674,4 +734,14 @@
     public void setServiceImpl(IImsCallSession serviceImpl) {
         mServiceImpl = serviceImpl;
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsCallSession.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index d75da90..11fc328 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -33,12 +33,21 @@
 import com.android.ims.ImsConfig;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.util.RemoteCallbackListExt;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
 
 /**
  * Controls the modification of IMS specific configurations. For more information on the supported
@@ -81,21 +90,48 @@
         WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
         private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
         private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+        private final Object mLock = new Object();
+        private Executor mExecutor;
 
         @VisibleForTesting
-        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) {
+        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Executor executor) {
+            mExecutor = executor;
             mImsConfigImplBaseWeakReference =
                     new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
         }
 
         @Override
         public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().addImsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().addImsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "addImsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception addImsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().removeImsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().removeImsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "removeImsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception removeImsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         /**
@@ -108,16 +144,34 @@
          * unavailable.
          */
         @Override
-        public synchronized int getConfigInt(int item) throws RemoteException {
-            if (mProvisionedIntValue.containsKey(item)) {
-                return mProvisionedIntValue.get(item);
-            } else {
-                int retVal = getImsConfigImpl().getConfigInt(item);
-                if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
-                    updateCachedValue(item, retVal, false);
+        public int getConfigInt(int item) throws RemoteException {
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            int retVal = executeMethodAsyncForResult(()-> {
+                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+                synchronized (mLock) {
+                    if (mProvisionedIntValue.containsKey(item)) {
+                        return mProvisionedIntValue.get(item);
+                    } else {
+                        try {
+                            returnVal = getImsConfigImpl().getConfigInt(item);
+                            if (returnVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+                                mProvisionedIntValue.put(item, returnVal);
+                            }
+                        } catch (RemoteException e) {
+                            exceptionRef.set(e);
+                            return returnVal;
+                        }
+                    }
                 }
-                return retVal;
+                return returnVal;
+            }, "getConfigInt");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
+                throw exceptionRef.get();
             }
+
+            return retVal;
         }
 
         /**
@@ -129,16 +183,34 @@
          * @return value in String format.
          */
         @Override
-        public synchronized String getConfigString(int item) throws RemoteException {
-            if (mProvisionedStringValue.containsKey(item)) {
-                return mProvisionedStringValue.get(item);
-            } else {
-                String retVal = getImsConfigImpl().getConfigString(item);
-                if (retVal != null) {
-                    updateCachedValue(item, retVal, false);
+        public String getConfigString(int item) throws RemoteException {
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            String retVal = executeMethodAsyncForResult(()-> {
+                String returnVal = null;
+                synchronized (mLock) {
+                    if (mProvisionedStringValue.containsKey(item)) {
+                        returnVal = mProvisionedStringValue.get(item);
+                    } else {
+                        try {
+                            returnVal = getImsConfigImpl().getConfigString(item);
+                            if (returnVal != null) {
+                                mProvisionedStringValue.put(item, returnVal);
+                            }
+                        } catch (RemoteException e) {
+                            exceptionRef.set(e);
+                            return returnVal;
+                        }
+                    }
                 }
-                return retVal;
+                return returnVal;
+            }, "getConfigString");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
+                throw exceptionRef.get();
             }
+
+            return retVal;
         }
 
         /**
@@ -153,14 +225,32 @@
          * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
          */
         @Override
-        public synchronized int setConfigInt(int item, int value) throws RemoteException {
-            mProvisionedIntValue.remove(item);
-            int retVal = getImsConfigImpl().setConfig(item, value);
-            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
-                updateCachedValue(item, value, true);
-            } else {
-                Log.d(TAG, "Set provision value of " + item +
-                        " to " + value + " failed with error code " + retVal);
+        public int setConfigInt(int item, int value) throws RemoteException {
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            int retVal = executeMethodAsyncForResult(()-> {
+                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+                try {
+                    synchronized (mLock) {
+                        mProvisionedIntValue.remove(item);
+                        returnVal = getImsConfigImpl().setConfig(item, value);
+                        if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                            mProvisionedIntValue.put(item, value);
+                        } else {
+                            Log.d(TAG, "Set provision value of " + item
+                                    + " to " + value + " failed with error code " + returnVal);
+                        }
+                    }
+                    notifyImsConfigChanged(item, value);
+                    return returnVal;
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return returnVal;
+                }
+            }, "setConfigInt");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
+                throw exceptionRef.get();
             }
 
             return retVal;
@@ -178,12 +268,30 @@
          * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
          */
         @Override
-        public synchronized int setConfigString(int item, String value)
+        public int setConfigString(int item, String value)
                 throws RemoteException {
-            mProvisionedStringValue.remove(item);
-            int retVal = getImsConfigImpl().setConfig(item, value);
-            if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
-                updateCachedValue(item, value, true);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            int retVal = executeMethodAsyncForResult(()-> {
+                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+                try {
+                    synchronized (mLock) {
+                        mProvisionedStringValue.remove(item);
+                        returnVal = getImsConfigImpl().setConfig(item, value);
+                        if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+                            mProvisionedStringValue.put(item, value);
+                        }
+                    }
+                    notifyImsConfigChanged(item, value);
+                    return returnVal;
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                    return returnVal;
+                }
+            }, "setConfigString");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
+                throw exceptionRef.get();
             }
 
             return retVal;
@@ -191,7 +299,19 @@
 
         @Override
         public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException {
-            getImsConfigImpl().updateImsCarrierConfigs(bundle);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().updateImsCarrierConfigs(bundle);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "updateImsCarrierConfigs");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception updateImsCarrierConfigs");
+                throw exceptionRef.get();
+            }
         }
 
         private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
@@ -206,13 +326,37 @@
         @Override
         public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
                 throws RemoteException {
-            getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyRcsAutoConfigurationReceived");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationReceived");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void notifyRcsAutoConfigurationRemoved()
                 throws RemoteException {
-            getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyRcsAutoConfigurationRemoved");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationRemoved");
+                throw exceptionRef.get();
+            }
         }
 
         private void notifyImsConfigChanged(int item, int value) throws RemoteException {
@@ -223,50 +367,144 @@
             getImsConfigImpl().notifyConfigChanged(item, value);
         }
 
-        protected synchronized void updateCachedValue(int item, int value, boolean notifyChange)
-        throws RemoteException {
-            mProvisionedIntValue.put(item, value);
-            if (notifyChange) {
-                notifyImsConfigChanged(item, value);
+        protected void updateCachedValue(int item, int value) {
+            synchronized (mLock) {
+                mProvisionedIntValue.put(item, value);
             }
         }
 
-        protected synchronized void updateCachedValue(int item, String value,
-                boolean notifyChange) throws RemoteException {
-            mProvisionedStringValue.put(item, value);
-            if (notifyChange) {
-                notifyImsConfigChanged(item, value);
+        protected void updateCachedValue(int item, String value) {
+            synchronized (mLock) {
+                mProvisionedStringValue.put(item, value);
             }
         }
 
         @Override
         public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().addRcsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().addRcsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "addRcsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception addRcsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
-            getImsConfigImpl().removeRcsConfigCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().removeRcsConfigCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "removeRcsConfigCallback");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception removeRcsConfigCallback");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void triggerRcsReconfiguration() throws RemoteException {
-            getImsConfigImpl().triggerAutoConfiguration();
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().triggerAutoConfiguration();
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "triggerRcsReconfiguration");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception triggerRcsReconfiguration");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
-            getImsConfigImpl().setRcsClientConfiguration(rcc);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    getImsConfigImpl().setRcsClientConfiguration(rcc);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "setRcsClientConfiguration");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception setRcsClientConfiguration");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void notifyIntImsConfigChanged(int item, int value) throws RemoteException {
-            notifyImsConfigChanged(item, value);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    notifyImsConfigChanged(item, value);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyIntImsConfigChanged");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyIntImsConfigChanged");
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void notifyStringImsConfigChanged(int item, String value) throws RemoteException {
-            notifyImsConfigChanged(item, value);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(()-> {
+                try {
+                    notifyImsConfigChanged(item, value);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "notifyStringImsConfigChanged");
+
+            if (exceptionRef.get() != null) {
+                Log.d(TAG, "ImsConfigImplBase Exception notifyStringImsConfigChanged");
+                throw exceptionRef.get();
+            }
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
         }
     }
 
@@ -303,15 +541,24 @@
     ImsConfigStub mImsConfigStub;
 
     /**
-     * Used for compatibility between older versions of the ImsService.
+     * Create a ImsConfig using the Executor specified for methods being called by the
+     * framework.
+     * @param executor The executor for the framework to use when executing the methods overridden
+     * by the implementation of ImsConfig.
+     */
+    public ImsConfigImplBase(@NonNull Executor executor) {
+        mImsConfigStub = new ImsConfigStub(this, executor);
+    }
+
+    /**
      * @hide
      */
-    public ImsConfigImplBase(Context context) {
-        mImsConfigStub = new ImsConfigStub(this);
+    public ImsConfigImplBase(@NonNull Context context) {
+        mImsConfigStub = new ImsConfigStub(this, null);
     }
 
     public ImsConfigImplBase() {
-        mImsConfigStub = new ImsConfigStub(this);
+        mImsConfigStub = new ImsConfigStub(this, null);
     }
 
     /**
@@ -427,8 +674,10 @@
      * @param value in Integer format.
      */
     public final void notifyProvisionedValueChanged(int item, int value) {
+        mImsConfigStub.updateCachedValue(item, value);
+
         try {
-            mImsConfigStub.updateCachedValue(item, value, true);
+            mImsConfigStub.notifyImsConfigChanged(item, value);
         } catch (RemoteException e) {
             Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
         }
@@ -443,8 +692,10 @@
      * @param value in String format.
      */
     public final void notifyProvisionedValueChanged(int item, String value) {
+        mImsConfigStub.updateCachedValue(item, value);
+
         try {
-        mImsConfigStub.updateCachedValue(item, value, true);
+            mImsConfigStub.notifyImsConfigChanged(item, value);
         } catch (RemoteException e) {
             Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
         }
@@ -582,4 +833,16 @@
             }
         });
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsConfig.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mImsConfigStub.mExecutor == null) {
+            mImsConfigStub.mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 8ad40ed..84b2253 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -16,14 +16,21 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsEcbmListener;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
+
 
 /**
  * Base implementation of ImsEcbm, which implements stub versions of the methods
@@ -40,10 +47,12 @@
 
     private final Object mLock = new Object();
     private IImsEcbmListener mListener;
+    private Executor mExecutor = Runnable::run;
+
     private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
         @Override
         public void setListener(IImsEcbmListener listener) {
-            synchronized (mLock) {
+            executeMethodAsync(() -> {
                 if (mListener != null && !mListener.asBinder().isBinderAlive()) {
                     Log.w(TAG, "setListener: discarding dead Binder");
                     mListener = null;
@@ -62,12 +71,25 @@
                             + "listener");
                     mListener = listener;
                 }
-            }
+            }, "setListener");
         }
 
         @Override
         public void exitEmergencyCallbackMode() {
-            ImsEcbmImplBase.this.exitEmergencyCallbackMode();
+            executeMethodAsync(() -> ImsEcbmImplBase.this.exitEmergencyCallbackMode(),
+                    "exitEmergencyCallbackMode");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsEcbmImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
         }
     };
 
@@ -123,4 +145,14 @@
             }
         }
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsEcbm.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index ec1c7b3..a723cd8 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.ims.ImsExternalCallState;
@@ -23,9 +24,14 @@
 
 import com.android.ims.internal.IImsExternalCallStateListener;
 import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
 
 /**
  * Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
@@ -43,11 +49,13 @@
 
     private IImsExternalCallStateListener mListener;
     private final Object mLock = new Object();
+    private Executor mExecutor = Runnable::run;
+
     private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
 
         @Override
         public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
-            synchronized (mLock) {
+            executeMethodAsync(() -> {
                 if (mListener != null && !mListener.asBinder().isBinderAlive()) {
                     Log.w(TAG, "setListener: discarding dead Binder");
                     mListener = null;
@@ -67,12 +75,25 @@
                             + "listener");
                     mListener = listener;
                 }
-            }
+            }, "setListener");
         }
 
         @Override
         public void requestImsExternalCallStateInfo() throws RemoteException {
-            ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo();
+            executeMethodAsync(() -> ImsMultiEndpointImplBase.this
+                    .requestImsExternalCallStateInfo(), "requestImsExternalCallStateInfo");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsMultiEndpointImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
         }
     };
 
@@ -108,4 +129,14 @@
     public void requestImsExternalCallStateInfo() {
         Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsMultiEndpoint.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 02bcdec..ac5565b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -31,10 +31,18 @@
 import android.util.Log;
 
 import com.android.internal.telephony.util.RemoteCallbackListExt;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.internal.util.ArrayUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
 
 /**
  * Controls IMS registration for this ImsService and notifies the framework when the IMS
@@ -42,9 +50,7 @@
  * <p>
  * Note: There is no guarantee on the thread that the calls from the framework will be called on. It
  * is the implementors responsibility to handle moving the calls to a working thread if required.
- * @hide
  */
-@SystemApi
 public class ImsRegistrationImplBase {
 
     private static final String LOG_TAG = "ImsRegistrationImplBase";
@@ -85,6 +91,12 @@
      */
     public static final int REGISTRATION_TECH_NR = 3;
 
+    /**
+     * This is used to check the upper range of registration tech
+     * {@hide}
+     */
+    public static final int REGISTRATION_TECH_MAX = REGISTRATION_TECH_NR + 1;
+
     // Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current
     // state.
     // The unknown state is set as the initialization state. This is so that we do not call back
@@ -92,39 +104,118 @@
     // yet.
     private static final int REGISTRATION_STATE_UNKNOWN = -1;
 
+    private Executor mExecutor;
+
+    /**
+     * Create a new ImsRegistration.
+     * <p>
+     * Method stubs called from the framework will be called asynchronously. To specify the
+     * {@link Executor} that the methods stubs will be called, use
+     * {@link ImsRegistrationImplBase#ImsRegistrationImplBase(Executor)} instead.
+     * @hide This API is not part of the Android public SDK API
+     */
+    @SystemApi
+    public ImsRegistrationImplBase() {
+        super();
+    }
+
+    /**
+     * Create a ImsRegistration using the Executor specified for methods being called by the
+     * framework.
+     * @param executor The executor for the framework to use when executing the methods overridden
+     * by the implementation of ImsRegistration.
+     * @hide This API is not part of the Android public SDK API
+     */
+    @SystemApi
+    public ImsRegistrationImplBase(@NonNull Executor executor) {
+        super();
+        mExecutor = executor;
+    }
+
     private final IImsRegistration mBinder = new IImsRegistration.Stub() {
 
         @Override
         public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
-            synchronized (mLock) {
-                return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE
-                        : mRegistrationAttributes.getRegistrationTechnology();
-            }
+            return executeMethodAsyncForResult(() -> (mRegistrationAttributes == null)
+                    ? REGISTRATION_TECH_NONE : mRegistrationAttributes.getRegistrationTechnology(),
+                    "getRegistrationTechnology");
         }
 
         @Override
         public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
-            ImsRegistrationImplBase.this.addRegistrationCallback(c);
+            AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+            executeMethodAsync(() -> {
+                try {
+                    ImsRegistrationImplBase.this.addRegistrationCallback(c);
+                } catch (RemoteException e) {
+                    exceptionRef.set(e);
+                }
+            }, "addRegistrationCallback");
+
+            if (exceptionRef.get() != null) {
+                throw exceptionRef.get();
+            }
         }
 
         @Override
         public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
-            ImsRegistrationImplBase.this.removeRegistrationCallback(c);
+            executeMethodAsync(() -> ImsRegistrationImplBase.this.removeRegistrationCallback(c),
+                    "removeRegistrationCallback");
         }
 
         @Override
         public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
-            ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason);
+            executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+                    .triggerFullNetworkRegistration(sipCode, sipReason),
+                    "triggerFullNetworkRegistration");
         }
 
         @Override
         public void triggerUpdateSipDelegateRegistration() {
-            ImsRegistrationImplBase.this.updateSipDelegateRegistration();
+            executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+                    .updateSipDelegateRegistration(), "triggerUpdateSipDelegateRegistration");
         }
 
         @Override
         public void triggerSipDelegateDeregistration() {
-            ImsRegistrationImplBase.this.triggerSipDelegateDeregistration();
+            executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+                    .triggerSipDelegateDeregistration(), "triggerSipDelegateDeregistration");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
         }
     };
 
@@ -166,7 +257,9 @@
      * If the SIP delegate feature tag configuration has changed, then this method will be
      * called in order to let the ImsService know that it can pick up these changes in the IMS
      * registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public void updateSipDelegateRegistration() {
         // Stub implementation, ImsService should implement this
     }
@@ -182,7 +275,9 @@
      * <p>
      * This should not affect the registration of features managed by the ImsService itself, such as
      * feature tags related to MMTEL registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public void triggerSipDelegateDeregistration() {
         // Stub implementation, ImsService should implement this
     }
@@ -200,7 +295,9 @@
      *    be carrier specific.
      * @param sipReason The reason associated with the SIP error code. {@code null} if there was no
      *    reason associated with the error.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public void triggerFullNetworkRegistration(@IntRange(from = 100, to = 699) int sipCode,
             @Nullable String sipReason) {
         // Stub implementation, ImsService should implement this
@@ -211,7 +308,9 @@
      * Notify the framework that the device is connected to the IMS network.
      *
      * @param imsRadioTech the radio access technology.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
         onRegistered(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
     }
@@ -220,7 +319,9 @@
      * Notify the framework that the device is connected to the IMS network.
      *
      * @param attributes The attributes associated with the IMS registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
         updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERED);
         mCallbacks.broadcastAction((c) -> {
@@ -236,7 +337,9 @@
      * Notify the framework that the device is trying to connect the IMS network.
      *
      * @param imsRadioTech the radio access technology.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
         onRegistering(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
     }
@@ -245,7 +348,9 @@
      * Notify the framework that the device is trying to connect the IMS network.
      *
      * @param attributes The attributes associated with the IMS registration.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onRegistering(@NonNull ImsRegistrationAttributes attributes) {
         updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERING);
         mCallbacks.broadcastAction((c) -> {
@@ -272,7 +377,9 @@
      * result.
      *
      * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onDeregistered(ImsReasonInfo info) {
         updateToDisconnectedState(info);
         // ImsReasonInfo should never be null.
@@ -293,7 +400,9 @@
      * {@link #REGISTRATION_TECH_LTE}, {@link #REGISTRATION_TECH_IWLAN} and
      * {@link #REGISTRATION_TECH_CROSS_SIM}.
      * @param info The {@link ImsReasonInfo} for the failure to change technology.
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
             ImsReasonInfo info) {
         final ImsReasonInfo reasonInfo = (info != null) ? info : new ImsReasonInfo();
@@ -312,7 +421,9 @@
      *
      * The {@link Uri}s are not guaranteed to be different between subsequent calls.
      * @param uris changed uris
+     * @hide This API is not part of the Android public SDK API
      */
+    @SystemApi
     public final void onSubscriberAssociatedUriChanged(Uri[] uris) {
         synchronized (mLock) {
             mUris = ArrayUtils.cloneOrNull(uris);
@@ -394,4 +505,16 @@
             onSubscriberAssociatedUriChanged(c, uris);
         }
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of Registration.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mExecutor == null) {
+            mExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index eb3e8ed..11cdeed 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -27,10 +27,17 @@
 
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsUtListener;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 /**
  * Base implementation of IMS UT interface, which implements stubs. Override these methods to
@@ -119,96 +126,108 @@
      */
     public static final int INVALID_RESULT = -1;
 
+    private Executor mExecutor = Runnable::run;
+
     private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
         private final Object mLock = new Object();
         private ImsUtListener mUtListener;
 
         @Override
         public void close() throws RemoteException {
-            ImsUtImplBase.this.close();
+            executeMethodAsync(() ->ImsUtImplBase.this.close(), "close");
         }
 
         @Override
         public int queryCallBarring(int cbType) throws RemoteException {
-            return ImsUtImplBase.this.queryCallBarring(cbType);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallBarring(cbType),
+                    "queryCallBarring");
         }
 
         @Override
         public int queryCallForward(int condition, String number) throws RemoteException {
-            return ImsUtImplBase.this.queryCallForward(condition, number);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallForward(
+                    condition, number), "queryCallForward");
         }
 
         @Override
         public int queryCallWaiting() throws RemoteException {
-            return ImsUtImplBase.this.queryCallWaiting();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallWaiting(),
+                    "queryCallWaiting");
         }
 
         @Override
         public int queryCLIR() throws RemoteException {
-            return ImsUtImplBase.this.queryCLIR();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIR(), "queryCLIR");
         }
 
         @Override
         public int queryCLIP() throws RemoteException {
-            return ImsUtImplBase.this.queryCLIP();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIP(), "queryCLIP");
         }
 
         @Override
         public int queryCOLR() throws RemoteException {
-            return ImsUtImplBase.this.queryCOLR();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLR(), "queryCOLR");
         }
 
         @Override
         public int queryCOLP() throws RemoteException {
-            return ImsUtImplBase.this.queryCOLP();
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLP(), "queryCOLP");
         }
 
         @Override
         public int transact(Bundle ssInfo) throws RemoteException {
-            return ImsUtImplBase.this.transact(ssInfo);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.transact(ssInfo),
+                    "transact");
         }
 
         @Override
         public int updateCallBarring(int cbType, int action, String[] barrList) throws
                 RemoteException {
-            return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallBarring(
+                    cbType, action, barrList), "updateCallBarring");
         }
 
         @Override
         public int updateCallForward(int action, int condition, String number, int serviceClass,
                 int timeSeconds) throws RemoteException {
-            return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass,
-                    timeSeconds);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallForward(
+                    action, condition, number, serviceClass, timeSeconds), "updateCallForward");
         }
 
         @Override
         public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
-            return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallWaiting(
+                    enable, serviceClass), "updateCallWaiting");
         }
 
         @Override
         public int updateCLIR(int clirMode) throws RemoteException {
-            return ImsUtImplBase.this.updateCLIR(clirMode);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIR(clirMode),
+                    "updateCLIR");
         }
 
         @Override
         public int updateCLIP(boolean enable) throws RemoteException {
-            return ImsUtImplBase.this.updateCLIP(enable);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIP(enable),
+                    "updateCLIP");
         }
 
         @Override
         public int updateCOLR(int presentation) throws RemoteException {
-            return ImsUtImplBase.this.updateCOLR(presentation);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLR(presentation),
+                    "updateCOLR");
         }
 
         @Override
         public int updateCOLP(boolean enable) throws RemoteException {
-            return ImsUtImplBase.this.updateCOLP(enable);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLP(enable),
+                    "updateCOLP");
         }
 
         @Override
         public void setListener(IImsUtListener listener) throws RemoteException {
-            synchronized (mLock) {
+            executeMethodAsync(() -> {
                 if (mUtListener != null
                         && !mUtListener.getListenerInterface().asBinder().isBinderAlive()) {
                     Log.w(TAG, "setListener: discarding dead Binder");
@@ -229,29 +248,59 @@
                             + "listener");
                     mUtListener = new ImsUtListener(listener);
                 }
-            }
 
-            ImsUtImplBase.this.setListener(mUtListener);
+                ImsUtImplBase.this.setListener(mUtListener);
+            }, "setListener");
         }
 
         @Override
         public int queryCallBarringForServiceClass(int cbType, int serviceClass)
                 throws RemoteException {
-            return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+                    .queryCallBarringForServiceClass(cbType, serviceClass),
+                    "queryCallBarringForServiceClass");
         }
 
         @Override
         public int updateCallBarringForServiceClass(int cbType, int action,
                 String[] barrList, int serviceClass) throws RemoteException {
-            return ImsUtImplBase.this.updateCallBarringForServiceClass(
-                    cbType, action, barrList, serviceClass);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+                    .updateCallBarringForServiceClass(cbType, action, barrList, serviceClass),
+                    "updateCallBarringForServiceClass");
         }
 
         @Override
         public int updateCallBarringWithPassword(int cbType, int action, String[] barrList,
                 int serviceClass, String password) throws RemoteException {
-            return ImsUtImplBase.this.updateCallBarringWithPassword(
-                    cbType, action, barrList, serviceClass, password);
+            return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+                    .updateCallBarringWithPassword(cbType, action, barrList, serviceClass,
+                    password), "updateCallBarringWithPassword");
+        }
+
+        // Call the methods with a clean calling identity on the executor and wait indefinitely for
+        // the future to return.
+        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+            try {
+                CompletableFuture.runAsync(
+                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+            } catch (CancellationException | CompletionException e) {
+                Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
+        }
+
+        private <T> T executeMethodAsyncForResult(Supplier<T> r,
+                String errorLogName) throws RemoteException {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(
+                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+            try {
+                return future.get();
+            } catch (ExecutionException | InterruptedException e) {
+                Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
+                        + e.getMessage());
+                throw new RemoteException(e.getMessage());
+            }
         }
     };
 
@@ -470,4 +519,14 @@
     public IImsUt getInterface() {
         return mServiceImpl;
     }
+
+    /**
+     * Set default Executor from MmTelFeature.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of ImsUT.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index 13ea9973..52538cb 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -86,10 +86,21 @@
         }
     };
 
-    private final Executor mBinderExecutor;
+    private Executor mBinderExecutor;
     private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
 
     /**
+     * Create a new SipTransport.
+     * <p>
+     * Method stubs called from the framework will be called asynchronously. To specify the
+     * {@link Executor} that the methods stubs will be called, use
+     * {@link SipTransportImplBase#SipTransportImplBase(Executor)} instead.
+     */
+    public SipTransportImplBase() {
+        super();
+    }
+
+    /**
      * Create an implementation of SipTransportImplBase.
      *
      * @param executor The executor that remote calls from the framework will be called on. This
@@ -212,4 +223,16 @@
     public ISipTransport getBinder() {
         return mSipTransportImpl;
     }
+
+    /**
+     * Set default Executor from ImsService.
+     * @param executor The default executor for the framework to use when executing the methods
+     * overridden by the implementation of SipTransport.
+     * @hide
+     */
+    public final void setDefaultExecutor(@NonNull Executor executor) {
+        if (mBinderExecutor == null) {
+            mBinderExecutor = executor;
+        }
+    }
 }
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
index f5f67bd..416096b 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
@@ -23,11 +23,11 @@
  * {@hide}
  */
 oneway interface IImsServiceFeatureCallback {
-    void imsFeatureCreated(in ImsFeatureContainer feature);
+    void imsFeatureCreated(in ImsFeatureContainer feature, int subId);
     // Reason defined in FeatureConnector.UnavailableReason
     void imsFeatureRemoved(int reason);
     // Status defined in ImsFeature.ImsState.
-    void imsStatusChanged(int status);
+    void imsStatusChanged(int status, int subId);
     //Capabilities defined in ImsService.ImsServiceCapability
     void updateCapabilities(long capabilities);
 }
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 409c838..2470887 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -114,6 +114,7 @@
     public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 54;
     public static final int EVENT_SIM_STATE_UPDATED = BASE + 55;
     public static final int EVENT_APN_UNTHROTTLED = BASE + 56;
+    public static final int EVENT_TRAFFIC_DESCRIPTORS_UPDATED = BASE + 57;
 
     /***** Constants *****/
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 167aa07..0ac7cf9 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -55,6 +55,7 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.RcsClientConfiguration;
 import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.aidl.IFeatureProvisioningCallback;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
@@ -2027,6 +2028,18 @@
     void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
 
     /**
+     * Register an IMS provisioning change callback with Telephony.
+     */
+    void registerFeatureProvisioningChangedCallback(int subId,
+            IFeatureProvisioningCallback callback);
+
+    /**
+     * unregister an existing IMS provisioning change callback.
+     */
+    void unregisterFeatureProvisioningChangedCallback(int subId,
+            IFeatureProvisioningCallback callback);
+
+    /**
      * Set the provisioning status for the IMS MmTel capability using the specified subscription.
      */
     void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
@@ -2040,19 +2053,12 @@
     /**
      * Get the provisioning status for the IMS Rcs capability specified.
      */
-    boolean getRcsProvisioningStatusForCapability(int subId, int capability);
+    boolean getRcsProvisioningStatusForCapability(int subId, int capability, int tech);
 
     /**
      * Set the provisioning status for the IMS Rcs capability using the specified subscription.
      */
-    void setRcsProvisioningStatusForCapability(int subId, int capability,
-            boolean isProvisioned);
-
-    /** Is the capability and tech flagged as provisioned in the cache */
-    boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech);
-
-    /** Set the provisioning for the capability and tech in the cache */
-    void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech,
+    void setRcsProvisioningStatusForCapability(int subId, int capability, int tech,
             boolean isProvisioned);
 
     /**
@@ -2555,4 +2561,18 @@
      * @return the service name of the modem service which bind to.
      */
     String getModemService();
+
+    /**
+     * Is Provisioning required for capability
+     * @return true if provisioning is required for the MMTEL capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    boolean isProvisioningRequiredForCapability(int subId, int capability, int tech);
+
+    /**
+     * Is RCS Provisioning required for capability
+     * @return true if provisioning is required for the RCS capability and IMS
+     * registration technology specified, false if it is not required.
+     */
+    boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index ba95841..39ab7eb 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -592,6 +592,7 @@
     int RIL_UNSOL_UNTHROTTLE_APN = 1052;
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_CHANGED = 1053;
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED = 1054;
+    int RIL_UNSOL_SLICING_CONFIG_CHANGED = 1055;
 
     /* The following unsols are not defined in RIL.h */
     int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 97ebba6..527159a 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -26,7 +26,19 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     //   SPDX-license-identifier-CPL-1.0
-    default_applicable_licenses: ["frameworks_base_license"],
+    default_applicable_licenses: ["frameworks_base_test-base_license"],
+}
+
+license {
+    name: "frameworks_base_test-base_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-CPL-1.0",
+    ],
+    license_text: [
+        "src/junit/cpl-v10.html",
+    ],
 }
 
 java_sdk_library {
@@ -60,11 +72,16 @@
 
 // Build the android.test.base_static library
 // ==========================================
-// This is only intended for inclusion in the android.test.runner-minus-junit,
-// robolectric_android-all-stub and repackaged.android.test.* libraries.
+// This is only intended for use by the android.test.runner-minus-junit
+// library.
+//
 // Must not be used elsewhere.
+//
 java_library_static {
     name: "android.test.base_static",
+    visibility: [
+        "//frameworks/base/test-runner",
+    ],
     installable: false,
 
     srcs: [":android-test-base-sources"],
@@ -79,28 +96,10 @@
     sdk_version: "current",
 }
 
-// Build the repackaged.android.test.base library
-// ==============================================
-// This contains repackaged versions of the classes from
-// android.test.base.
-java_library_static {
-    name: "repackaged.android.test.base",
-
-    sdk_version: "current",
-    static_libs: ["android.test.base_static"],
-
-    jarjar_rules: "jarjar-rules.txt",
-    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
-    java_version: "1.8",
-}
-
 // Build the android.test.base-minus-junit library
 // ===============================================
 // This contains the android.test classes from android.test.base plus
-// the com.android.internal.util.Predicate[s] classes. This is only
-// intended for inclusion in android.test.legacy and in
-// android.test.base-hiddenapi-annotations to avoid a dependency cycle and must
-// not be used elsewhere.
+// the com.android.internal.util.Predicate[s] classes.
 java_library_static {
     name: "android.test.base-minus-junit",
 
diff --git a/test-base/jarjar-rules.txt b/test-base/jarjar-rules.txt
deleted file mode 100644
index fd8555c..0000000
--- a/test-base/jarjar-rules.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-rule junit.** repackaged.junit.@1
-rule android.test.** repackaged.android.test.@1
-rule com.android.internal.util.** repackaged.com.android.internal.util.@1
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index 0f56bb3..13a5dac 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -18,12 +18,19 @@
 // =====================================
 package {
     // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    //   SPDX-license-identifier-CPL-1.0
-    default_applicable_licenses: ["frameworks_base_license"],
+    default_applicable_licenses: ["frameworks_base_test-runner_license"],
+}
+
+license {
+    name: "frameworks_base_test-runner_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-CPL-1.0",
+    ],
+    license_text: [
+        "src/junit/cpl-v10.html",
+    ],
 }
 
 java_sdk_library {
@@ -72,32 +79,6 @@
     ],
 }
 
-// Build the repackaged.android.test.runner library
-// ================================================
-java_library_static {
-    name: "repackaged.android.test.runner",
-
-    srcs: [":android-test-runner-sources"],
-    exclude_srcs: [
-        "src/android/test/ActivityUnitTestCase.java",
-        "src/android/test/ApplicationTestCase.java",
-        "src/android/test/IsolatedContext.java",
-        "src/android/test/ProviderTestCase.java",
-        "src/android/test/ProviderTestCase2.java",
-        "src/android/test/RenamingDelegatingContext.java",
-        "src/android/test/ServiceTestCase.java",
-    ],
-
-    sdk_version: "current",
-    libs: [
-        "android.test.base_static",
-    ],
-
-    jarjar_rules: "jarjar-rules.txt",
-    // Pin java_version until jarjar is certified to support later versions. http://b/72703434
-    java_version: "1.8",
-}
-
 // Make the current.txt available for use by the cts/tests/signature tests.
 // ========================================================================
 filegroup {
diff --git a/test-runner/jarjar-rules.txt b/test-runner/jarjar-rules.txt
deleted file mode 120000
index f6f7913..0000000
--- a/test-runner/jarjar-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
-../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.bp
new file mode 100644
index 0000000..4fff969
--- /dev/null
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "frameworks_base_license",
+    ],
+}
+
+android_test {
+    name: "SmartCamera",
+    optimize: {
+        enabled: false,
+    },
+    // comment it out for now since we need use some hidden APIs
+    sdk_version: "current",
+    static_libs: ["android-ex-camera2"],
+    srcs: [
+        "src/**/*.java",
+    ],
+    jni_libs: ["libsmartcamera_jni"],
+}
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.mk
deleted file mode 100644
index 6003628..0000000
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ifneq ($(TARGET_BUILD_JAVA_SUPPORT_LEVEL),)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# comment it out for now since we need use some hidden APIs
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2
-
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    $(call all-renderscript-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmartCamera
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../NOTICE
-LOCAL_JNI_SHARED_LIBRARIES := libsmartcamera_jni
-
-include $(BUILD_PACKAGE)
-
-# Include packages in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
-endif
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.bp
new file mode 100644
index 0000000..5edb1de
--- /dev/null
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "frameworks_base_license",
+    ],
+}
+
+android_test {
+    name: "SmartCamera-tests",
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
+    libs: ["android.test.base"],
+    static_libs: [
+        "guava",
+        "junit",
+    ],
+    optimize: {
+        enabled: false,
+    },
+    instrumentation_for: "SmartCamera",
+}
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
deleted file mode 100644
index c23d593..0000000
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PACKAGE_NAME := SmartCamera-tests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_SRC_FILES += $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := guava junit
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_INSTRUMENTATION_FOR := SmartCamera
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CanvasCompare/Android.bp b/tests/CanvasCompare/Android.bp
new file mode 100644
index 0000000..9883115
--- /dev/null
+++ b/tests/CanvasCompare/Android.bp
@@ -0,0 +1,63 @@
+//
+// 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 {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: [
+        "frameworks_base_license",
+    ],
+}
+
+android_test {
+    name: "CanvasCompare",
+    srcs: [
+        "src/**/*.java",
+        ":CanvasCompare-rscript{CanvasCompare.srcjar}",
+    ],
+    resource_zips: [
+        ":CanvasCompare-rscript{CanvasCompare.res.zip}",
+    ],
+    platform_apis: true,
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+}
+
+genrule {
+    name: "CanvasCompare-rscript",
+    srcs: [
+        "src/**/*.rscript",
+        ":rs_script_api",
+        ":rs_clang_headers",
+    ],
+    tools: [
+        "llvm-rs-cc",
+        "soong_zip",
+    ],
+    out: [
+        "CanvasCompare.srcjar",
+        "CanvasCompare.res.zip",
+    ],
+    cmd: "for f in $(locations src/**/*.rscript); do " +
+        "  $(location llvm-rs-cc) -o $(genDir)/res/raw -p $(genDir)/src " +
+        "  -I $$(dirname $$(echo $(locations :rs_script_api) | awk '{ print $$1 }')) " +
+        "  -I $$(dirname $$(echo $(locations :rs_clang_headers) | awk '{ print $$1 }')) $${f}; " +
+        "done && " +
+        "$(location soong_zip) -srcjar -o $(location CanvasCompare.srcjar) -C $(genDir)/src -D $(genDir)/src &&" +
+        "$(location soong_zip) -o $(location CanvasCompare.res.zip) -C $(genDir)/res -D $(genDir)/res",
+}
diff --git a/tests/CanvasCompare/Android.mk b/tests/CanvasCompare/Android.mk
deleted file mode 100644
index b82ae65..0000000
--- a/tests/CanvasCompare/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
-
-LOCAL_PACKAGE_NAME := CanvasCompare
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE  := $(LOCAL_PATH)/../../NOTICE
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
index 4ec86b186..56848b8 100644
--- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -15,20 +15,19 @@
  */
 package com.android.tests.dataidle;
 
+import static android.net.NetworkStats.METERED_YES;
+
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
 import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStats;
-import android.net.NetworkStats.Entry;
 import android.net.NetworkTemplate;
-import android.net.TrafficStats;
 import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.telephony.TelephonyManager;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
+import java.util.Set;
+
 /**
  * A test that dumps data usage to instrumentation out, used for measuring data usage for idle
  * devices.
@@ -36,7 +35,7 @@
 public class DataIdleTest extends InstrumentationTestCase {
 
     private TelephonyManager mTelephonyManager;
-    private INetworkStatsService mStatsService;
+    private NetworkStatsManager mStatsManager;
 
     private static final String LOG_TAG = "DataIdleTest";
     private final static int INSTRUMENTATION_IN_PROGRESS = 2;
@@ -44,8 +43,7 @@
     protected void setUp() throws Exception {
         super.setUp();
         Context c = getInstrumentation().getTargetContext();
-        mStatsService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+        mStatsManager = c.getSystemService(NetworkStatsManager.class);
         mTelephonyManager = (TelephonyManager) c.getSystemService(Context.TELEPHONY_SERVICE);
     }
 
@@ -53,7 +51,9 @@
      * Test that dumps all the data usage metrics for wifi to instrumentation out.
      */
     public void testWifiIdle() {
-        NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard();
+        final NetworkTemplate template = new NetworkTemplate
+                .Builder(NetworkTemplate.MATCH_WIFI)
+                .build();
         fetchStats(template);
     }
 
@@ -61,8 +61,11 @@
      * Test that dumps all the data usage metrics for all mobile to instrumentation out.
      */
     public void testMobile() {
-        String subscriberId = mTelephonyManager.getSubscriberId();
-        NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
+        final String subscriberId = mTelephonyManager.getSubscriberId();
+        NetworkTemplate template = new NetworkTemplate
+                .Builder(NetworkTemplate.MATCH_MOBILE)
+                .setMeteredness(METERED_YES)
+                .setSubscriberIds(Set.of(subscriberId)).build();
         fetchStats(template);
     }
 
@@ -72,49 +75,26 @@
      * @param template {@link NetworkTemplate} to match.
      */
     private void fetchStats(NetworkTemplate template) {
-        INetworkStatsSession session = null;
         try {
-            mStatsService.forceUpdate();
-            session = mStatsService.openSession();
-            final NetworkStats stats = session.getSummaryForAllUid(
-                    template, Long.MIN_VALUE, Long.MAX_VALUE, false);
-            reportStats(stats);
-        } catch (RemoteException e) {
+            mStatsManager.forceUpdate();
+            final NetworkStats.Bucket bucket =
+                    mStatsManager.querySummaryForDevice(template, Long.MIN_VALUE, Long.MAX_VALUE);
+            reportStats(bucket);
+        } catch (RuntimeException e) {
             Log.w(LOG_TAG, "Failed to fetch network stats.");
-        } finally {
-            TrafficStats.closeQuietly(session);
         }
     }
 
     /**
      * Print network data usage stats to instrumentation out
-     * @param stats {@link NetworkorStats} to print
+     * @param bucket {@link NetworkStats} to print
      */
-    void reportStats(NetworkStats stats) {
+    void reportStats(NetworkStats.Bucket bucket) {
         Bundle result = new Bundle();
-        long rxBytes = 0;
-        long txBytes = 0;
-        long rxPackets = 0;
-        long txPackets = 0;
-        for (int i = 0; i < stats.size(); ++i) {
-            // Label will be iface_uid_tag_set
-            Entry  statsEntry = stats.getValues(i, null);
-            // Debugging use.
-            /*
-            String labelTemplate = String.format("%s_%d_%d_%d", statsEntry.iface, statsEntry.uid,
-                    statsEntry.tag, statsEntry.set) + "_%s";
-            result.putLong(String.format(labelTemplate, "rxBytes"), statsEntry.rxBytes);
-            result.putLong(String.format(labelTemplate, "txBytes"), statsEntry.txBytes);
-            */
-            rxPackets += statsEntry.rxPackets;
-            rxBytes += statsEntry.rxBytes;
-            txPackets += statsEntry.txPackets;
-            txBytes += statsEntry.txBytes;
-        }
-        result.putLong("Total rx Bytes", rxBytes);
-        result.putLong("Total tx Bytes", txBytes);
-        result.putLong("Total rx Packets", rxPackets);
-        result.putLong("Total tx Packets", txPackets);
+        result.putLong("Total rx Bytes", bucket.getRxBytes());
+        result.putLong("Total tx Bytes", bucket.getTxBytes());
+        result.putLong("Total rx Packets", bucket.getRxPackets());
+        result.putLong("Total tx Packets", bucket.getTxPackets());
         getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, result);
 
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/close/OWNERS
new file mode 100644
index 0000000..f7c0a87
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/OWNERS
@@ -0,0 +1,2 @@
+# window manager > animations/transitions
+# Bug component: 316275
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OWNERS
new file mode 100644
index 0000000..301fafa
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OWNERS
@@ -0,0 +1,2 @@
+# ime
+# Bug component: 34867
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OWNERS
new file mode 100644
index 0000000..2c414a2
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OWNERS
@@ -0,0 +1,4 @@
+# System UI > ... > Overview (recent apps) > UI
+# Bug template url: https://b.corp.google.com/issues/new?component=807991&template=1390280 = per-file *Overview*
+# window manager > animations/transitions
+# Bug template url: https://b.corp.google.com/issues/new?component=316275&template=1018192
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/OWNERS
new file mode 100644
index 0000000..897fe5d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/OWNERS
@@ -0,0 +1,2 @@
+# System UI > ... > Launcher > Gesture nav
+# Bug component: 565144
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/OWNERS
new file mode 100644
index 0000000..f7c0a87
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/OWNERS
@@ -0,0 +1,2 @@
+# window manager > animations/transitions
+# Bug component: 316275
diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml
index c30d761..21256d8 100644
--- a/tests/SilkFX/AndroidManifest.xml
+++ b/tests/SilkFX/AndroidManifest.xml
@@ -20,17 +20,20 @@
     <uses-sdk android:minSdkVersion="30"/>
 
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
     <application android:label="SilkFX"
          android:theme="@android:style/Theme.Material">
 
         <activity android:name=".Main"
              android:label="SilkFX Demos"
+             android:banner="@drawable/background1"
              android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.DEFAULT"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
             </intent-filter>
         </activity>
 
@@ -41,13 +44,16 @@
 
         <activity android:name=".materials.GlassActivity"
             android:label="Glass Examples"
-            android:banner="@drawable/background1"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
             </intent-filter>
         </activity>
 
+        <activity android:name=".materials.BackgroundBlurActivity"
+            android:theme="@style/Theme.BackgroundBlurTheme"
+            android:exported="true">
+        </activity>
+
     </application>
 </manifest>
diff --git a/tests/SilkFX/res/drawable/background_blur_drawable.xml b/tests/SilkFX/res/drawable/background_blur_drawable.xml
new file mode 100644
index 0000000..173ca99
--- /dev/null
+++ b/tests/SilkFX/res/drawable/background_blur_drawable.xml
@@ -0,0 +1,20 @@
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+           android:shape="rectangle">
+    <solid android:color="#20FFFFFF"/>
+    <corners android:radius="10dp"/>
+</shape>
diff --git a/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml b/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml
new file mode 100644
index 0000000..bd8942d
--- /dev/null
+++ b/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="10dp"/>
+</shape>
diff --git a/tests/SilkFX/res/layout/activity_background_blur.xml b/tests/SilkFX/res/layout/activity_background_blur.xml
new file mode 100644
index 0000000..f13c088
--- /dev/null
+++ b/tests/SilkFX/res/layout/activity_background_blur.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/background"
+    android:layout_width="390dp"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:padding="15dp"
+    android:orientation="vertical"
+    tools:context=".materials.BackgroundBlurActivity">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        android:padding="10dp"
+        android:textColor="#ffffffff"
+        android:text="Hello blurry world!"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:textColor="#ffffffff"
+            android:text="Background blur"/>
+
+        <SeekBar
+            android:id="@+id/set_background_blur"
+            android:min="0"
+            android:max="300"
+            android:layout_width="160dp"
+            android:layout_height="wrap_content"/>
+        <TextView
+            android:id="@+id/background_blur_radius"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#ffffffff"
+            android:ems="3"
+            android:gravity="center"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:text="TODO"/>
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:textColor="#ffffffff"
+            android:text="Background alpha"/>
+
+        <SeekBar
+            android:id="@+id/set_background_alpha"
+            android:min="0"
+            android:max="100"
+            android:layout_width="160dp"
+            android:layout_height="wrap_content" />
+        <TextView
+            android:id="@+id/background_alpha"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#ffffffff"
+            android:ems="3"
+            android:gravity="center"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:text="TODO"/>
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:textColor="#ffffffff"
+            android:text="Blur behind"/>
+
+        <SeekBar
+            android:id="@+id/set_blur_behind"
+            android:min="0"
+            android:max="300"
+            android:layout_width="160dp"
+            android:layout_height="wrap_content" />
+        <TextView
+            android:id="@+id/blur_behind_radius"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:textColor="#ffffffff"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:ems="3"
+            android:text="TODO"/>
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:textColor="#ffffffff"
+            android:text="Dim amount"/>
+
+        <SeekBar
+            android:id="@+id/set_dim_amount"
+            android:min="0"
+            android:max="100"
+            android:layout_width="160dp"
+            android:layout_height="wrap_content" />
+        <TextView
+            android:id="@+id/dim_amount"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:textColor="#ffffffff"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp"
+            android:ems="3"
+            android:text="TODO"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginTop="5dp"
+        android:orientation="vertical"
+        android:gravity="center">
+
+        <Button
+            android:id="@+id/toggle_blur_enabled"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="Disable blur"
+            android:onClick="toggleForceBlurDisabled"/>
+
+        <Button
+            android:id="@+id/toggle_battery_saving_mode"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="TODO"
+            android:onClick="toggleBatterySavingMode"/>
+    </LinearLayout>
+    <requestFocus/>
+
+</LinearLayout>
diff --git a/tests/SilkFX/res/values/style.xml b/tests/SilkFX/res/values/style.xml
new file mode 100644
index 0000000..66edbb5
--- /dev/null
+++ b/tests/SilkFX/res/values/style.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<!-- Styles for immersive actions UI. -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="Theme.BackgroundBlurTheme" parent= "Theme.AppCompat.Dialog">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBlurBehindEnabled">true</item>
+        <item name="android:backgroundDimEnabled">false</item>
+        <item name="android:windowElevation">0dp</item>
+        <item name="buttonStyle">@style/AppTheme.Button</item>
+        <item name="colorAccent">#bbffffff</item>
+    </style>
+    <style name="AppTheme.Button" parent="Widget.AppCompat.Button">
+        <item name="android:textColor">#ffffffff</item>
+    </style>
+
+</resources>
diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
index 9ed8d2f..7132ae8 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
 import com.android.test.silkfx.app.EXTRA_TITLE
 import com.android.test.silkfx.hdr.GlowActivity
 import com.android.test.silkfx.materials.GlassActivity
+import com.android.test.silkfx.materials.BackgroundBlurActivity
 import kotlin.reflect.KClass
 
 class Demo(val name: String, val makeIntent: (Context) -> Intent) {
@@ -51,7 +52,8 @@
                 Demo("Blingy Notifications", R.layout.bling_notifications)
         )),
         DemoGroup("Materials", listOf(
-                Demo("Glass", GlassActivity::class)
+                Demo("Glass", GlassActivity::class),
+                Demo("Background Blur", BackgroundBlurActivity::class)
         ))
 )
 
@@ -126,4 +128,4 @@
 
         AllDemos.forEachIndexed { index, _ -> list.expandGroup(index) }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt
new file mode 100644
index 0000000..9d17d38
--- /dev/null
+++ b/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.test.silkfx.materials
+
+import android.app.Activity
+import android.content.Intent
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.PaintDrawable
+import android.graphics.drawable.Drawable
+import android.os.Bundle
+import android.provider.Settings
+import android.util.TypedValue
+import android.view.View
+import android.view.WindowManager
+import android.widget.ImageView
+import android.widget.SeekBar
+import android.widget.Switch
+import android.widget.TextView
+import com.android.test.silkfx.R
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable
+import android.widget.LinearLayout
+import android.widget.Button
+
+import android.view.ViewRootImpl
+
+class BackgroundBlurActivity : Activity(), SeekBar.OnSeekBarChangeListener  {
+    var mBackgroundDrawable = PaintDrawable(Color.WHITE)
+    var mBackgroundBlurRadius = 50
+    var mAlphaWithBlur = 0.2f
+    var mAlphaNoBlur = 0.5f
+
+    var mBlurBehindRadius = 10
+    var mDimAmountWithBlur = 0.2f
+    var mDimAmountNoBlur = 0.2f
+
+    var mBlurForceDisabled = false
+    var mBatterySavingModeOn = false
+
+    lateinit var blurBackgroundSeekBar: SeekBar
+    lateinit var backgroundAlphaSeekBar : SeekBar
+    lateinit var blurBehindSeekBar : SeekBar
+    lateinit var dimAmountSeekBar : SeekBar
+
+    val blurEnabledListener = { enabled : Boolean ->
+        blurBackgroundSeekBar.setProgress(mBackgroundBlurRadius)
+        blurBehindSeekBar.setProgress(mBlurBehindRadius)
+
+        if (enabled) {
+            setBackgroundBlur(mBackgroundBlurRadius)
+            setBackgroundColorAlpha(mAlphaWithBlur)
+
+            setBlurBehind(mBlurBehindRadius)
+            setDimAmount(mDimAmountWithBlur)
+
+            backgroundAlphaSeekBar.setProgress((mAlphaWithBlur * 100).toInt())
+            dimAmountSeekBar.setProgress((mDimAmountWithBlur * 100).toInt())
+        } else {
+            setBackgroundColorAlpha(mAlphaNoBlur)
+            setDimAmount(mDimAmountNoBlur)
+
+            backgroundAlphaSeekBar.setProgress((mAlphaNoBlur * 100).toInt())
+            dimAmountSeekBar.setProgress((mDimAmountNoBlur * 100).toInt())
+        }
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_background_blur)
+
+        window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
+        window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+        mBackgroundDrawable.setCornerRadius(30f)
+        window.setBackgroundDrawable(mBackgroundDrawable)
+
+        mBatterySavingModeOn =
+            Settings.Global.getInt(getContentResolver(), Settings.Global.LOW_POWER_MODE, 0) == 1
+        setBatterySavingModeOn(mBatterySavingModeOn)
+
+        blurBackgroundSeekBar = requireViewById(R.id.set_background_blur)
+        backgroundAlphaSeekBar = requireViewById(R.id.set_background_alpha)
+        blurBehindSeekBar = requireViewById(R.id.set_blur_behind)
+        dimAmountSeekBar = requireViewById(R.id.set_dim_amount)
+
+        arrayOf(blurBackgroundSeekBar, backgroundAlphaSeekBar, blurBehindSeekBar, dimAmountSeekBar)
+                .forEach {
+                    it.setOnSeekBarChangeListener(this)
+                }
+    }
+
+    override fun onAttachedToWindow() {
+        super.onAttachedToWindow()
+        getWindowManager().addCrossWindowBlurEnabledListener(blurEnabledListener)
+    }
+
+    override fun onDetachedFromWindow() {
+        super.onDetachedFromWindow()
+        getWindowManager().removeCrossWindowBlurEnabledListener(blurEnabledListener)
+    }
+
+    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+        when (seekBar) {
+            blurBackgroundSeekBar -> setBackgroundBlur(progress)
+            backgroundAlphaSeekBar -> setBackgroundColorAlpha(progress / 100.0f)
+            blurBehindSeekBar -> setBlurBehind(progress)
+            dimAmountSeekBar -> setDimAmount(progress / 100.0f)
+            else -> throw IllegalArgumentException("Unknown seek bar")
+        }
+    }
+
+    override fun onStartTrackingTouch(seekBar: SeekBar?) {}
+    override fun onStopTrackingTouch(seekBar: SeekBar?) {}
+
+    fun setBlurDisabled(disabled: Boolean) {
+        mBlurForceDisabled = disabled
+        Settings.Global.putInt(getContentResolver(), Settings.Global.DISABLE_WINDOW_BLURS,
+                if (mBlurForceDisabled) 1 else 0)
+        (findViewById(R.id.toggle_blur_enabled) as Button)
+                .setText(if (mBlurForceDisabled) "Enable blurs" else "Disable blurs")
+    }
+
+    fun toggleForceBlurDisabled(v: View) {
+        setBlurDisabled(!mBlurForceDisabled)
+    }
+
+    fun setBackgroundBlur(radius: Int) {
+        mBackgroundBlurRadius = radius
+        (findViewById(R.id.background_blur_radius) as TextView).setText(radius.toString())
+        window.setBackgroundBlurRadius(mBackgroundBlurRadius)
+    }
+
+    fun setBlurBehind(radius: Int) {
+        mBlurBehindRadius = radius
+        (findViewById(R.id.blur_behind_radius) as TextView).setText(radius.toString())
+        window.getAttributes().setBlurBehindRadius(mBlurBehindRadius)
+        window.setAttributes(window.getAttributes())
+    }
+
+    fun setDimAmount(amount: Float) {
+        if (getWindowManager().isCrossWindowBlurEnabled()) {
+            mDimAmountWithBlur = amount
+        } else {
+            mDimAmountNoBlur = amount
+        }
+        (findViewById(R.id.dim_amount) as TextView).setText("%.2f".format(amount))
+        window.getAttributes().dimAmount = amount
+        window.setAttributes(window.getAttributes())
+    }
+
+    fun setBatterySavingModeOn(on: Boolean) {
+        mBatterySavingModeOn = on
+        Settings.Global.putInt(getContentResolver(),
+            Settings.Global.LOW_POWER_MODE, if (on) 1 else 0)
+        (findViewById(R.id.toggle_battery_saving_mode) as Button).setText(
+            if (on) "Exit low power mode" else "Enter low power mode")
+    }
+
+    fun toggleBatterySavingMode(v: View) {
+        setBatterySavingModeOn(!mBatterySavingModeOn)
+    }
+
+    fun setBackgroundColorAlpha(alpha: Float) {
+        if (getWindowManager().isCrossWindowBlurEnabled()) {
+            mAlphaWithBlur = alpha
+        } else {
+            mAlphaNoBlur = alpha
+        }
+        (findViewById(R.id.background_alpha) as TextView).setText("%.2f".format(alpha))
+        mBackgroundDrawable.setAlpha((alpha * 255f).toInt())
+        getWindowManager().updateViewLayout(window.getDecorView(), window.getAttributes())
+    }
+}
diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp
deleted file mode 100644
index f87ca2e..0000000
--- a/tests/benchmarks/Android.bp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2015 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// build framework base core benchmarks
-// ============================================================
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library {
-    name: "networkStatsFactory-benchmarks",
-    installable: true,
-
-    srcs: ["src/**/*.java"],
-
-    libs: [
-        "caliper-api-target",
-        "services.core",
-    ],
-
-}
diff --git a/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java b/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
deleted file mode 100644
index ef014f0..0000000
--- a/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 com.android.server.net;
-
-import android.net.NetworkStats;
-import android.os.SystemClock;
-import com.android.server.net.NetworkStatsFactory;
-import com.google.caliper.AfterExperiment;
-import com.google.caliper.BeforeExperiment;
-import java.io.File;
-
-public class NetworkStatsFactoryBenchmark {
-    private File mStats;
-
-    // TODO: consider staging stats file with different number of rows
-
-    @BeforeExperiment
-    protected void setUp() {
-        mStats = new File("/proc/net/xt_qtaguid/stats");
-    }
-
-    @AfterExperiment
-    protected void tearDown() {
-        mStats = null;
-    }
-
-    public void timeReadNetworkStatsDetailJava(int reps) throws Exception {
-        for (int i = 0; i < reps; i++) {
-            NetworkStatsFactory.javaReadNetworkStatsDetail(mStats, NetworkStats.UID_ALL,
-                    // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70
-                    // Fixed compilation problem but needs addressing properly.
-                    new String[0], 999);
-        }
-    }
-
-    public void timeReadNetworkStatsDetailNative(int reps) {
-        for (int i = 0; i < reps; i++) {
-            final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
-            NetworkStatsFactory.nativeReadNetworkStatsDetail(
-                    stats, mStats.getAbsolutePath(), NetworkStats.UID_ALL,
-                    // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70
-                    // Fixed compilation problem but needs addressing properly.
-                    new String[0], 999, false);
-        }
-    }
-}
diff --git a/tests/benchmarks/src/com/android/server/net/OWNERS b/tests/benchmarks/src/com/android/server/net/OWNERS
deleted file mode 100644
index aa87958..0000000
--- a/tests/benchmarks/src/com/android/server/net/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /services/core/java/com/android/server/net/OWNERS
diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp
index 41f73cd..228520e 100644
--- a/tests/vcn/Android.bp
+++ b/tests/vcn/Android.bp
@@ -18,6 +18,7 @@
         "java/**/*.kt",
     ],
     platform_apis: true,
+    defaults: ["framework-connectivity-test-defaults"],
     test_suites: ["device-tests"],
     certificate: "platform",
     static_libs: [
@@ -28,6 +29,7 @@
         "net-tests-utils",
         "platform-test-annotations",
         "services.core",
+        "service-connectivity-tiramisu-pre-jarjar",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/vcn/AndroidManifest.xml b/tests/vcn/AndroidManifest.xml
index 2ad9aac..a8f657c 100644
--- a/tests/vcn/AndroidManifest.xml
+++ b/tests/vcn/AndroidManifest.xml
@@ -16,7 +16,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.tests.vcn">
-
+    <uses-sdk android:minSdkVersion="33"
+        android:targetSdkVersion="33"/>
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
index 4a724b7..2fbcf9d 100644
--- a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
@@ -18,25 +18,29 @@
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 import org.junit.Test;
 
 import java.util.HashSet;
 import java.util.Set;
 
-public class VcnCellUnderlyingNetworkTemplateTest {
+public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTemplateTestBase {
     private static final Set<String> ALLOWED_PLMN_IDS = new HashSet<>();
     private static final Set<Integer> ALLOWED_CARRIER_IDS = new HashSet<>();
 
     // Package private for use in VcnGatewayConnectionConfigTest
     static VcnCellUnderlyingNetworkTemplate getTestNetworkTemplate() {
         return new VcnCellUnderlyingNetworkTemplate.Builder()
-                .setNetworkQuality(NETWORK_QUALITY_OK)
                 .setMetered(MATCH_FORBIDDEN)
+                .setMinUpstreamBandwidthKbps(
+                        TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                        TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS)
+                .setMinDownstreamBandwidthKbps(
+                        TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                        TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS)
                 .setOperatorPlmnIds(ALLOWED_PLMN_IDS)
                 .setSimSpecificCarrierIds(ALLOWED_CARRIER_IDS)
                 .setRoaming(MATCH_FORBIDDEN)
@@ -47,8 +51,19 @@
     @Test
     public void testBuilderAndGetters() {
         final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
-        assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality());
         assertEquals(MATCH_FORBIDDEN, networkPriority.getMetered());
+        assertEquals(
+                TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinEntryUpstreamBandwidthKbps());
+        assertEquals(
+                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinExitUpstreamBandwidthKbps());
+        assertEquals(
+                TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinEntryDownstreamBandwidthKbps());
+        assertEquals(
+                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinExitDownstreamBandwidthKbps());
         assertEquals(ALLOWED_PLMN_IDS, networkPriority.getOperatorPlmnIds());
         assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getSimSpecificCarrierIds());
         assertEquals(MATCH_FORBIDDEN, networkPriority.getRoaming());
@@ -59,8 +74,14 @@
     public void testBuilderAndGettersForDefaultValues() {
         final VcnCellUnderlyingNetworkTemplate networkPriority =
                 new VcnCellUnderlyingNetworkTemplate.Builder().build();
-        assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality());
         assertEquals(MATCH_ANY, networkPriority.getMetered());
+
+        // Explicitly expect 0, as documented in Javadoc on setter methods.
+        assertEquals(0, networkPriority.getMinEntryUpstreamBandwidthKbps());
+        assertEquals(0, networkPriority.getMinExitUpstreamBandwidthKbps());
+        assertEquals(0, networkPriority.getMinEntryDownstreamBandwidthKbps());
+        assertEquals(0, networkPriority.getMinExitDownstreamBandwidthKbps());
+
         assertEquals(new HashSet<String>(), networkPriority.getOperatorPlmnIds());
         assertEquals(new HashSet<Integer>(), networkPriority.getSimSpecificCarrierIds());
         assertEquals(MATCH_ANY, networkPriority.getRoaming());
@@ -68,6 +89,29 @@
     }
 
     @Test
+    public void testBuilderRequiresStricterEntryCriteria() {
+        try {
+            new VcnCellUnderlyingNetworkTemplate.Builder()
+                    .setMinUpstreamBandwidthKbps(
+                            TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                            TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS);
+
+            fail("Expected IAE for exit threshold > entry threshold");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            new VcnCellUnderlyingNetworkTemplate.Builder()
+                    .setMinDownstreamBandwidthKbps(
+                            TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                            TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS);
+
+            fail("Expected IAE for exit threshold > entry threshold");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
     public void testPersistableBundle() {
         final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
         assertEquals(
diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkTemplateTestBase.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkTemplateTestBase.java
new file mode 100644
index 0000000..399e136
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkTemplateTestBase.java
@@ -0,0 +1,24 @@
+/*
+ * 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.net.vcn;
+
+public class VcnUnderlyingNetworkTemplateTestBase {
+    // Public for use in NetworkPriorityClassifierTest
+    public static final int TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS = 200;
+    public static final int TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS = 100;
+    public static final int TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS = 400;
+    public static final int TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS = 300;
+}
diff --git a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java
index cb5b47b..4063178 100644
--- a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java
@@ -17,8 +17,6 @@
 
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -28,15 +26,19 @@
 
 import java.util.Set;
 
-public class VcnWifiUnderlyingNetworkTemplateTest {
+public class VcnWifiUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTemplateTestBase {
     private static final String SSID = "TestWifi";
-    private static final int INVALID_NETWORK_QUALITY = -1;
 
     // Package private for use in VcnGatewayConnectionConfigTest
     static VcnWifiUnderlyingNetworkTemplate getTestNetworkTemplate() {
         return new VcnWifiUnderlyingNetworkTemplate.Builder()
-                .setNetworkQuality(NETWORK_QUALITY_OK)
                 .setMetered(MATCH_FORBIDDEN)
+                .setMinUpstreamBandwidthKbps(
+                        TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                        TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS)
+                .setMinDownstreamBandwidthKbps(
+                        TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                        TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS)
                 .setSsids(Set.of(SSID))
                 .build();
     }
@@ -44,8 +46,19 @@
     @Test
     public void testBuilderAndGetters() {
         final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
-        assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality());
         assertEquals(MATCH_FORBIDDEN, networkPriority.getMetered());
+        assertEquals(
+                TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinEntryUpstreamBandwidthKbps());
+        assertEquals(
+                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinExitUpstreamBandwidthKbps());
+        assertEquals(
+                TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinEntryDownstreamBandwidthKbps());
+        assertEquals(
+                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                networkPriority.getMinExitDownstreamBandwidthKbps());
         assertEquals(Set.of(SSID), networkPriority.getSsids());
     }
 
@@ -53,18 +66,37 @@
     public void testBuilderAndGettersForDefaultValues() {
         final VcnWifiUnderlyingNetworkTemplate networkPriority =
                 new VcnWifiUnderlyingNetworkTemplate.Builder().build();
-        assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality());
         assertEquals(MATCH_ANY, networkPriority.getMetered());
+
+        // Explicitly expect 0, as documented in Javadoc on setter methods..
+        assertEquals(0, networkPriority.getMinEntryUpstreamBandwidthKbps());
+        assertEquals(0, networkPriority.getMinExitUpstreamBandwidthKbps());
+        assertEquals(0, networkPriority.getMinEntryDownstreamBandwidthKbps());
+        assertEquals(0, networkPriority.getMinExitDownstreamBandwidthKbps());
+
         assertTrue(networkPriority.getSsids().isEmpty());
     }
 
     @Test
-    public void testBuildWithInvalidNetworkQuality() {
+    public void testBuilderRequiresStricterEntryCriteria() {
         try {
             new VcnWifiUnderlyingNetworkTemplate.Builder()
-                    .setNetworkQuality(INVALID_NETWORK_QUALITY);
-            fail("Expected to fail due to the invalid network quality");
-        } catch (Exception expected) {
+                    .setMinUpstreamBandwidthKbps(
+                            TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                            TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS);
+
+            fail("Expected IAE for exit threshold > entry threshold");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            new VcnWifiUnderlyingNetworkTemplate.Builder()
+                    .setMinDownstreamBandwidthKbps(
+                            TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                            TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS);
+
+            fail("Expected IAE for exit threshold > entry threshold");
+        } catch (IllegalArgumentException expected) {
         }
     }
 
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 978bf3e..7b1f7a5 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -174,7 +174,7 @@
 
     private IntentFilter getIntentFilter() {
         final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
+        verify(mContext).registerReceiver(any(), captor.capture(), any(), any(), anyInt());
 
         return captor.getValue();
     }
@@ -258,7 +258,8 @@
                         eq(mTelephonySubscriptionTracker),
                         any(IntentFilter.class),
                         any(),
-                        eq(mHandler));
+                        eq(mHandler),
+                        eq(Context.RECEIVER_NOT_EXPORTED));
         final IntentFilter filter = getIntentFilter();
         assertEquals(2, filter.countActions());
         assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index e547400..4cfa93b 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -307,7 +307,10 @@
                         ncCaptor.capture(),
                         lpCaptor.capture(),
                         any(),
-                        argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE),
+                        // Subtype integer/name and extras do not have getters; cannot be tested.
+                        argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE
+                                && nac.getLegacyTypeName().equals(
+                                        VcnGatewayConnection.NETWORK_INFO_NETWORK_TYPE_STRING)),
                         any(),
                         any(),
                         any());
diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java
index 5d2f9d7..6d26968 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java
@@ -58,6 +58,7 @@
 import com.android.server.VcnManagementService.VcnCallback;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
 import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
+import com.android.server.vcn.Vcn.VcnUserMobileDataStateListener;
 import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
 
 import org.junit.Before;
@@ -208,6 +209,13 @@
     }
 
     @Test
+    public void testMobileDataStateListenersRegistered() {
+        // Validate state from setUp()
+        verify(mTelephonyManager, times(3))
+                .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class));
+    }
+
+    @Test
     public void testMobileDataStateCheckedOnInitialization_enabled() {
         // Validate state from setUp()
         assertTrue(mVcn.isMobileDataEnabled());
@@ -263,6 +271,24 @@
         assertFalse(mVcn.isMobileDataEnabled());
     }
 
+    @Test
+    public void testSubscriptionSnapshotUpdatesMobileDataStateListeners() {
+        final TelephonySubscriptionSnapshot updatedSnapshot =
+                mock(TelephonySubscriptionSnapshot.class);
+
+        doReturn(new ArraySet<>(Arrays.asList(2, 4)))
+                .when(updatedSnapshot)
+                .getAllSubIdsInGroup(any());
+
+        mVcn.updateSubscriptionSnapshot(updatedSnapshot);
+        mTestLooper.dispatchAll();
+
+        verify(mTelephonyManager, times(4))
+                .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class));
+        verify(mTelephonyManager, times(2))
+                .unregisterTelephonyCallback(any(VcnUserMobileDataStateListener.class));
+    }
+
     private void triggerVcnRequestListeners(NetworkRequestListener requestListener) {
         for (final int[] caps : TEST_CAPS) {
             startVcnGatewayWithCapabilities(requestListener, caps);
@@ -402,24 +428,17 @@
         verify(mVcnNetworkProvider).resendAllRequests(requestListener);
     }
 
-    private void verifyMobileDataToggled(boolean startingToggleState, boolean endingToggleState) {
-        final ArgumentCaptor<ContentObserver> captor =
-                ArgumentCaptor.forClass(ContentObserver.class);
-        verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture());
-        final ContentObserver contentObserver = captor.getValue();
-
+    private void setupForMobileDataTest(boolean startingToggleState) {
         // Start VcnGatewayConnections
         final NetworkRequestListener requestListener = verifyAndGetRequestListener();
         mVcn.setMobileDataEnabled(startingToggleState);
         triggerVcnRequestListeners(requestListener);
-        final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways =
-                mVcn.getVcnGatewayConnectionConfigMap();
+    }
 
-        // Trigger data toggle change.
-        doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled();
-        contentObserver.onChange(false /* selfChange, ignored */);
-        mTestLooper.dispatchAll();
-
+    private void verifyMobileDataToggledUpdatesGatewayConnections(
+            boolean startingToggleState,
+            boolean endingToggleState,
+            Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways) {
         // Verify that data toggle changes restart ONLY INTERNET or DUN networks, and only if the
         // toggle state changed.
         for (Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry : gateways.entrySet()) {
@@ -433,29 +452,98 @@
             }
         }
 
+        final NetworkRequestListener requestListener = verifyAndGetRequestListener();
         if (startingToggleState != endingToggleState) {
             verify(mVcnNetworkProvider).resendAllRequests(requestListener);
         }
         assertEquals(endingToggleState, mVcn.isMobileDataEnabled());
     }
 
-    @Test
-    public void testMobileDataEnabled() {
-        verifyMobileDataToggled(false /* startingToggleState */, true /* endingToggleState */);
+    private void verifyGlobalMobileDataToggled(
+            boolean startingToggleState, boolean endingToggleState) {
+        setupForMobileDataTest(startingToggleState);
+        final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways =
+                mVcn.getVcnGatewayConnectionConfigMap();
+
+        // Trigger data toggle change
+        final ArgumentCaptor<ContentObserver> captor =
+                ArgumentCaptor.forClass(ContentObserver.class);
+        verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture());
+        final ContentObserver contentObserver = captor.getValue();
+
+        doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled();
+        contentObserver.onChange(false /* selfChange, ignored */);
+        mTestLooper.dispatchAll();
+
+        // Verify resultant behavior
+        verifyMobileDataToggledUpdatesGatewayConnections(
+                startingToggleState, endingToggleState, gateways);
     }
 
     @Test
-    public void testMobileDataDisabled() {
-        verifyMobileDataToggled(true /* startingToggleState */, false /* endingToggleState */);
+    public void testGlobalMobileDataEnabled() {
+        verifyGlobalMobileDataToggled(
+                false /* startingToggleState */, true /* endingToggleState */);
     }
 
     @Test
-    public void testMobileDataObserverFiredWithoutChanges_dataEnabled() {
-        verifyMobileDataToggled(false /* startingToggleState */, false /* endingToggleState */);
+    public void testGlobalMobileDataDisabled() {
+        verifyGlobalMobileDataToggled(
+                true /* startingToggleState */, false /* endingToggleState */);
     }
 
     @Test
-    public void testMobileDataObserverFiredWithoutChanges_dataDisabled() {
-        verifyMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */);
+    public void testGlobalMobileDataObserverFiredWithoutChanges_dataEnabled() {
+        verifyGlobalMobileDataToggled(
+                false /* startingToggleState */, false /* endingToggleState */);
+    }
+
+    @Test
+    public void testGlobalMobileDataObserverFiredWithoutChanges_dataDisabled() {
+        verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */);
+    }
+
+    private void verifySubscriptionMobileDataToggled(
+            boolean startingToggleState, boolean endingToggleState) {
+        setupForMobileDataTest(startingToggleState);
+        final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways =
+                mVcn.getVcnGatewayConnectionConfigMap();
+
+        // Trigger data toggle change.
+        final ArgumentCaptor<VcnUserMobileDataStateListener> captor =
+                ArgumentCaptor.forClass(VcnUserMobileDataStateListener.class);
+        verify(mTelephonyManager, times(3)).registerTelephonyCallback(any(), captor.capture());
+        final VcnUserMobileDataStateListener listener = captor.getValue();
+
+        doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled();
+        listener.onUserMobileDataStateChanged(false /* enabled, ignored */);
+        mTestLooper.dispatchAll();
+
+        // Verify resultant behavior
+        verifyMobileDataToggledUpdatesGatewayConnections(
+                startingToggleState, endingToggleState, gateways);
+    }
+
+    @Test
+    public void testSubscriptionMobileDataEnabled() {
+        verifyGlobalMobileDataToggled(
+                false /* startingToggleState */, true /* endingToggleState */);
+    }
+
+    @Test
+    public void testSubscriptionMobileDataDisabled() {
+        verifyGlobalMobileDataToggled(
+                true /* startingToggleState */, false /* endingToggleState */);
+    }
+
+    @Test
+    public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataEnabled() {
+        verifyGlobalMobileDataToggled(
+                false /* startingToggleState */, false /* endingToggleState */);
+    }
+
+    @Test
+    public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataDisabled() {
+        verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */);
     }
 }
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
index 4bb7de8..6c849b5 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
@@ -18,7 +18,10 @@
 
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
-import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
+import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS;
+import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS;
+import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS;
+import static android.net.vcn.VcnUnderlyingNetworkTemplateTestBase.TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS;
 
 import static com.android.server.vcn.VcnTestUtils.setupSystemService;
 import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_ANY;
@@ -76,6 +79,12 @@
     private static final int CARRIER_ID = 1;
     private static final int CARRIER_ID_OTHER = 2;
 
+    private static final int LINK_UPSTREAM_BANDWIDTH_KBPS = 1024;
+    private static final int LINK_DOWNSTREAM_BANDWIDTH_KBPS = 2048;
+
+    private static final int TEST_MIN_UPSTREAM_BANDWIDTH_KBPS = 100;
+    private static final int TEST_MIN_DOWNSTREAM_BANDWIDTH_KBPS = 200;
+
     private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
 
     private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES =
@@ -83,6 +92,8 @@
                     .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                     .setSignalStrength(WIFI_RSSI)
                     .setSsid(SSID)
+                    .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
+                    .setLinkDownstreamBandwidthKbps(LINK_DOWNSTREAM_BANDWIDTH_KBPS)
                     .build();
 
     private static final TelephonyNetworkSpecifier TEL_NETWORK_SPECIFIER =
@@ -93,6 +104,8 @@
                     .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                     .setSubscriptionIds(Set.of(SUB_ID))
                     .setNetworkSpecifier(TEL_NETWORK_SPECIFIER)
+                    .setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
+                    .setLinkDownstreamBandwidthKbps(LINK_DOWNSTREAM_BANDWIDTH_KBPS)
                     .build();
 
     private static final LinkProperties LINK_PROPERTIES = getLinkPropertiesWithName("test_iface");
@@ -146,7 +159,6 @@
     public void testMatchWithoutNotMeteredBit() {
         final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
                 new VcnWifiUnderlyingNetworkTemplate.Builder()
-                        .setNetworkQuality(NETWORK_QUALITY_OK)
                         .setMetered(MATCH_FORBIDDEN)
                         .build();
 
@@ -161,11 +173,133 @@
                         null /* carrierConfig */));
     }
 
+    private void verifyMatchesPriorityRuleForUpstreamBandwidth(
+            int entryUpstreamBandwidth,
+            int exitUpstreamBandwidth,
+            UnderlyingNetworkRecord currentlySelected,
+            boolean expectMatch) {
+        final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
+                new VcnWifiUnderlyingNetworkTemplate.Builder()
+                        .setMinUpstreamBandwidthKbps(entryUpstreamBandwidth, exitUpstreamBandwidth)
+                        .build();
+
+        assertEquals(
+                expectMatch,
+                checkMatchesPriorityRule(
+                        mVcnContext,
+                        wifiNetworkPriority,
+                        mWifiNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot,
+                        currentlySelected,
+                        null /* carrierConfig */));
+    }
+
+    private void verifyMatchesPriorityRuleForDownstreamBandwidth(
+            int entryDownstreamBandwidth,
+            int exitDownstreamBandwidth,
+            UnderlyingNetworkRecord currentlySelected,
+            boolean expectMatch) {
+        final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
+                new VcnWifiUnderlyingNetworkTemplate.Builder()
+                        .setMinDownstreamBandwidthKbps(
+                                entryDownstreamBandwidth, exitDownstreamBandwidth)
+                        .build();
+
+        assertEquals(
+                expectMatch,
+                checkMatchesPriorityRule(
+                        mVcnContext,
+                        wifiNetworkPriority,
+                        mWifiNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot,
+                        currentlySelected,
+                        null /* carrierConfig */));
+    }
+
+    @Test
+    public void testMatchWithEntryUpstreamBandwidthEquals() {
+        verifyMatchesPriorityRuleForUpstreamBandwidth(
+                TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                null /* currentlySelected */,
+                true);
+    }
+
+    @Test
+    public void testMatchWithEntryUpstreamBandwidthTooLow() {
+        verifyMatchesPriorityRuleForUpstreamBandwidth(
+                LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
+                LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
+                null /* currentlySelected */,
+                false);
+    }
+
+    @Test
+    public void testMatchWithEntryDownstreamBandwidthEquals() {
+        verifyMatchesPriorityRuleForDownstreamBandwidth(
+                TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                null /* currentlySelected */,
+                true);
+    }
+
+    @Test
+    public void testMatchWithEntryDownstreamBandwidthTooLow() {
+        verifyMatchesPriorityRuleForDownstreamBandwidth(
+                LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
+                LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
+                null /* currentlySelected */,
+                false);
+    }
+
+    @Test
+    public void testMatchWithExitUpstreamBandwidthEquals() {
+        verifyMatchesPriorityRuleForUpstreamBandwidth(
+                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS,
+                mWifiNetworkRecord,
+                true);
+    }
+
+    @Test
+    public void testMatchWithExitUpstreamBandwidthTooLow() {
+        verifyMatchesPriorityRuleForUpstreamBandwidth(
+                LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
+                LINK_UPSTREAM_BANDWIDTH_KBPS + 1,
+                mWifiNetworkRecord,
+                false);
+    }
+
+    @Test
+    public void testMatchWithExitDownstreamBandwidthEquals() {
+        verifyMatchesPriorityRuleForDownstreamBandwidth(
+                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS,
+                mWifiNetworkRecord,
+                true);
+    }
+
+    @Test
+    public void testMatchWithExitDownstreamBandwidthTooLow() {
+        verifyMatchesPriorityRuleForDownstreamBandwidth(
+                LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
+                LINK_DOWNSTREAM_BANDWIDTH_KBPS + 1,
+                mWifiNetworkRecord,
+                false);
+    }
+
     private void verifyMatchWifi(
             boolean isSelectedNetwork, PersistableBundle carrierConfig, boolean expectMatch) {
         final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
                 new VcnWifiUnderlyingNetworkTemplate.Builder()
-                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setMinUpstreamBandwidthKbps(
+                                TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS)
+                        .setMinDownstreamBandwidthKbps(
+                                TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS)
                         .build();
         final UnderlyingNetworkRecord selectedNetworkRecord =
                 isSelectedNetwork ? mWifiNetworkRecord : null;
@@ -214,7 +348,12 @@
         final String nwPrioritySsid = useMatchedSsid ? SSID : SSID_OTHER;
         final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
                 new VcnWifiUnderlyingNetworkTemplate.Builder()
-                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setMinUpstreamBandwidthKbps(
+                                TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                                TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS)
+                        .setMinDownstreamBandwidthKbps(
+                                TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                                TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS)
                         .setSsids(Set.of(nwPrioritySsid))
                         .build();
 
@@ -238,7 +377,13 @@
     }
 
     private static VcnCellUnderlyingNetworkTemplate.Builder getCellNetworkPriorityBuilder() {
-        return new VcnCellUnderlyingNetworkTemplate.Builder().setNetworkQuality(NETWORK_QUALITY_OK);
+        return new VcnCellUnderlyingNetworkTemplate.Builder()
+                .setMinUpstreamBandwidthKbps(
+                        TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
+                        TEST_MIN_EXIT_UPSTREAM_BANDWIDTH_KBPS)
+                .setMinDownstreamBandwidthKbps(
+                        TEST_MIN_ENTRY_DOWNSTREAM_BANDWIDTH_KBPS,
+                        TEST_MIN_EXIT_DOWNSTREAM_BANDWIDTH_KBPS);
     }
 
     @Test
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index 36bea57..95b43cd 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
 
-if git branch -vv | grep -q -E "^\*[^\[]+\[aosp/"; then
+if git log -n 1 --format='%D' HEAD@{upstream} | grep -q aosp/; then
     # Change appears to be in AOSP
     exit 0
 elif git log -n 1 --format='%B' $1 | grep -q -E "^Ignore-AOSP-First: .+" ; then
diff --git a/tools/sdkparcelables/Android.bp b/tools/sdkparcelables/Android.bp
index 9d773e4..ec2bffd 100644
--- a/tools/sdkparcelables/Android.bp
+++ b/tools/sdkparcelables/Android.bp
@@ -14,7 +14,7 @@
         "src/**/*.kt",
     ],
     static_libs: [
-        "asm-6.0",
+        "asm-7.0",
     ],
 }
 
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
index 22e8d78..0fb062f 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
@@ -39,7 +39,7 @@
         kotlin.system.exitProcess(2)
     }
 
-    val ancestorCollector = AncestorCollector(Opcodes.ASM6, null)
+    val ancestorCollector = AncestorCollector(Opcodes.ASM7, null)
 
     for (entry in zipFile.entries()) {
         if (entry.name.endsWith(".class")) {
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
index 1ec83a3..b18bdff 100644
--- a/tools/streaming_proto/Android.bp
+++ b/tools/streaming_proto/Android.bp
@@ -69,7 +69,6 @@
         "test/**/*.proto",
     ],
     proto: {
-        plugin: "javastream",
+        type: "stream",
     },
-    static_libs: ["libprotobuf-java-lite"],
 }