Merge "Convert apct/framework/window_manager_presubmit-cloud-tf to Test Mapping Suite."
diff --git a/Android.bp b/Android.bp
index 7d91b1e..808879f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -266,6 +266,7 @@
     name: "framework-updatable-sources",
     srcs: [
         ":framework-sdkext-sources",
+        ":framework-tethering-srcs",
         ":updatable-media-srcs",
     ]
 }
@@ -366,8 +367,11 @@
 
     sdk_version: "core_platform",
     libs: [
+        "app-compat-annotations",
         "ext",
+        "unsupportedappusage",
         "updatable_media_stubs",
+        "framework-tethering",
     ],
 
     jarjar_rules: ":framework-jarjar-rules",
@@ -426,7 +430,6 @@
     name: "framework-minus-apex",
     defaults: ["framework-defaults"],
     srcs: [":framework-non-updatable-sources"],
-    libs: ["app-compat-annotations"],
     installable: true,
     javac_shard_size: 150,
     required: [
@@ -441,6 +444,7 @@
     ],
     // For backwards compatibility.
     stem: "framework",
+    apex_available: ["//apex_available:platform"],
 }
 
 // This "framework" module is NOT installed to the device. It's
@@ -458,9 +462,12 @@
     installable: false, // this lib is a build-only library
     static_libs: [
         "framework-minus-apex",
-        // TODO(jiyong): add stubs for APEXes here
+        "updatable_media_stubs",
+        "framework-sdkext-stubs-systemapi",
+        // TODO(jiyong): add more stubs for APEXes here
     ],
     sdk_version: "core_platform",
+    apex_available: ["//apex_available:platform"],
 }
 
 java_library {
@@ -468,14 +475,17 @@
     defaults: ["framework-defaults"],
     srcs: [":framework-all-sources"],
     installable: false,
-    libs: ["app-compat-annotations"],
+    apex_available: ["//apex_available:platform"],
 }
 
 java_library {
     name: "framework-annotation-proc",
     defaults: ["framework-defaults"],
     srcs: [":framework-all-sources"],
-    libs: ["app-compat-annotations"],
+    libs: [
+        "app-compat-annotations",
+        "unsupportedappusage",
+    ],
     installable: false,
     plugins: [
         "unsupportedappusage-annotation-processor",
@@ -563,6 +573,7 @@
         "core/java/android/annotation/Nullable.java",
         "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/IntRange.java",
+        "core/java/android/annotation/SystemApi.java",
         "core/java/android/annotation/UnsupportedAppUsage.java",
         "core/java/com/android/internal/annotations/GuardedBy.java",
         "core/java/com/android/internal/annotations/VisibleForTesting.java",
@@ -596,10 +607,26 @@
     ],
 }
 
+// keep these files in sync with the package/Tethering/jarjar-rules.txt for the tethering module.
 filegroup {
     name: "framework-tethering-shared-srcs",
     srcs: [
         "core/java/android/util/LocalLog.java",
+        "core/java/com/android/internal/util/BitUtils.java",
+        "core/java/com/android/internal/util/IndentingPrintWriter.java",
+        "core/java/com/android/internal/util/IState.java",
+        "core/java/com/android/internal/util/MessageUtils.java",
+        "core/java/com/android/internal/util/Preconditions.java",
+        "core/java/com/android/internal/util/State.java",
+        "core/java/com/android/internal/util/StateMachine.java",
+    ],
+}
+
+filegroup {
+    name: "framework-tethering-annotations",
+    srcs: [
+        "core/java/android/annotation/NonNull.java",
+        "core/java/android/annotation/SystemApi.java",
     ],
 }
 // Build ext.jar
@@ -909,653 +936,6 @@
     ],
 }
 
-// Make the api/current.txt file available for use by modules in other
-// directories.
-filegroup {
-    name: "frameworks-base-api-current.txt",
-    srcs: [
-        "api/current.txt",
-    ],
-}
-
-// Make the api/system-current.txt file available for use by modules in other
-// directories.
-filegroup {
-    name: "frameworks-base-api-system-current.txt",
-    srcs: [
-        "api/system-current.txt",
-    ],
-}
-
-// Make the api/system-removed.txt file available for use by modules in other
-// directories.
-filegroup {
-    name: "frameworks-base-api-system-removed.txt",
-    srcs: [
-        "api/system-removed.txt",
-    ],
-}
-
-framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
-    "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
-    "-overview $(location core/java/overview.html) " +
-    // Federate Support Library references against local API file.
-    "-federate SupportLib https://developer.android.com " +
-    "-federationapi SupportLib $(location :current-support-api) " +
-    // Federate Support Library references against local API file.
-    "-federate AndroidX https://developer.android.com " +
-    "-federationapi AndroidX $(location :current-androidx-api) "
-
-framework_docs_only_libs = [
-    "voip-common",
-    "android.test.mock",
-    "android-support-annotations",
-    "android-support-compat",
-    "android-support-core-ui",
-    "android-support-core-utils",
-    "android-support-customtabs",
-    "android-support-design",
-    "android-support-dynamic-animation",
-    "android-support-exifinterface",
-    "android-support-fragment",
-    "android-support-media-compat",
-    "android-support-percent",
-    "android-support-recommendation",
-    "android-support-transition",
-    "android-support-tv-provider",
-    "android-support-v7-cardview",
-    "android-support-v7-gridlayout",
-    "android-support-v7-mediarouter",
-    "android-support-v7-palette",
-    "android-support-v7-preference",
-    "android-support-v13",
-    "android-support-v14-preference",
-    "android-support-v17-leanback",
-    "android-support-v17-preference-leanback",
-    "android-support-wear",
-    "android-support-vectordrawable",
-    "android-support-animatedvectordrawable",
-    "android-support-v7-appcompat",
-    "android-support-v7-recyclerview",
-    "android-support-emoji",
-    "android-support-emoji-appcompat",
-    "android-support-emoji-bundled",
-    "android-support-v8-renderscript",
-    "android-support-multidex",
-    "android-support-multidex-instrumentation",
-]
-
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
-    "--ignore-classes-on-classpath " +
-    "--hide-package com.android.server " +
-    "--error UnhiddenSystemApi " +
-    "--hide RequiresPermission " +
-    "--hide CallbackInterface " +
-    "--hide MissingPermission --hide BroadcastBehavior " +
-    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
-    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
-    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
-
-packages_to_document = [
-    "android",
-    "dalvik",
-    "java",
-    "javax",
-    "junit",
-    "org.apache.http",
-    "org.json",
-    "org.w3c.dom",
-    "org.xml.sax",
-    "org.xmlpull",
-]
-
-stubs_defaults {
-    name: "framework-doc-stubs-default",
-    srcs: [
-        ":framework-mime-sources",
-        ":framework-non-updatable-sources",
-        ":framework-updatable-sources",
-        "core/java/**/*.logtags",
-        "test-base/src/**/*.java",
-        ":opt-telephony-srcs",
-        ":opt-net-voip-srcs",
-        ":core-current-stubs-source",
-        ":core_public_api_files",
-        "test-mock/src/**/*.java",
-        "test-runner/src/**/*.java",
-    ],
-    libs: framework_docs_only_libs,
-    create_doc_stubs: true,
-    annotations_enabled: true,
-    api_levels_annotations_enabled: true,
-    api_levels_annotations_dirs: [
-        "sdk-dir",
-        "api-versions-jars-dir",
-    ],
-    previous_api: ":last-released-public-api",
-    merge_annotations_dirs: [
-        "metalava-manual",
-    ],
-}
-
-doc_defaults {
-    name: "framework-docs-default",
-    libs: framework_docs_only_libs +
-        ["stub-annotations"],
-    html_dirs: [
-        "docs/html",
-    ],
-    knowntags: [
-        "docs/knowntags.txt",
-        ":known-oj-tags",
-    ],
-    custom_template: "droiddoc-templates-sdk",
-    resourcesdir: "docs/html/reference/images/",
-    resourcesoutdir: "reference/android/images/",
-    hdf: [
-        "dac true",
-        "sdk.codename O",
-        "sdk.preview.version 1",
-        "sdk.version 7.0",
-        "sdk.rel.id 1",
-        "sdk.preview 0",
-    ],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-        "core/java/overview.html",
-        ":current-support-api",
-        ":current-androidx-api",
-    ],
-    create_stubs: false,
-}
-
-doc_defaults {
-    name: "framework-dokka-docs-default",
-    create_stubs: false,
-}
-
-stubs_defaults {
-    name: "metalava-api-stubs-default",
-    srcs: [
-        ":framework-non-updatable-sources",
-        ":framework-updatable-sources",
-        "core/java/**/*.logtags",
-        ":opt-telephony-srcs",
-        ":opt-net-voip-srcs",
-        ":core-current-stubs-source",
-        ":core_public_api_files",
-        ":ike-api-srcs",
-    ],
-    libs: ["framework-internal-utils"],
-    installable: false,
-    annotations_enabled: true,
-    previous_api: ":last-released-public-api",
-    merge_annotations_dirs: [
-        "metalava-manual",
-    ],
-    api_levels_annotations_enabled: true,
-    api_levels_annotations_dirs: [
-        "sdk-dir",
-        "api-versions-jars-dir",
-    ],
-    sdk_version: "core_platform",
-    filter_packages: packages_to_document,
-}
-
-droidstubs {
-    name: "framework-doc-stubs",
-    defaults: ["framework-doc-stubs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    args: metalava_framework_docs_args,
-    write_sdk_values: true,
-}
-
-droidstubs {
-    name: "framework-doc-system-stubs",
-    defaults: ["framework-doc-stubs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi ",
-    write_sdk_values: true,
-}
-
-droiddoc {
-    name: "doc-comment-check-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    args: framework_docs_only_args + " -referenceonly -parsecomments",
-    installable: false,
-}
-
-droiddoc {
-    name: "offline-sdk-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc offline",
-    ],
-    proofread_file: "offline-sdk-docs-proofrerad.txt",
-    args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
-    static_doc_index_redirect: "docs/docs-preview-index.html",
-}
-
-droiddoc {
-    // Please sync with android-api-council@ before making any changes for the name property below.
-    // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
-    // See b/116221385 for reference.
-    name: "offline-sdk-referenceonly-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc offline",
-    ],
-    proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
-    args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
-    static_doc_index_redirect: "docs/docs-documentation-redirect.html",
-    static_doc_properties: "docs/source.properties",
-}
-
-droiddoc {
-    // Please sync with android-api-council@ before making any changes for the name property below.
-    // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
-    // See b/116221385 for reference.
-    name: "offline-system-sdk-referenceonly-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-system-stubs",
-    ],
-    hdf: [
-        "android.whichdoc offline",
-    ],
-    proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
-    args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
-    " -offlinemode -title \"Android System SDK\" -referenceonly",
-    static_doc_index_redirect: "docs/docs-documentation-redirect.html",
-    static_doc_properties: "docs/source.properties",
-}
-
-droiddoc {
-    name: "online-sdk-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc online",
-        "android.hasSamples true",
-    ],
-    proofread_file: "online-sdk-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -toroot / -samplegroup Admin " +
-        " -samplegroup Background " +
-        " -samplegroup Connectivity " +
-        " -samplegroup Content " +
-        " -samplegroup Input " +
-        " -samplegroup Media " +
-        " -samplegroup Notification " +
-        " -samplegroup RenderScript " +
-        " -samplegroup Security " +
-        " -samplegroup Sensors " +
-        " -samplegroup System " +
-        " -samplegroup Testing " +
-        " -samplegroup UI " +
-        " -samplegroup Views " +
-        " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
-    name: "online-system-api-sdk-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-system-stubs",
-    ],
-    hdf: [
-        "android.whichdoc online",
-        "android.hasSamples true",
-    ],
-    proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -referenceonly " +
-        " -title \"Android SDK - Including system APIs.\" " +
-        " -hide 101 " +
-        " -hide 104 " +
-        " -hide 108 " +
-        " -toroot / -samplegroup Admin " +
-        " -samplegroup Background " +
-        " -samplegroup Connectivity " +
-        " -samplegroup Content " +
-        " -samplegroup Input " +
-        " -samplegroup Media " +
-        " -samplegroup Notification " +
-        " -samplegroup RenderScript " +
-        " -samplegroup Security " +
-        " -samplegroup Sensors " +
-        " -samplegroup System " +
-        " -samplegroup Testing " +
-        " -samplegroup UI " +
-        " -samplegroup Views " +
-        " -samplegroup Wearable -samplesdir development/samples/browseable ",
-    installable: false,
-}
-
-droiddoc {
-    name: "ds-docs-java",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc online",
-        "android.hasSamples true",
-    ],
-    proofread_file: "ds-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
-        " -samplegroup Background " +
-        " -samplegroup Connectivity " +
-        " -samplegroup Content " +
-        " -samplegroup Input " +
-        " -samplegroup Media " +
-        " -samplegroup Notification " +
-        " -samplegroup RenderScript " +
-        " -samplegroup Security " +
-        " -samplegroup Sensors " +
-        " -samplegroup System " +
-        " -samplegroup Testing " +
-        " -samplegroup UI " +
-        " -samplegroup Views " +
-        " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
-    name: "ds-docs-kt",
-    defaults: ["framework-dokka-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
-    "-noStdlibLink",
-    proofread_file: "ds-dokka-proofread.txt",
-    dokka_enabled: true,
-}
-
-java_genrule {
-    name: "ds-docs",
-    tools: [
-        "zip2zip",
-        "merge_zips",
-    ],
-    srcs: [
-        ":ds-docs-java{.docs.zip}",
-        ":ds-docs-kt{.docs.zip}",
-    ],
-    out: ["ds-docs.zip"],
-    dist: {
-        targets: ["docs"],
-    },
-    cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " +
-         "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
-}
-
-java_genrule {
-    name: "ds-docs-switched",
-    tools: [
-        "switcher4",
-        "soong_zip",
-    ],
-    srcs: [
-        ":ds-docs-java{.docs.zip}",
-        ":ds-docs-kt{.docs.zip}",
-    ],
-    out: ["ds-docs-switched.zip"],
-    dist: {
-        targets: ["docs"],
-    },
-    cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
-         "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
-         "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
-         "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " +
-         "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
-}
-
-
-droiddoc {
-    name: "ds-static-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc online",
-    ],
-    proofread_file: "ds-static-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -staticonly " +
-        " -toroot / " +
-        " -devsite " +
-        " -ignoreJdLinks ",
-}
-
-droiddoc {
-    name: "ds-ref-navtree-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc online",
-    ],
-    proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -toroot / " +
-        " -atLinksNavtree " +
-        " -navtreeonly ",
-}
-
-droiddoc {
-    name: "online-sdk-dev-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    hdf: [
-        "android.whichdoc online",
-        "android.hasSamples true",
-    ],
-    proofread_file: "online-sdk-dev-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -toroot / -samplegroup Admin " +
-        " -samplegroup Background " +
-        " -samplegroup Connectivity " +
-        " -samplegroup Content " +
-        " -samplegroup Input " +
-        " -samplegroup Media " +
-        " -samplegroup Notification " +
-        " -samplegroup RenderScript " +
-        " -samplegroup Security " +
-        " -samplegroup Sensors " +
-        " -samplegroup System " +
-        " -samplegroup Testing " +
-        " -samplegroup UI " +
-        " -samplegroup Views " +
-        " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
-    name: "hidden-docs",
-    defaults: ["framework-docs-default"],
-    srcs: [
-        ":framework-doc-stubs",
-    ],
-    proofread_file: "hidden-docs-proofrerad.txt",
-    args: framework_docs_only_args +
-        " -referenceonly " +
-        " -title \"Android SDK - Including hidden APIs.\"",
-}
-
-droidstubs {
-    name: "hwbinder-stubs-docs",
-    srcs: [
-        "core/java/android/os/HidlSupport.java",
-        "core/java/android/annotation/IntDef.java",
-        "core/java/android/annotation/IntRange.java",
-        "core/java/android/annotation/NonNull.java",
-        "core/java/android/annotation/SystemApi.java",
-        "core/java/android/os/HidlMemory.java",
-        "core/java/android/os/HwBinder.java",
-        "core/java/android/os/HwBlob.java",
-        "core/java/android/os/HwParcel.java",
-        "core/java/android/os/IHwBinder.java",
-        "core/java/android/os/IHwInterface.java",
-        "core/java/android/os/DeadObjectException.java",
-        "core/java/android/os/DeadSystemException.java",
-        "core/java/android/os/NativeHandle.java",
-        "core/java/android/os/RemoteException.java",
-        "core/java/android/util/AndroidException.java",
-    ],
-    installable: false,
-    sdk_version: "core_platform",
-    annotations_enabled: true,
-    previous_api: ":last-released-public-api",
-    merge_annotations_dirs: [
-        "metalava-manual",
-    ],
-    args: " --show-annotation android.annotation.SystemApi",
-}
-
-java_library_static {
-    name: "hwbinder.stubs",
-    sdk_version: "core_current",
-    srcs: [
-        ":hwbinder-stubs-docs",
-    ],
-}
-
-droidstubs {
-    name: "hiddenapi-lists-docs",
-    defaults: ["metalava-api-stubs-default"],
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    dex_api_filename: "public-dex.txt",
-    private_dex_api_filename: "private-dex.txt",
-    removed_dex_api_filename: "removed-dex.txt",
-    args: metalava_framework_docs_args +
-        " --show-unannotated " +
-        " --show-annotation android.annotation.SystemApi " +
-        " --show-annotation android.annotation.TestApi ",
-}
-
-droidstubs {
-    name: "hiddenapi-mappings",
-    defaults: ["metalava-api-stubs-default"],
-    srcs: [
-        ":opt-telephony-common-srcs",
-    ],
-
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    dex_mapping_filename: "dex-mapping.txt",
-    args: metalava_framework_docs_args +
-        " --hide ReferencesHidden " +
-        " --hide UnhiddenSystemApi " +
-        " --show-unannotated " +
-        " --show-annotation android.annotation.SystemApi " +
-        " --show-annotation android.annotation.TestApi ",
-}
-
-droidstubs {
-    name: "api-stubs-docs",
-    defaults: ["metalava-api-stubs-default"],
-    api_filename: "public_api.txt",
-    private_api_filename: "private.txt",
-    removed_api_filename: "removed.txt",
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    args: metalava_framework_docs_args,
-    check_api: {
-        current: {
-            api_file: "api/current.txt",
-            removed_api_file: "api/removed.txt",
-        },
-        last_released: {
-            api_file: ":last-released-public-api",
-            removed_api_file: "api/removed.txt",
-            baseline_file: ":public-api-incompatibilities-with-last-released",
-        },
-        api_lint: {
-            enabled: true,
-            new_since: ":last-released-public-api",
-            baseline_file: "api/lint-baseline.txt",
-        },
-    },
-    jdiff_enabled: true,
-}
-
-droidstubs {
-    name: "system-api-stubs-docs",
-    defaults: ["metalava-api-stubs-default"],
-    api_tag_name: "SYSTEM",
-    api_filename: "system-api.txt",
-    private_api_filename: "system-private.txt",
-    private_dex_api_filename: "system-private-dex.txt",
-    removed_api_filename: "system-removed.txt",
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi",
-    check_api: {
-        current: {
-            api_file: "api/system-current.txt",
-            removed_api_file: "api/system-removed.txt",
-        },
-        last_released: {
-            api_file: ":last-released-system-api",
-            removed_api_file: "api/system-removed.txt",
-            baseline_file: ":system-api-incompatibilities-with-last-released"
-        },
-        api_lint: {
-            enabled: true,
-            new_since: ":last-released-system-api",
-            baseline_file: "api/system-lint-baseline.txt",
-        },
-    },
-    jdiff_enabled: true,
-}
-
-droidstubs {
-    name: "test-api-stubs-docs",
-    defaults: ["metalava-api-stubs-default"],
-    api_tag_name: "TEST",
-    api_filename: "test-api.txt",
-    removed_api_filename: "test-removed.txt",
-    arg_files: [
-        "core/res/AndroidManifest.xml",
-    ],
-    args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
-    check_api: {
-        current: {
-            api_file: "api/test-current.txt",
-            removed_api_file: "api/test-removed.txt",
-        },
-        api_lint: {
-            enabled: true,
-            baseline_file: "api/test-lint-baseline.txt",
-        },
-    },
-}
-
 filegroup {
     name: "framework-annotation-nonnull-srcs",
     srcs: [
@@ -1604,10 +984,13 @@
 filegroup {
     name: "framework-cellbroadcast-shared-srcs",
     srcs: [
-        "core/java/android/util/LocalLog.java",
+	"core/java/android/os/HandlerExecutor.java",
+	"core/java/android/util/LocalLog.java",
         "core/java/android/util/Slog.java",
-        "core/java/com/android/internal/util/State.java",
-        "core/java/com/android/internal/util/StateMachine.java",
+	"core/java/com/android/internal/util/IState.java",
+	"core/java/com/android/internal/util/Preconditions.java",
+	"core/java/com/android/internal/util/State.java",
+	"core/java/com/android/internal/util/StateMachine.java",
     ],
 }
 
@@ -1619,15 +1002,34 @@
         "core/java/android/os/RegistrantList.java",
         "core/java/android/os/Registrant.java",
         "core/java/android/util/LocalLog.java",
-        "core/java/android/util/Slog.java",
         "core/java/android/util/TimeUtils.java",
         "core/java/com/android/internal/os/SomeArgs.java",
+        "core/java/com/android/internal/util/AsyncChannel.java",
+        "core/java/com/android/internal/util/BitwiseInputStream.java",
+        "core/java/com/android/internal/util/FastXmlSerializer.java",
+        "core/java/com/android/internal/util/HexDump.java",
+        "core/java/com/android/internal/util/IState.java",
+        "core/java/com/android/internal/util/IndentingPrintWriter.java",
         "core/java/com/android/internal/util/Preconditions.java",
         "core/java/com/android/internal/util/State.java",
         "core/java/com/android/internal/util/StateMachine.java",
-        "core/java/com/android/internal/util/XmlUtils.java",
-        "core/java/com/android/internal/util/HexDump.java",
-        "core/java/com/android/internal/util/IndentingPrintWriter.java",
-        "core/java/com/android/internal/util/DumpUtils.java"
+        "core/java/com/android/internal/util/UserIcons.java",
     ],
 }
+
+// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
+metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
+    "--ignore-classes-on-classpath " +
+    "--hide-package com.android.server " +
+    "--error UnhiddenSystemApi " +
+    "--hide RequiresPermission " +
+    "--hide CallbackInterface " +
+    "--hide MissingPermission --hide BroadcastBehavior " +
+    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
+    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
+
+build = [
+    "StubLibraries.bp",
+    "ApiDocs.bp",
+]
diff --git a/ApiDocs.bp b/ApiDocs.bp
new file mode 100644
index 0000000..e373db6
--- /dev/null
+++ b/ApiDocs.bp
@@ -0,0 +1,436 @@
+// 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.
+
+// How API docs are generated:
+//
+// raw source files --(metalava)--> stub source files --(doclava)--> API doc
+//
+// The metalava conversion is done by droidstub modules framework-doc-*-stubs.
+// The API doc generation is done by the various droiddoc modules each of which
+// is for different format.
+
+/////////////////////////////////////////////////////////////////////
+// stub source files are generated using metalava
+/////////////////////////////////////////////////////////////////////
+
+framework_docs_only_libs = [
+    "voip-common",
+    "android.test.mock",
+    "android-support-annotations",
+    "android-support-compat",
+    "android-support-core-ui",
+    "android-support-core-utils",
+    "android-support-design",
+    "android-support-dynamic-animation",
+    "android-support-exifinterface",
+    "android-support-fragment",
+    "android-support-media-compat",
+    "android-support-percent",
+    "android-support-transition",
+    "android-support-v7-cardview",
+    "android-support-v7-gridlayout",
+    "android-support-v7-mediarouter",
+    "android-support-v7-palette",
+    "android-support-v7-preference",
+    "android-support-v13",
+    "android-support-v14-preference",
+    "android-support-v17-leanback",
+    "android-support-vectordrawable",
+    "android-support-animatedvectordrawable",
+    "android-support-v7-appcompat",
+    "android-support-v7-recyclerview",
+    "android-support-v8-renderscript",
+    "android-support-multidex",
+    "android-support-multidex-instrumentation",
+]
+
+stubs_defaults {
+    name: "framework-doc-stubs-default",
+    srcs: [
+        ":framework-mime-sources",
+        ":framework-non-updatable-sources",
+        ":framework-updatable-sources",
+        "core/java/**/*.logtags",
+        "test-base/src/**/*.java",
+        ":opt-telephony-srcs",
+        ":opt-net-voip-srcs",
+        ":core-current-stubs-source",
+        ":core_public_api_files",
+        "test-mock/src/**/*.java",
+        "test-runner/src/**/*.java",
+    ],
+    libs: framework_docs_only_libs,
+    create_doc_stubs: true,
+    annotations_enabled: true,
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
+    ],
+    previous_api: ":last-released-public-api",
+    merge_annotations_dirs: [
+        "metalava-manual",
+    ],
+}
+
+droidstubs {
+    name: "framework-doc-stubs",
+    defaults: ["framework-doc-stubs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args,
+    write_sdk_values: true,
+}
+
+droidstubs {
+    name: "framework-doc-system-stubs",
+    defaults: ["framework-doc-stubs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ",
+    write_sdk_values: true,
+}
+
+/////////////////////////////////////////////////////////////////////
+// API docs are created from the generated stub source files
+// using droiddoc
+/////////////////////////////////////////////////////////////////////
+
+framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+    "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
+    "-overview $(location core/java/overview.html) " +
+    // Federate Support Library references against local API file.
+    "-federate SupportLib https://developer.android.com " +
+    "-federationapi SupportLib $(location :current-support-api) " +
+    // Federate Support Library references against local API file.
+    "-federate AndroidX https://developer.android.com " +
+    "-federationapi AndroidX $(location :current-androidx-api) "
+
+doc_defaults {
+    name: "framework-docs-default",
+    libs: framework_docs_only_libs +
+        ["stub-annotations"],
+    html_dirs: [
+        "docs/html",
+    ],
+    knowntags: [
+        "docs/knowntags.txt",
+        ":known-oj-tags",
+    ],
+    custom_template: "droiddoc-templates-sdk",
+    resourcesdir: "docs/html/reference/images/",
+    resourcesoutdir: "reference/android/images/",
+    hdf: [
+        "dac true",
+        "sdk.codename O",
+        "sdk.preview.version 1",
+        "sdk.version 7.0",
+        "sdk.rel.id 1",
+        "sdk.preview 0",
+    ],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+        "core/java/overview.html",
+        ":current-support-api",
+        ":current-androidx-api",
+    ],
+    create_stubs: false,
+}
+
+doc_defaults {
+    name: "framework-dokka-docs-default",
+    create_stubs: false,
+}
+
+droiddoc {
+    name: "doc-comment-check-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    args: framework_docs_only_args + " -referenceonly -parsecomments",
+    installable: false,
+}
+
+droiddoc {
+    name: "offline-sdk-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc offline",
+    ],
+    proofread_file: "offline-sdk-docs-proofrerad.txt",
+    args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
+    static_doc_index_redirect: "docs/docs-preview-index.html",
+}
+
+droiddoc {
+    // Please sync with android-api-council@ before making any changes for the name property below.
+    // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
+    // See b/116221385 for reference.
+    name: "offline-sdk-referenceonly-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc offline",
+    ],
+    proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
+    args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
+    static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+    static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+    // Please sync with android-api-council@ before making any changes for the name property below.
+    // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
+    // See b/116221385 for reference.
+    name: "offline-system-sdk-referenceonly-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-system-stubs",
+    ],
+    hdf: [
+        "android.whichdoc offline",
+    ],
+    proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
+    args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
+    " -offlinemode -title \"Android System SDK\" -referenceonly",
+    static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+    static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+    name: "online-sdk-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "online-sdk-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+    name: "online-system-api-sdk-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-system-stubs",
+    ],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -referenceonly " +
+        " -title \"Android SDK - Including system APIs.\" " +
+        " -hide 101 " +
+        " -hide 104 " +
+        " -hide 108 " +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -samplesdir development/samples/browseable ",
+    installable: false,
+}
+
+droiddoc {
+    name: "ds-docs-java",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "ds-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+    name: "ds-docs-kt",
+    defaults: ["framework-dokka-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
+    "-noStdlibLink",
+    proofread_file: "ds-dokka-proofread.txt",
+    dokka_enabled: true,
+}
+
+java_genrule {
+    name: "ds-docs",
+    tools: [
+        "zip2zip",
+        "merge_zips",
+    ],
+    srcs: [
+        ":ds-docs-java{.docs.zip}",
+        ":ds-docs-kt{.docs.zip}",
+    ],
+    out: ["ds-docs.zip"],
+    dist: {
+        targets: ["docs"],
+    },
+    cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " +
+         "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
+}
+
+java_genrule {
+    name: "ds-docs-switched",
+    tools: [
+        "switcher4",
+        "soong_zip",
+    ],
+    srcs: [
+        ":ds-docs-java{.docs.zip}",
+        ":ds-docs-kt{.docs.zip}",
+    ],
+    out: ["ds-docs-switched.zip"],
+    dist: {
+        targets: ["docs"],
+    },
+    cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
+         "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
+         "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
+         "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " +
+         "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
+}
+
+droiddoc {
+    name: "ds-static-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc online",
+    ],
+    proofread_file: "ds-static-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -staticonly " +
+        " -toroot / " +
+        " -devsite " +
+        " -ignoreJdLinks ",
+}
+
+droiddoc {
+    name: "ds-ref-navtree-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc online",
+    ],
+    proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -toroot / " +
+        " -atLinksNavtree " +
+        " -navtreeonly ",
+}
+
+droiddoc {
+    name: "online-sdk-dev-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    hdf: [
+        "android.whichdoc online",
+        "android.hasSamples true",
+    ],
+    proofread_file: "online-sdk-dev-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -toroot / -samplegroup Admin " +
+        " -samplegroup Background " +
+        " -samplegroup Connectivity " +
+        " -samplegroup Content " +
+        " -samplegroup Input " +
+        " -samplegroup Media " +
+        " -samplegroup Notification " +
+        " -samplegroup RenderScript " +
+        " -samplegroup Security " +
+        " -samplegroup Sensors " +
+        " -samplegroup System " +
+        " -samplegroup Testing " +
+        " -samplegroup UI " +
+        " -samplegroup Views " +
+        " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+    name: "hidden-docs",
+    defaults: ["framework-docs-default"],
+    srcs: [
+        ":framework-doc-stubs",
+    ],
+    proofread_file: "hidden-docs-proofrerad.txt",
+    args: framework_docs_only_args +
+        " -referenceonly " +
+        " -title \"Android SDK - Including hidden APIs.\"",
+}
+
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f7a2858..3047dd7 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -255,6 +255,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/CaptivePortalLogin)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/ext.jar)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/google/android/mms)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
 # ******************************************************************
diff --git a/StubLibraries.bp b/StubLibraries.bp
new file mode 100644
index 0000000..78f1b9c
--- /dev/null
+++ b/StubLibraries.bp
@@ -0,0 +1,340 @@
+// 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.
+
+// How stubs are generated:
+//
+// raw source files --(metalava)--> stub source files --(javac)--> stub jar files
+//
+// The metalava conversion is done by droidstub modules *-api-stubs-docs.
+// The javac compilation is done by java_library modules android_*_stubs_current.
+// The metalava conversion is also responsible for creating API signature files
+// and comparing them against the last API signature in api/*-current.txt files
+// and also against the latest frozen API signature in prebuilts/sdk/*/*/api/android.txt
+// files.
+
+/////////////////////////////////////////////////////////////////////
+// Common metalava configs
+/////////////////////////////////////////////////////////////////////
+
+packages_to_document = [
+    "android",
+    "dalvik",
+    "java",
+    "javax",
+    "junit",
+    "org.apache.http",
+    "org.json",
+    "org.w3c.dom",
+    "org.xml.sax",
+    "org.xmlpull",
+]
+
+stubs_defaults {
+    name: "metalava-api-stubs-default",
+    srcs: [
+        ":framework-non-updatable-sources",
+        ":framework-updatable-sources",
+        "core/java/**/*.logtags",
+        ":opt-telephony-srcs",
+        ":opt-net-voip-srcs",
+        ":core-current-stubs-source",
+        ":core_public_api_files",
+        ":ike-api-srcs",
+    ],
+    libs: ["framework-internal-utils"],
+    installable: false,
+    annotations_enabled: true,
+    previous_api: ":last-released-public-api",
+    merge_annotations_dirs: [
+        "metalava-manual",
+    ],
+    api_levels_annotations_enabled: true,
+    api_levels_annotations_dirs: [
+        "sdk-dir",
+        "api-versions-jars-dir",
+    ],
+    sdk_version: "core_platform",
+    filter_packages: packages_to_document,
+}
+
+/////////////////////////////////////////////////////////////////////
+// *-api-stubs-docs modules providing source files for the stub libraries
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+    name: "api-stubs-docs",
+    defaults: ["metalava-api-stubs-default"],
+    api_filename: "public_api.txt",
+    private_api_filename: "private.txt",
+    removed_api_filename: "removed.txt",
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args,
+    check_api: {
+        current: {
+            api_file: "api/current.txt",
+            removed_api_file: "api/removed.txt",
+        },
+        last_released: {
+            api_file: ":last-released-public-api",
+            removed_api_file: "api/removed.txt",
+            baseline_file: ":public-api-incompatibilities-with-last-released",
+        },
+        api_lint: {
+            enabled: true,
+            new_since: ":last-released-public-api",
+            baseline_file: "api/lint-baseline.txt",
+        },
+    },
+    jdiff_enabled: true,
+}
+
+droidstubs {
+    name: "system-api-stubs-docs",
+    defaults: ["metalava-api-stubs-default"],
+    api_tag_name: "SYSTEM",
+    api_filename: "system-api.txt",
+    private_api_filename: "system-private.txt",
+    private_dex_api_filename: "system-private-dex.txt",
+    removed_api_filename: "system-removed.txt",
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+    check_api: {
+        current: {
+            api_file: "api/system-current.txt",
+            removed_api_file: "api/system-removed.txt",
+        },
+        last_released: {
+            api_file: ":last-released-system-api",
+            removed_api_file: "api/system-removed.txt",
+            baseline_file: ":system-api-incompatibilities-with-last-released"
+        },
+        api_lint: {
+            enabled: true,
+            new_since: ":last-released-system-api",
+            baseline_file: "api/system-lint-baseline.txt",
+        },
+    },
+    jdiff_enabled: true,
+}
+
+droidstubs {
+    name: "test-api-stubs-docs",
+    defaults: ["metalava-api-stubs-default"],
+    api_tag_name: "TEST",
+    api_filename: "test-api.txt",
+    removed_api_filename: "test-removed.txt",
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
+    check_api: {
+        current: {
+            api_file: "api/test-current.txt",
+            removed_api_file: "api/test-removed.txt",
+        },
+        api_lint: {
+            enabled: true,
+            baseline_file: "api/test-lint-baseline.txt",
+        },
+    },
+}
+
+/////////////////////////////////////////////////////////////////////
+// android_*_stubs_current modules are the stubs libraries compiled
+// from *-api-stubs-docs
+/////////////////////////////////////////////////////////////////////
+
+java_defaults {
+    name: "framework-stubs-default",
+    errorprone: {
+        javacflags: [
+            "-XepDisableAllChecks",
+        ],
+    },
+    java_resources: [
+        ":notices-for-framework-stubs",
+    ],
+    sdk_version: "core_current",
+    system_modules: "none",
+    java_version: "1.8",
+    compile_dex: true,
+}
+
+java_library_static {
+    name: "android_stubs_current",
+    srcs: [
+        ":api-stubs-docs",
+    ],
+    libs: [
+        "stub-annotations",
+    ],
+    static_libs: [
+        "private-stub-annotations-jar",
+    ],
+    defaults: ["framework-stubs-default"],
+}
+
+java_library_static {
+    name: "android_system_stubs_current",
+    srcs: [
+        ":system-api-stubs-docs",
+    ],
+    libs: [
+        "stub-annotations",
+    ],
+    static_libs: [
+        "private-stub-annotations-jar",
+    ],
+    defaults: ["framework-stubs-default"],
+}
+
+java_library_static {
+    name: "android_test_stubs_current",
+    srcs: [
+        ":test-api-stubs-docs",
+    ],
+    libs: [
+        "stub-annotations",
+    ],
+    static_libs: [
+        "private-stub-annotations-jar",
+    ],
+    defaults: ["framework-stubs-default"],
+}
+
+java_system_modules {
+    name: "android_stubs_current_system_modules",
+    libs: ["android_stubs_current"],
+}
+
+java_system_modules {
+    name: "android_system_stubs_current_system_modules",
+    libs: ["android_system_stubs_current"],
+}
+
+java_system_modules {
+    name: "android_test_stubs_current_system_modules",
+    libs: ["android_test_stubs_current"],
+}
+
+/////////////////////////////////////////////////////////////////////
+// hwbinder.stubs provides APIs required for building HIDL Java
+// libraries.
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+    name: "hwbinder-stubs-docs",
+    srcs: [
+        "core/java/android/os/HidlSupport.java",
+        "core/java/android/annotation/IntDef.java",
+        "core/java/android/annotation/IntRange.java",
+        "core/java/android/annotation/NonNull.java",
+        "core/java/android/annotation/SystemApi.java",
+        "core/java/android/os/HidlMemory.java",
+        "core/java/android/os/HwBinder.java",
+        "core/java/android/os/HwBlob.java",
+        "core/java/android/os/HwParcel.java",
+        "core/java/android/os/IHwBinder.java",
+        "core/java/android/os/IHwInterface.java",
+        "core/java/android/os/DeadObjectException.java",
+        "core/java/android/os/DeadSystemException.java",
+        "core/java/android/os/NativeHandle.java",
+        "core/java/android/os/RemoteException.java",
+        "core/java/android/util/AndroidException.java",
+    ],
+    installable: false,
+    sdk_version: "core_platform",
+    annotations_enabled: true,
+    previous_api: ":last-released-public-api",
+    merge_annotations_dirs: [
+        "metalava-manual",
+    ],
+    args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+}
+
+java_library_static {
+    name: "hwbinder.stubs",
+    sdk_version: "core_current",
+    srcs: [
+        ":hwbinder-stubs-docs",
+    ],
+}
+
+/////////////////////////////////////////////////////////////////////
+// Stubs for hiddenapi processing.
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+    name: "hiddenapi-lists-docs",
+    defaults: ["metalava-api-stubs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    dex_api_filename: "public-dex.txt",
+    private_dex_api_filename: "private-dex.txt",
+    removed_dex_api_filename: "removed-dex.txt",
+    args: metalava_framework_docs_args +
+        " --show-unannotated " +
+        " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
+        " --show-annotation android.annotation.TestApi ",
+}
+
+droidstubs {
+    name: "hiddenapi-mappings",
+    defaults: ["metalava-api-stubs-default"],
+    srcs: [
+        ":opt-telephony-common-srcs",
+    ],
+
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+    ],
+    dex_mapping_filename: "dex-mapping.txt",
+    args: metalava_framework_docs_args +
+        " --hide ReferencesHidden " +
+        " --hide UnhiddenSystemApi " +
+        " --show-unannotated " +
+        " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
+        " --show-annotation android.annotation.TestApi ",
+}
+
+/////////////////////////////////////////////////////////////////////
+// api/*-current.txt files for use by modules in other directories
+// like the CTS test
+/////////////////////////////////////////////////////////////////////
+
+filegroup {
+    name: "frameworks-base-api-current.txt",
+    srcs: [
+        "api/current.txt",
+    ],
+}
+
+filegroup {
+    name: "frameworks-base-api-system-current.txt",
+    srcs: [
+        "api/system-current.txt",
+    ],
+}
+
+filegroup {
+    name: "frameworks-base-api-system-removed.txt",
+    srcs: [
+        "api/system-removed.txt",
+    ],
+}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 1e0b58e..1a6f104 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,6 +7,50 @@
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
+    },
+    {
+      "name": "ExtServicesUnitTests",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "TestablesTests",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    },
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
     }
   ]
 }
diff --git a/apex/Android.bp b/apex/Android.bp
new file mode 100644
index 0000000..9ea3953
--- /dev/null
+++ b/apex/Android.bp
@@ -0,0 +1,39 @@
+// 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.
+
+mainline_stubs_args =
+    "--error UnhiddenSystemApi " +
+    "--hide BroadcastBehavior " +
+    "--hide DeprecationMismatch " +
+    "--hide HiddenSuperclass " +
+    "--hide HiddenTypedefConstant " +
+    "--hide HiddenTypeParameter " +
+    "--hide MissingPermission " +
+    "--hide RequiresPermission " +
+    "--hide SdkConstant " +
+    "--hide Todo " +
+    "--hide Typo " +
+    "--hide UnavailableSymbol "
+
+stubs_defaults {
+    name: "framework-module-stubs-defaults-publicapi",
+    args: mainline_stubs_args,
+    installable: false,
+}
+
+stubs_defaults {
+    name: "framework-module-stubs-defaults-systemapi",
+    args: mainline_stubs_args + " --show-annotation android.annotation.SystemApi ",
+    installable: false,
+}
diff --git a/apex/sdkext/Android.bp b/apex/sdkext/Android.bp
index b8dcb90..f62f167 100644
--- a/apex/sdkext/Android.bp
+++ b/apex/sdkext/Android.bp
@@ -12,14 +12,29 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_visibility: [":__subpackages__"],
+}
+
 apex {
     name: "com.android.sdkext",
     manifest: "manifest.json",
+    binaries: [ "derive_sdk" ],
     java_libs: [ "framework-sdkext" ],
+    prebuilts: [
+      "com.android.sdkext.ldconfig",
+      "cur_sdkinfo",
+      "derive_sdk.rc",
+    ],
     key: "com.android.sdkext.key",
     certificate: ":com.android.sdkext.certificate",
 }
 
+sdk {
+    name: "sdkext-sdk",
+    java_header_libs: [ "framework-sdkext-stubs-systemapi" ],
+}
+
 apex_key {
     name: "com.android.sdkext.key",
     public_key: "com.android.sdkext.avbpubkey",
@@ -30,3 +45,40 @@
     name: "com.android.sdkext.certificate",
     certificate: "com.android.sdkext",
 }
+
+prebuilt_etc {
+    name: "com.android.sdkext.ldconfig",
+    src: "ld.config.txt",
+    filename: "ld.config.txt",
+    installable: false,
+}
+
+python_binary_host {
+    name: "gen_sdkinfo",
+    srcs: [
+        "sdk.proto",
+        "gen_sdkinfo.py",
+    ],
+    proto: {
+        canonical_path_from_root: false,
+    },
+    version: {
+        py3: {
+            embedded_launcher: true,
+        },
+    },
+}
+
+gensrcs {
+    name: "cur_sdkinfo_src",
+    srcs: [""],
+    tools: [ "gen_sdkinfo" ],
+    cmd: "$(location) -v 0 -o $(out)",
+}
+
+prebuilt_etc {
+    name: "cur_sdkinfo",
+    src: ":cur_sdkinfo_src",
+    filename: "sdkinfo.binarypb",
+    installable: false,
+}
diff --git a/apex/sdkext/TEST_MAPPING b/apex/sdkext/TEST_MAPPING
new file mode 100644
index 0000000..91947f3
--- /dev/null
+++ b/apex/sdkext/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsSdkExtTestCases"
+    }
+  ]
+}
diff --git a/apex/sdkext/derive_sdk/Android.bp b/apex/sdkext/derive_sdk/Android.bp
new file mode 100644
index 0000000..c4e3c29
--- /dev/null
+++ b/apex/sdkext/derive_sdk/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+cc_binary {
+    name: "derive_sdk",
+    srcs: [
+        "derive_sdk.cpp",
+        "sdk.proto",
+    ],
+    proto: {
+        type: "lite",
+    },
+    sdk_version: "current",
+    stl: "c++_static",
+    shared_libs: [ "liblog" ],
+    static_libs: [
+        "libbase_ndk",
+        "libprotobuf-cpp-lite-ndk",
+    ],
+}
+
+prebuilt_etc {
+    name: "derive_sdk.rc",
+    src: "derive_sdk.rc",
+    installable: false,
+}
diff --git a/apex/sdkext/derive_sdk/derive_sdk.cpp b/apex/sdkext/derive_sdk/derive_sdk.cpp
new file mode 100644
index 0000000..0a97116
--- /dev/null
+++ b/apex/sdkext/derive_sdk/derive_sdk.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "derive_sdk"
+
+#include <algorithm>
+#include <dirent.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+
+#include "frameworks/base/apex/sdkext/derive_sdk/sdk.pb.h"
+
+using com::android::sdkext::proto::SdkVersion;
+
+int main(int, char**) {
+    std::unique_ptr<DIR, decltype(&closedir)> apex(opendir("/apex"), closedir);
+    if (!apex) {
+        LOG(ERROR) << "Could not read /apex";
+        return EXIT_FAILURE;
+    }
+    struct dirent* de;
+    std::vector<std::string> paths;
+    while ((de = readdir(apex.get()))) {
+        std::string name = de->d_name;
+        if (name[0] == '.' || name.find('@') != std::string::npos) {
+            // Skip <name>@<ver> dirs, as they are bind-mounted to <name>
+            continue;
+        }
+        std::string path = "/apex/" + name + "/etc/sdkinfo.binarypb";
+        struct stat statbuf;
+        if (stat(path.c_str(), &statbuf) == 0) {
+            paths.push_back(path);
+        }
+    }
+
+    std::vector<int> versions;
+    for (const auto& path : paths) {
+        std::string contents;
+        if (!android::base::ReadFileToString(path, &contents, true)) {
+            LOG(ERROR) << "failed to read " << path;
+            continue;
+        }
+        SdkVersion sdk_version;
+        if (!sdk_version.ParseFromString(contents)) {
+            LOG(ERROR) << "failed to parse " << path;
+            continue;
+        }
+        LOG(INFO) << "Read version " << sdk_version.version() << " from " << path;
+        versions.push_back(sdk_version.version());
+    }
+    auto itr = std::min_element(versions.begin(), versions.end());
+    std::string prop_value = itr == versions.end() ? "0" : std::to_string(*itr);
+
+    if (!android::base::SetProperty("ro.build.version.extensions.r", prop_value)) {
+        LOG(ERROR) << "failed to set sdk_info prop";
+        return EXIT_FAILURE;
+    }
+
+    LOG(INFO) << "R extension version is " << prop_value;
+    return EXIT_SUCCESS;
+}
diff --git a/apex/sdkext/derive_sdk/derive_sdk.rc b/apex/sdkext/derive_sdk/derive_sdk.rc
new file mode 100644
index 0000000..1b66794
--- /dev/null
+++ b/apex/sdkext/derive_sdk/derive_sdk.rc
@@ -0,0 +1,3 @@
+service derive_sdk /apex/com.android.sdkext/bin/derive_sdk
+    oneshot
+    disabled
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/apex/sdkext/derive_sdk/sdk.proto
similarity index 73%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to apex/sdkext/derive_sdk/sdk.proto
index d502088..d15b935 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/apex/sdkext/derive_sdk/sdk.proto
@@ -14,15 +14,12 @@
  * limitations under the License.
  */
 
-package android.net;
+syntax = "proto3";
+package com.android.sdkext.proto;
 
-import android.net.Network;
+option java_outer_classname = "SdkProto";
+option optimize_for = LITE_RUNTIME;
 
-/**
- * Callback class for receiving tethering changed events
- * @hide
- */
-oneway interface ITetheringEventCallback
-{
-    void onUpstreamChanged(in Network network);
+message SdkVersion {
+  int32 version = 1;
 }
diff --git a/apex/sdkext/framework/Android.bp b/apex/sdkext/framework/Android.bp
index b17f0f8..a50dc3d 100644
--- a/apex/sdkext/framework/Android.bp
+++ b/apex/sdkext/framework/Android.bp
@@ -12,12 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_visibility: [ ":__pkg__" ]
+}
+
 filegroup {
     name: "framework-sdkext-sources",
     srcs: [
         "java/**/*.java",
     ],
     path: "java",
+    visibility: [ "//frameworks/base:__pkg__" ] // For the "global" stubs.
 }
 
 java_library {
@@ -27,4 +32,40 @@
     libs: [ "framework-annotations-lib" ],
     permitted_packages: [ "android.os.ext" ],
     installable: true,
+    visibility: [ "//frameworks/base/apex/sdkext:__pkg__" ],
+}
+
+droidstubs {
+    name: "framework-sdkext-droidstubs-publicapi",
+    defaults: [
+        "framework-sdkext-stubs-defaults",
+        "framework-module-stubs-defaults-publicapi",
+    ]
+}
+
+droidstubs {
+    name: "framework-sdkext-droidstubs-systemapi",
+    defaults: [
+        "framework-sdkext-stubs-defaults",
+        "framework-module-stubs-defaults-systemapi",
+    ]
+}
+
+stubs_defaults {
+    name: "framework-sdkext-stubs-defaults",
+    srcs: [
+        ":framework-sdkext-sources",
+        ":framework-annotations",
+    ],
+    sdk_version: "system_current",
+}
+
+java_library {
+    name: "framework-sdkext-stubs-systemapi",
+    srcs: [":framework-sdkext-droidstubs-systemapi"],
+    sdk_version: "system_current",
+    visibility: [
+      "//frameworks/base:__pkg__", // Framework
+      "//frameworks/base/apex/sdkext:__pkg__", // sdkext SDK
+    ]
 }
diff --git a/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java b/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
index c039a82..a8a7eff 100644
--- a/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
+++ b/apex/sdkext/framework/java/android/os/ext/SdkExtensions.java
@@ -17,25 +17,40 @@
 package android.os.ext;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.os.Build.VERSION_CODES;
 import android.os.SystemProperties;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-/** @hide */
+/**
+ * Methods for interacting with the extension SDK.
+ *
+ * This class provides information about the extension SDK version present
+ * on this device. Use the {@link #getExtensionVersion(int) getExtension} to
+ * query for the extension version for the given SDK version.
+
+ * @hide
+ */
+@SystemApi
 public class SdkExtensions {
 
     private static final int R_EXTENSION_INT;
     static {
-        R_EXTENSION_INT = SystemProperties.getInt("persist.com.android.sdkext.sdk_info", 0);
+        R_EXTENSION_INT = SystemProperties.getInt("ro.build.version.extensions.r", 0);
     }
 
-    /** Values suitable as parameters for {@link #getExtensionVersion(int)}. */
+    /**
+     * Values suitable as parameters for {@link #getExtensionVersion(int)}.
+     * @hide
+     */
     @IntDef(value = { VERSION_CODES.R })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SdkVersion {}
 
+    private SdkExtensions() { }
+
     /**
      * Return the version of the extension to the given SDK.
      *
@@ -45,7 +60,7 @@
      */
     public static int getExtensionVersion(@SdkVersion int sdk) {
         if (sdk < VERSION_CODES.R) {
-            throw new IllegalArgumentException();
+            throw new IllegalArgumentException(String.valueOf(sdk) + " does not have extensions");
         }
         return R_EXTENSION_INT;
     }
diff --git a/apex/sdkext/framework/tests/Android.bp b/apex/sdkext/framework/tests/Android.bp
deleted file mode 100644
index 3d5dbb3..0000000
--- a/apex/sdkext/framework/tests/Android.bp
+++ /dev/null
@@ -1,10 +0,0 @@
-android_test {
-    name: "framework-sdkext-tests",
-    srcs: ["src/**/*.java"],
-    libs: [
-        "android.test.base",
-        "android.test.runner",
-    ],
-    static_libs: [ "framework-sdkext" ],
-    platform_apis: true,
-}
diff --git a/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java b/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
deleted file mode 100644
index 6885110..0000000
--- a/apex/sdkext/framework/tests/src/android/os/ext/SdkExtensionsTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.ext;
-
-import android.os.Build;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-public class SdkExtensionsTest extends TestCase {
-
-    @SmallTest
-    public void testBadArgument() throws Exception {
-        try {
-            SdkExtensions.getExtensionVersion(Build.VERSION_CODES.Q);
-            fail("expected IllegalArgumentException");
-        } catch (IllegalArgumentException expected) { }
-
-        try {
-            SdkExtensions.getExtensionVersion(999999);
-            fail("expected IllegalArgumentException");
-        } catch (IllegalArgumentException expected) { }
-    }
-
-    @SmallTest
-    public void testDefault() throws Exception {
-        int r = SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R);
-        assertTrue(r >= 0);
-    }
-
-}
diff --git a/apex/sdkext/gen_sdkinfo.py b/apex/sdkext/gen_sdkinfo.py
new file mode 100644
index 0000000..5af478b
--- /dev/null
+++ b/apex/sdkext/gen_sdkinfo.py
@@ -0,0 +1,19 @@
+import sdk_pb2
+import sys
+
+if __name__ == '__main__':
+  argv = sys.argv[1:]
+  if not len(argv) == 4 or sorted([argv[0], argv[2]]) != ['-o', '-v']:
+    print('usage: gen_sdkinfo -v <version> -o <output-file>')
+    sys.exit(1)
+
+  for i in range(len(argv)):
+    if sys.argv[i] == '-o':
+      filename = sys.argv[i+1]
+    if sys.argv[i] == '-v':
+      version = int(sys.argv[i+1])
+
+  proto = sdk_pb2.SdkVersion()
+  proto.version = version
+  with open(filename, 'wb') as f:
+    f.write(proto.SerializeToString())
diff --git a/apex/sdkext/ld.config.txt b/apex/sdkext/ld.config.txt
new file mode 100644
index 0000000..b447068
--- /dev/null
+++ b/apex/sdkext/ld.config.txt
@@ -0,0 +1,31 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Bionic loader config file for the sdkext apex.
+
+dir.sdkext = /apex/com.android.sdkext/bin/
+
+[sdkext]
+additional.namespaces = platform
+
+namespace.default.isolated = true
+namespace.default.links = platform
+namespace.default.link.platform.allow_all_shared_libs = true
+
+###############################################################################
+# "platform" namespace: used for NDK libraries
+###############################################################################
+namespace.platform.isolated = true
+namespace.platform.search.paths = /system/${LIB}
+namespace.platform.asan.search.paths = /data/asan/system/${LIB}
+
+# /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc.
+# Add /apex/... path to the permitted paths because linker uses realpath(3)
+# to check the accessibility of the lib. We could add this to search.paths
+# instead but that makes the resolution of bionic libs be dependent on
+# the order of /system/lib and /apex/... in search.paths. If /apex/...
+# is after /system/lib, then /apex/... is never tried because libc.so
+# is always found in /system/lib but fails to pass the accessibility test
+# because of its realpath.  It's better to not depend on the ordering if
+# possible.
+namespace.platform.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
+namespace.platform.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/apex/sdkext/sdk.proto
similarity index 73%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to apex/sdkext/sdk.proto
index d502088..d15b935 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/apex/sdkext/sdk.proto
@@ -14,15 +14,12 @@
  * limitations under the License.
  */
 
-package android.net;
+syntax = "proto3";
+package com.android.sdkext.proto;
 
-import android.net.Network;
+option java_outer_classname = "SdkProto";
+option optimize_for = LITE_RUNTIME;
 
-/**
- * Callback class for receiving tethering changed events
- * @hide
- */
-oneway interface ITetheringEventCallback
-{
-    void onUpstreamChanged(in Network network);
+message SdkVersion {
+  int32 version = 1;
 }
diff --git a/api/current.txt b/api/current.txt
index 4850897..b99f8de 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -99,6 +99,7 @@
     field public static final String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
     field public static final String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
     field public static final String NFC = "android.permission.NFC";
+    field public static final String NFC_PREFERRED_PAYMENT_INFO = "android.permission.NFC_PREFERRED_PAYMENT_INFO";
     field public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
     field public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
     field @Deprecated public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
@@ -19379,6 +19380,197 @@
 
 }
 
+package android.icu.number {
+
+  public class CompactNotation extends android.icu.number.Notation {
+  }
+
+  public abstract class CurrencyPrecision extends android.icu.number.Precision {
+    method public android.icu.number.Precision withCurrency(android.icu.util.Currency);
+  }
+
+  public class FormattedNumber implements java.lang.CharSequence {
+    method public char charAt(int);
+    method public int length();
+    method public CharSequence subSequence(int, int);
+    method public java.math.BigDecimal toBigDecimal();
+    method public java.text.AttributedCharacterIterator toCharacterIterator();
+  }
+
+  public class FormattedNumberRange implements java.lang.CharSequence {
+    method public char charAt(int);
+    method public java.math.BigDecimal getFirstBigDecimal();
+    method public android.icu.number.NumberRangeFormatter.RangeIdentityResult getIdentityResult();
+    method public java.math.BigDecimal getSecondBigDecimal();
+    method public int length();
+    method public CharSequence subSequence(int, int);
+    method public java.text.AttributedCharacterIterator toCharacterIterator();
+  }
+
+  public abstract class FractionPrecision extends android.icu.number.Precision {
+    method public android.icu.number.Precision withMaxDigits(int);
+    method public android.icu.number.Precision withMinDigits(int);
+  }
+
+  public class IntegerWidth {
+    method public android.icu.number.IntegerWidth truncateAt(int);
+    method public static android.icu.number.IntegerWidth zeroFillTo(int);
+  }
+
+  public class LocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.LocalizedNumberFormatter> {
+    method public android.icu.number.FormattedNumber format(long);
+    method public android.icu.number.FormattedNumber format(double);
+    method public android.icu.number.FormattedNumber format(Number);
+    method public android.icu.number.FormattedNumber format(android.icu.util.Measure);
+    method public java.text.Format toFormat();
+  }
+
+  public class LocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.LocalizedNumberRangeFormatter> {
+    method public android.icu.number.FormattedNumberRange formatRange(int, int);
+    method public android.icu.number.FormattedNumberRange formatRange(double, double);
+    method public android.icu.number.FormattedNumberRange formatRange(Number, Number);
+  }
+
+  public class Notation {
+    method public static android.icu.number.CompactNotation compactLong();
+    method public static android.icu.number.CompactNotation compactShort();
+    method public static android.icu.number.ScientificNotation engineering();
+    method public static android.icu.number.ScientificNotation scientific();
+    method public static android.icu.number.SimpleNotation simple();
+  }
+
+  public final class NumberFormatter {
+    method public static android.icu.number.UnlocalizedNumberFormatter with();
+    method public static android.icu.number.LocalizedNumberFormatter withLocale(java.util.Locale);
+    method public static android.icu.number.LocalizedNumberFormatter withLocale(android.icu.util.ULocale);
+  }
+
+  public enum NumberFormatter.DecimalSeparatorDisplay {
+    enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay ALWAYS;
+    enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay AUTO;
+  }
+
+  public enum NumberFormatter.GroupingStrategy {
+    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy AUTO;
+    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy MIN2;
+    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy OFF;
+    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy ON_ALIGNED;
+    enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy THOUSANDS;
+  }
+
+  public enum NumberFormatter.SignDisplay {
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING;
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_ALWAYS;
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_EXCEPT_ZERO;
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ALWAYS;
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay AUTO;
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay EXCEPT_ZERO;
+    enum_constant public static final android.icu.number.NumberFormatter.SignDisplay NEVER;
+  }
+
+  public enum NumberFormatter.UnitWidth {
+    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth FULL_NAME;
+    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth HIDDEN;
+    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth ISO_CODE;
+    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth NARROW;
+    enum_constant public static final android.icu.number.NumberFormatter.UnitWidth SHORT;
+  }
+
+  public abstract class NumberFormatterSettings<T extends android.icu.number.NumberFormatterSettings<?>> {
+    method public T decimal(android.icu.number.NumberFormatter.DecimalSeparatorDisplay);
+    method public T grouping(android.icu.number.NumberFormatter.GroupingStrategy);
+    method public T integerWidth(android.icu.number.IntegerWidth);
+    method public T notation(android.icu.number.Notation);
+    method public T perUnit(android.icu.util.MeasureUnit);
+    method public T precision(android.icu.number.Precision);
+    method public T roundingMode(java.math.RoundingMode);
+    method public T scale(android.icu.number.Scale);
+    method public T sign(android.icu.number.NumberFormatter.SignDisplay);
+    method public T symbols(android.icu.text.DecimalFormatSymbols);
+    method public T symbols(android.icu.text.NumberingSystem);
+    method public T unit(android.icu.util.MeasureUnit);
+    method public T unitWidth(android.icu.number.NumberFormatter.UnitWidth);
+  }
+
+  public abstract class NumberRangeFormatter {
+    method public static android.icu.number.UnlocalizedNumberRangeFormatter with();
+    method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(java.util.Locale);
+    method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(android.icu.util.ULocale);
+  }
+
+  public enum NumberRangeFormatter.RangeCollapse {
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse ALL;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse AUTO;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse NONE;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse UNIT;
+  }
+
+  public enum NumberRangeFormatter.RangeIdentityFallback {
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY_OR_SINGLE_VALUE;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback RANGE;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback SINGLE_VALUE;
+  }
+
+  public enum NumberRangeFormatter.RangeIdentityResult {
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_AFTER_ROUNDING;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_BEFORE_ROUNDING;
+    enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult NOT_EQUAL;
+  }
+
+  public abstract class NumberRangeFormatterSettings<T extends android.icu.number.NumberRangeFormatterSettings<?>> {
+    method public T collapse(android.icu.number.NumberRangeFormatter.RangeCollapse);
+    method public T identityFallback(android.icu.number.NumberRangeFormatter.RangeIdentityFallback);
+    method public T numberFormatterBoth(android.icu.number.UnlocalizedNumberFormatter);
+    method public T numberFormatterFirst(android.icu.number.UnlocalizedNumberFormatter);
+    method public T numberFormatterSecond(android.icu.number.UnlocalizedNumberFormatter);
+  }
+
+  public abstract class Precision implements java.lang.Cloneable {
+    method public Object clone();
+    method public static android.icu.number.CurrencyPrecision currency(android.icu.util.Currency.CurrencyUsage);
+    method public static android.icu.number.FractionPrecision fixedFraction(int);
+    method public static android.icu.number.Precision fixedSignificantDigits(int);
+    method public static android.icu.number.Precision increment(java.math.BigDecimal);
+    method public static android.icu.number.FractionPrecision integer();
+    method public static android.icu.number.FractionPrecision maxFraction(int);
+    method public static android.icu.number.Precision maxSignificantDigits(int);
+    method public static android.icu.number.FractionPrecision minFraction(int);
+    method public static android.icu.number.FractionPrecision minMaxFraction(int, int);
+    method public static android.icu.number.Precision minMaxSignificantDigits(int, int);
+    method public static android.icu.number.Precision minSignificantDigits(int);
+    method public static android.icu.number.Precision unlimited();
+  }
+
+  public class Scale {
+    method public static android.icu.number.Scale byBigDecimal(java.math.BigDecimal);
+    method public static android.icu.number.Scale byDouble(double);
+    method public static android.icu.number.Scale byDoubleAndPowerOfTen(double, int);
+    method public static android.icu.number.Scale none();
+    method public static android.icu.number.Scale powerOfTen(int);
+  }
+
+  public class ScientificNotation extends android.icu.number.Notation implements java.lang.Cloneable {
+    method public Object clone();
+    method public android.icu.number.ScientificNotation withExponentSignDisplay(android.icu.number.NumberFormatter.SignDisplay);
+    method public android.icu.number.ScientificNotation withMinExponentDigits(int);
+  }
+
+  public class SimpleNotation extends android.icu.number.Notation {
+  }
+
+  public class UnlocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.UnlocalizedNumberFormatter> {
+    method public android.icu.number.LocalizedNumberFormatter locale(java.util.Locale);
+    method public android.icu.number.LocalizedNumberFormatter locale(android.icu.util.ULocale);
+  }
+
+  public class UnlocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.UnlocalizedNumberRangeFormatter> {
+    method public android.icu.number.LocalizedNumberRangeFormatter locale(java.util.Locale);
+    method public android.icu.number.LocalizedNumberRangeFormatter locale(android.icu.util.ULocale);
+  }
+
+}
+
 package android.icu.text {
 
   public final class AlphabeticIndex<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Bucket<V>> {
@@ -21893,6 +22085,7 @@
     field public static final android.icu.util.MeasureUnit ARC_MINUTE;
     field public static final android.icu.util.MeasureUnit ARC_SECOND;
     field public static final android.icu.util.MeasureUnit ASTRONOMICAL_UNIT;
+    field public static final android.icu.util.MeasureUnit ATMOSPHERE;
     field public static final android.icu.util.MeasureUnit BIT;
     field public static final android.icu.util.MeasureUnit BUSHEL;
     field public static final android.icu.util.MeasureUnit BYTE;
@@ -21994,6 +22187,9 @@
     field public static final android.icu.util.MeasureUnit OUNCE_TROY;
     field public static final android.icu.util.MeasureUnit PARSEC;
     field public static final android.icu.util.MeasureUnit PART_PER_MILLION;
+    field public static final android.icu.util.MeasureUnit PERCENT;
+    field public static final android.icu.util.MeasureUnit PERMILLE;
+    field public static final android.icu.util.MeasureUnit PETABYTE;
     field public static final android.icu.util.MeasureUnit PICOMETER;
     field public static final android.icu.util.MeasureUnit PINT;
     field public static final android.icu.util.MeasureUnit PINT_METRIC;
@@ -23283,6 +23479,7 @@
     field public static final int ENCODING_IEC61937 = 13; // 0xd
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_MP3 = 9; // 0x9
+    field public static final int ENCODING_OPUS = 20; // 0x14
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
     field public static final int ENCODING_PCM_8BIT = 3; // 0x3
     field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
@@ -28814,14 +29011,25 @@
   }
 
   public final class NetworkCapabilities implements android.os.Parcelable {
+    ctor public NetworkCapabilities();
     ctor public NetworkCapabilities(android.net.NetworkCapabilities);
+    method @NonNull public android.net.NetworkCapabilities addCapability(int);
+    method @NonNull public android.net.NetworkCapabilities addTransportType(int);
+    method public void clearAll();
     method public int describeContents();
     method public int getLinkDownstreamBandwidthKbps();
     method public int getLinkUpstreamBandwidthKbps();
+    method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
     method public int getSignalStrength();
     method @Nullable public android.net.TransportInfo getTransportInfo();
     method public boolean hasCapability(int);
     method public boolean hasTransport(int);
+    method @NonNull public android.net.NetworkCapabilities removeCapability(int);
+    method @NonNull public android.net.NetworkCapabilities setCapability(int, boolean);
+    method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int);
+    method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int);
+    method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier);
+    method @NonNull public android.net.NetworkCapabilities setSignalStrength(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
     field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
@@ -28903,6 +29111,7 @@
 
   public class NetworkRequest implements android.os.Parcelable {
     method public int describeContents();
+    method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
     method public boolean hasCapability(int);
     method public boolean hasTransport(int);
     method public void writeToParcel(android.os.Parcel, int);
@@ -29024,12 +29233,14 @@
     method public static long getMobileRxPackets();
     method public static long getMobileTxBytes();
     method public static long getMobileTxPackets();
+    method public static long getRxPackets(@NonNull String);
     method public static int getThreadStatsTag();
     method public static int getThreadStatsUid();
     method public static long getTotalRxBytes();
     method public static long getTotalRxPackets();
     method public static long getTotalTxBytes();
     method public static long getTotalTxPackets();
+    method public static long getTxPackets(@NonNull String);
     method public static long getUidRxBytes(int);
     method public static long getUidRxPackets(int);
     method @Deprecated public static long getUidTcpRxBytes(int);
@@ -30705,6 +30916,7 @@
     method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
     field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
     field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
+    field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
     field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
     field public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
     field @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) public static final String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED";
@@ -30713,6 +30925,7 @@
     field public static final String EXTRA_DATA = "android.nfc.extra.DATA";
     field public static final String EXTRA_ID = "android.nfc.extra.ID";
     field public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
+    field public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
     field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
     field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
     field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
@@ -30723,6 +30936,9 @@
     field public static final int FLAG_READER_NFC_V = 8; // 0x8
     field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100
     field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80
+    field public static final int PREFERRED_PAYMENT_CHANGED = 2; // 0x2
+    field public static final int PREFERRED_PAYMENT_LOADED = 1; // 0x1
+    field public static final int PREFERRED_PAYMENT_UPDATED = 3; // 0x3
     field public static final int STATE_OFF = 1; // 0x1
     field public static final int STATE_ON = 3; // 0x3
     field public static final int STATE_TURNING_OFF = 4; // 0x4
@@ -30778,8 +30994,11 @@
 
   public final class CardEmulation {
     method public boolean categoryAllowsForegroundPreference(String);
+    method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
     method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
+    method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getDescriptionForPreferredPaymentService();
     method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
+    method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
     method public int getSelectionModeForCategory(String);
     method public boolean isDefaultServiceForAid(android.content.ComponentName, String);
     method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
@@ -35013,11 +35232,12 @@
     method public boolean isIgnoringBatteryOptimizations(String);
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
+    method public boolean isRebootingUserspaceSupported();
     method @Deprecated public boolean isScreenOn();
     method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, String);
-    method public void reboot(String);
+    method public void reboot(@Nullable String);
     method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
     field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
@@ -42355,6 +42575,7 @@
     method public static void execve(String, String[], String[]) throws android.system.ErrnoException;
     method public static void fchmod(java.io.FileDescriptor, int) throws android.system.ErrnoException;
     method public static void fchown(java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
+    method public static int fcntlInt(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
     method public static void fdatasync(java.io.FileDescriptor) throws android.system.ErrnoException;
     method public static android.system.StructStat fstat(java.io.FileDescriptor) throws android.system.ErrnoException;
     method public static android.system.StructStatVfs fstatvfs(java.io.FileDescriptor) throws android.system.ErrnoException;
@@ -42384,6 +42605,7 @@
     method public static String[] listxattr(String) throws android.system.ErrnoException;
     method public static long lseek(java.io.FileDescriptor, long, int) throws android.system.ErrnoException;
     method public static android.system.StructStat lstat(String) throws android.system.ErrnoException;
+    method @NonNull public static java.io.FileDescriptor memfd_create(@NonNull String, int) throws android.system.ErrnoException;
     method public static void mincore(long, long, byte[]) throws android.system.ErrnoException;
     method public static void mkdir(String, int) throws android.system.ErrnoException;
     method public static void mkfifo(String, int) throws android.system.ErrnoException;
@@ -42692,6 +42914,7 @@
     field public static final int MCAST_UNBLOCK_SOURCE;
     field public static final int MCL_CURRENT;
     field public static final int MCL_FUTURE;
+    field public static final int MFD_CLOEXEC;
     field public static final int MSG_CTRUNC;
     field public static final int MSG_DONTROUTE;
     field public static final int MSG_EOR;
@@ -42703,6 +42926,7 @@
     field public static final int MS_INVALIDATE;
     field public static final int MS_SYNC;
     field public static final int NETLINK_INET_DIAG;
+    field public static final int NETLINK_NETFILTER;
     field public static final int NETLINK_ROUTE;
     field public static final int NI_DGRAM;
     field public static final int NI_NAMEREQD;
@@ -43414,6 +43638,7 @@
     field public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final String EVENT_CALL_REMOTELY_HELD = "android.telecom.event.CALL_REMOTELY_HELD";
     field public static final String EVENT_CALL_REMOTELY_UNHELD = "android.telecom.event.CALL_REMOTELY_UNHELD";
+    field public static final String EVENT_CALL_SWITCH_FAILED = "android.telecom.event.CALL_SWITCH_FAILED";
     field public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE";
     field public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START";
     field public static final String EVENT_ON_HOLD_TONE_END = "android.telecom.event.ON_HOLD_TONE_END";
@@ -43871,19 +44096,27 @@
     field @Deprecated public static final String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
     field public static final String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
     field public static final String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED";
+    field public static final String ACTION_POST_CALL = "android.telecom.action.POST_CALL";
     field public static final String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
     field public static final String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
     field public static final String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION";
     field public static final String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
     field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
+    field public static final int DURATION_LONG = 3; // 0x3
+    field public static final int DURATION_MEDIUM = 2; // 0x2
+    field public static final int DURATION_SHORT = 1; // 0x1
+    field public static final int DURATION_VERY_SHORT = 0; // 0x0
     field public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
     field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
     field public static final String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
+    field public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
     field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telecom.extra.CALL_NETWORK_TYPE";
     field public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME";
     field public static final String EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME = "android.telecom.extra.DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME";
+    field public static final String EXTRA_DISCONNECT_CAUSE = "android.telecom.extra.DISCONNECT_CAUSE";
+    field public static final String EXTRA_HANDLE = "android.telecom.extra.HANDLE";
     field public static final String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS";
     field public static final String EXTRA_INCOMING_CALL_EXTRAS = "android.telecom.extra.INCOMING_CALL_EXTRAS";
     field public static final String EXTRA_INCOMING_VIDEO_STATE = "android.telecom.extra.INCOMING_VIDEO_STATE";
@@ -44123,6 +44356,7 @@
     method public void notifyConfigChangedForSubId(int);
     field public static final String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
     field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
+    field public static final int DATA_CYCLE_USE_PLATFORM_DEFAULT = -1; // 0xffffffff
     field public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
     field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
     field public static final String KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrp_thresholds_int_array";
@@ -44133,6 +44367,7 @@
     field public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
     field public static final String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
     field public static final String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool";
+    field public static final String KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL = "allow_holding_video_call";
     field public static final String KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL = "allow_hold_call_during_emergency_bool";
     field public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
     field public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
@@ -44182,17 +44417,23 @@
     field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
     field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
     field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
-    field public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+    field public static final String KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING = "config_ims_mmtel_package_override_string";
+    field @Deprecated public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+    field public static final String KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING = "config_ims_rcs_package_override_string";
     field public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
     field public static final String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
     field public static final String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
+    field public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
     field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
+    field public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL = "data_rapid_notification_bool";
+    field public static final String KEY_DATA_WARNING_NOTIFICATION_BOOL = "data_warning_notification_bool";
     field public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
     field public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final String KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING = "default_vm_number_roaming_and_ims_unregistered_string";
     field public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
     field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
     field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+    field public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL = "disable_supplementary_services_in_airplane_mode_bool";
     field public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY = "disconnect_cause_play_busytone_int_array";
     field public static final String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool";
     field public static final String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool";
@@ -44219,6 +44460,8 @@
     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_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";
     field public static final String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
     field public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
     field public static final String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
@@ -44261,7 +44504,6 @@
     field public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT = "opportunistic_network_entry_threshold_rssnr_int";
     field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int";
     field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int";
-    field public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT = "parameters_use_for_5g_nr_signal_bar_int";
     field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
     field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool";
     field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
@@ -44305,6 +44547,11 @@
     field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
 
+  public static final class CarrierConfigManager.Gps {
+    field public static final String KEY_PERSIST_LPP_MODE_BOOL = "gps.persist_lpp_mode_bool";
+    field public static final String KEY_PREFIX = "gps.";
+  }
+
   public static final class CarrierConfigManager.Ims {
     field public static final String KEY_PREFIX = "ims.";
   }
@@ -44662,6 +44909,12 @@
     field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1
   }
 
+  public final class PhoneCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
+  }
+
   public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
     ctor public PhoneNumberFormattingTextWatcher();
     ctor public PhoneNumberFormattingTextWatcher(String);
@@ -44732,6 +44985,7 @@
     ctor public PhoneStateListener();
     ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
     method public void onActiveDataSubscriptionIdChanged(int);
+    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -44739,12 +44993,15 @@
     method public void onDataActivity(int);
     method public void onDataConnectionStateChanged(int);
     method public void onDataConnectionStateChanged(int, int);
+    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
     method public void onMessageWaitingIndicatorChanged(boolean);
+    method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
     method public void onServiceStateChanged(android.telephony.ServiceState);
     method @Deprecated public void onSignalStrengthChanged(int);
     method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
     method public void onUserMobileDataStateChanged(boolean);
     field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
+    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
     field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
     field public static final int LISTEN_CALL_STATE = 32; // 0x20
     field public static final int LISTEN_CELL_INFO = 1024; // 0x400
@@ -44752,14 +45009,26 @@
     field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
     field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
     field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
+    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
     field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
     field public static final int LISTEN_NONE = 0; // 0x0
+    field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
     field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
     field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
     field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
     field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000
   }
 
+  public final class PreciseDataConnectionState implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getLastCauseCode();
+    method @Nullable public android.net.LinkProperties getLinkProperties();
+    method public int getNetworkType();
+    method public int getState();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR;
+  }
+
   public final class RadioAccessSpecifier implements android.os.Parcelable {
     ctor public RadioAccessSpecifier(int, int[], int[]);
     method public int describeContents();
@@ -44819,6 +45088,7 @@
     method public int getLevel();
     method @Deprecated public boolean isGsm();
     method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalStrength> CREATOR;
     field public static final int INVALID = 2147483647; // 0x7fffffff
   }
 
@@ -44827,7 +45097,7 @@
     method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
     method public java.util.ArrayList<java.lang.String> divideMessage(String);
     method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
-    method public android.os.Bundle getCarrierConfigValues();
+    method @Nullable public android.os.Bundle getCarrierConfigValues();
     method public static android.telephony.SmsManager getDefault();
     method public static int getDefaultSmsSubscriptionId();
     method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
@@ -45131,6 +45401,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 @NonNull public static int[] getAllNetworkTypes();
     method public int getCallState();
     method public int getCardIdForDefaultEuicc();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
@@ -45156,7 +45427,7 @@
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(int);
     method public String getMmsUAProfUrl();
     method public String getMmsUserAgent();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getNai();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNai();
     method public String getNetworkCountryIso();
     method public String getNetworkOperator();
     method public String getNetworkOperatorName();
@@ -45262,6 +45533,7 @@
     field public static final int DATA_CONNECTED = 2; // 0x2
     field public static final int DATA_CONNECTING = 1; // 0x1
     field public static final int DATA_DISCONNECTED = 0; // 0x0
+    field public static final int DATA_DISCONNECTING = 4; // 0x4
     field public static final int DATA_SUSPENDED = 3; // 0x3
     field public static final int DATA_UNKNOWN = -1; // 0xffffffff
     field public static final String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
@@ -45316,6 +45588,8 @@
     field public static final int PHONE_TYPE_NONE = 0; // 0x0
     field public static final int PHONE_TYPE_SIP = 3; // 0x3
     field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
+    field public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3; // 0x3
+    field public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4; // 0x4
     field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
     field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
     field public static final int SIM_STATE_ABSENT = 1; // 0x1
@@ -45332,8 +45606,14 @@
     field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff
     field public static final int UNSUPPORTED_CARD_ID = -1; // 0xffffffff
     field public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2; // 0x2
+    field public static final int UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL = 5; // 0x5
+    field public static final int UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL = 6; // 0x6
     field public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3; // 0x3
+    field public static final int UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED = 7; // 0x7
     field public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4; // 0x4
+    field public static final int UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE = 8; // 0x8
+    field public static final int UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION = 9; // 0x9
+    field public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10; // 0xa
     field public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0; // 0x0
     field public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1; // 0x1
     field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
@@ -45495,6 +45775,7 @@
     field public static final int TYPE_MCX = 1024; // 0x400
     field public static final int TYPE_MMS = 2; // 0x2
     field public static final int TYPE_SUPL = 4; // 0x4
+    field public static final int TYPE_XCAP = 2048; // 0x800
   }
 
   public static class ApnSetting.Builder {
@@ -46064,12 +46345,12 @@
 
 package android.text {
 
-  public class AlteredCharSequence implements java.lang.CharSequence android.text.GetChars {
-    method public char charAt(int);
-    method public void getChars(int, int, char[], int);
-    method public int length();
-    method public static android.text.AlteredCharSequence make(CharSequence, char[], int, int);
-    method public CharSequence subSequence(int, int);
+  @Deprecated public class AlteredCharSequence implements java.lang.CharSequence android.text.GetChars {
+    method @Deprecated public char charAt(int);
+    method @Deprecated public void getChars(int, int, char[], int);
+    method @Deprecated public int length();
+    method @Deprecated public static android.text.AlteredCharSequence make(CharSequence, char[], int, int);
+    method @Deprecated public CharSequence subSequence(int, int);
   }
 
   @Deprecated public class AndroidCharacter {
@@ -46804,7 +47085,7 @@
     field public static final long WEEK_IN_MILLIS = 604800000L; // 0x240c8400L
     field public static final String YEAR_FORMAT = "%Y";
     field public static final String YEAR_FORMAT_TWO_DIGITS = "%g";
-    field public static final long YEAR_IN_MILLIS = 31449600000L; // 0x7528ad000L
+    field @Deprecated public static final long YEAR_IN_MILLIS = 31449600000L; // 0x7528ad000L
     field @Deprecated public static final int[] sameMonthTable;
     field @Deprecated public static final int[] sameYearTable;
   }
@@ -48241,6 +48522,13 @@
     ctor public Base64OutputStream(java.io.OutputStream, int);
   }
 
+  public final class CloseGuard {
+    ctor public CloseGuard();
+    method public void close();
+    method public void open(@NonNull String);
+    method public void warnIfOpen();
+  }
+
   @Deprecated public final class Config {
     field @Deprecated public static final boolean DEBUG = false;
     field @Deprecated public static final boolean LOGD = true;
diff --git a/api/lint-baseline.txt b/api/lint-baseline.txt
index 63c2069..2720498 100644
--- a/api/lint-baseline.txt
+++ b/api/lint-baseline.txt
@@ -507,6 +507,14 @@
     
 MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth) parameter #1:
     
+MissingNullability: android.icu.util.MeasureUnit#ATMOSPHERE:
+    Missing nullability on field `ATMOSPHERE` in class `class android.icu.util.MeasureUnit`
+MissingNullability: android.icu.util.MeasureUnit#PERCENT:
+    Missing nullability on field `PERCENT` in class `class android.icu.util.MeasureUnit`
+MissingNullability: android.icu.util.MeasureUnit#PERMILLE:
+    Missing nullability on field `PERMILLE` in class `class android.icu.util.MeasureUnit`
+MissingNullability: android.icu.util.MeasureUnit#PETABYTE:
+    Missing nullability on field `PETABYTE` in class `class android.icu.util.MeasureUnit`
 MissingNullability: android.icu.util.VersionInfo#UNICODE_12_0:
     
 MissingNullability: android.icu.util.VersionInfo#UNICODE_12_1:
diff --git a/api/system-current.txt b/api/system-current.txt
old mode 100644
new mode 100755
index 299048e..c78f819
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -75,6 +75,7 @@
     field public static final String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
     field public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS";
     field public static final String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
+    field public static final String GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS = "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS";
     field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES";
     field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
     field public static final String HDMI_CEC = "android.permission.HDMI_CEC";
@@ -1161,6 +1162,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method @Nullable public String getDefaultSmsPackage(int);
     method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
@@ -1225,6 +1227,7 @@
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
     method public int getUsageSource();
+    method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
     method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
@@ -1251,8 +1254,30 @@
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothDevice getActiveDevice();
+    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@Nullable android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int getOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothCodecConfig);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice, int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int supportsOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+    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(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isAudioPlaying(@Nullable android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
+    field @RequiresPermission(android.Manifest.permission.BLUETOOTH) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
   }
 
   public final class BluetoothAdapter {
@@ -1281,17 +1306,72 @@
     method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
   }
 
+  public final class BluetoothCodecConfig implements android.os.Parcelable {
+    ctor public BluetoothCodecConfig(int, int, int, int, int, long, long, long, long);
+    ctor public BluetoothCodecConfig(int);
+    method public int getBitsPerSample();
+    method @NonNull public String getCodecName();
+    method public int getCodecPriority();
+    method public long getCodecSpecific1();
+    method public int getCodecType();
+    method public int getSampleRate();
+    method public boolean isMandatoryCodec();
+    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_MAX = 5; // 0x5
+    field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
+  }
+
+  public final class BluetoothCodecStatus implements android.os.Parcelable {
+    ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable android.bluetooth.BluetoothCodecConfig[], @Nullable android.bluetooth.BluetoothCodecConfig[]);
+    method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
+    method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsLocalCapabilities();
+    method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsSelectableCapabilities();
+    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 BluetoothDevice implements android.os.Parcelable {
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean cancelBondProcess();
+    method public boolean cancelPairing();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getBatteryLevel();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getMessageAccessPermission();
     method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getPhonebookAccessPermission();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getSimAccessPermission();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isBondingInitiatedLocally();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isConnected();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isEncrypted();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean removeBond();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setAlias(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMessageAccessPermission(int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPin(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean);
+    method @RequiresPermission(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
@@ -1326,7 +1406,9 @@
   }
 
   public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
+    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public long getHiSyncId(@Nullable android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
   }
 
@@ -1345,6 +1427,11 @@
     field public static final int REMOTE_PANU_ROLE = 2; // 0x2
   }
 
+  public class BluetoothPbap implements android.bluetooth.BluetoothProfile {
+    method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+    field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
+  }
+
   public interface BluetoothProfile {
     field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
     field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
@@ -1466,7 +1553,9 @@
     field public static final String STATS_MANAGER = "stats";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
+    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry";
+    field public static final String TETHERING_SERVICE = "tethering";
     field public static final String VR_SERVICE = "vrmanager";
     field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager";
     field public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
@@ -1486,6 +1575,7 @@
     field public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
     field public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
     field public static final String ACTION_DEVICE_CUSTOMIZATION_READY = "android.intent.action.DEVICE_CUSTOMIZATION_READY";
+    field public static final String ACTION_DIAL_EMERGENCY = "android.intent.action.DIAL_EMERGENCY";
     field public static final String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
     field public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
     field public static final String ACTION_INCIDENT_REPORT_READY = "android.intent.action.INCIDENT_REPORT_READY";
@@ -1534,9 +1624,25 @@
     field public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
     field public static final String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
     field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
+    field @Deprecated public static final String EXTRA_SIM_LOCKED_REASON = "reason";
+    field @Deprecated public static final String EXTRA_SIM_STATE = "ss";
     field public static final String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
     field public static final String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
     field public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
+    field @Deprecated public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
+    field @Deprecated public static final String SIM_LOCKED_NETWORK = "NETWORK";
+    field @Deprecated public static final String SIM_LOCKED_ON_PIN = "PIN";
+    field @Deprecated public static final String SIM_LOCKED_ON_PUK = "PUK";
+    field @Deprecated public static final String SIM_STATE_ABSENT = "ABSENT";
+    field @Deprecated public static final String SIM_STATE_CARD_IO_ERROR = "CARD_IO_ERROR";
+    field @Deprecated public static final String SIM_STATE_CARD_RESTRICTED = "CARD_RESTRICTED";
+    field @Deprecated public static final String SIM_STATE_IMSI = "IMSI";
+    field @Deprecated public static final String SIM_STATE_LOADED = "LOADED";
+    field @Deprecated public static final String SIM_STATE_LOCKED = "LOCKED";
+    field @Deprecated public static final String SIM_STATE_NOT_READY = "NOT_READY";
+    field @Deprecated public static final String SIM_STATE_PRESENT = "PRESENT";
+    field @Deprecated public static final String SIM_STATE_READY = "READY";
+    field @Deprecated public static final String SIM_STATE_UNKNOWN = "UNKNOWN";
   }
 
   public class IntentFilter implements android.os.Parcelable {
@@ -3627,6 +3733,7 @@
     method public android.media.PlayerProxy getPlayerProxy();
     method public int getPlayerState();
     method public int getPlayerType();
+    method public boolean isActive();
     field public static final int PLAYER_STATE_IDLE = 1; // 0x1
     field public static final int PLAYER_STATE_PAUSED = 3; // 0x3
     field public static final int PLAYER_STATE_RELEASED = 0; // 0x0
@@ -3788,10 +3895,22 @@
 package android.media.session {
 
   public final class MediaSessionManager {
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventDispatchedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
     method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
   }
 
+  public static interface MediaSessionManager.OnMediaKeyEventDispatchedListener {
+    method public default void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @NonNull android.media.session.MediaSession.Token);
+  }
+
+  public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
+    method public default void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
+  }
+
   public static interface MediaSessionManager.OnMediaKeyListener {
     method public boolean onMediaKey(android.view.KeyEvent);
   }
@@ -3854,6 +3973,15 @@
 
 package android.media.tv {
 
+  public final class DvbDeviceInfo implements android.os.Parcelable {
+    ctor public DvbDeviceInfo(int, int);
+    method public int describeContents();
+    method public int getAdapterId();
+    method public int getDeviceId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR;
+  }
+
   public final class TvContentRatingSystemInfo implements android.os.Parcelable {
     method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo);
     method public int describeContents();
@@ -3968,12 +4096,14 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
+    method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
     method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
     method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList();
     method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean isSingleSessionActive();
     method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyPreviewProgramAddedToWatchNext(String, long, long);
     method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyPreviewProgramBrowsableDisabled(String, long);
     method @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS) public void notifyWatchNextProgramBrowsableDisabled(String, long);
+    method @Nullable @RequiresPermission("android.permission.DVB_DEVICE") public android.os.ParcelFileDescriptor openDvbDevice(@NonNull android.media.tv.DvbDeviceInfo, int);
     method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public void releaseTvInputHardware(int, android.media.tv.TvInputManager.Hardware);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void removeBlockedRating(@NonNull android.media.tv.TvContentRating);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void setParentalControlsEnabled(boolean);
@@ -3996,6 +4126,7 @@
     method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
     method @Nullable public android.media.tv.TvInputInfo onHdmiDeviceAdded(android.hardware.hdmi.HdmiDeviceInfo);
     method @Nullable public String onHdmiDeviceRemoved(android.hardware.hdmi.HdmiDeviceInfo);
+    method public void onHdmiDeviceUpdated(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
   }
 
   public abstract static class TvInputService.RecordingSession {
@@ -4203,12 +4334,20 @@
     ctor public LinkProperties(@Nullable android.net.LinkProperties);
     method public boolean addDnsServer(@NonNull java.net.InetAddress);
     method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
+    method public boolean addPcscfServer(@NonNull java.net.InetAddress);
+    method @NonNull public java.util.List<java.net.InetAddress> getAddresses();
+    method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
+    method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
+    method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
     method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
     method @Nullable public String getTcpBufferSizes();
     method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
     method public boolean hasGlobalIpv6Address();
     method public boolean hasIpv4Address();
+    method public boolean hasIpv4DefaultRoute();
+    method public boolean hasIpv4DnsServer();
     method public boolean hasIpv6DefaultRoute();
+    method public boolean hasIpv6DnsServer();
     method public boolean isIpv4Provisioned();
     method public boolean isIpv6Provisioned();
     method public boolean isProvisioned();
@@ -4223,6 +4362,13 @@
     method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
   }
 
+  public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+    ctor public MatchAllNetworkSpecifier();
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
+  }
+
   public class Network implements android.os.Parcelable {
     ctor public Network(@NonNull android.net.Network);
     method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
@@ -4232,6 +4378,8 @@
   public final class NetworkCapabilities implements android.os.Parcelable {
     method @NonNull public int[] getTransportTypes();
     method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
+    method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
+    method @NonNull public android.net.NetworkCapabilities setTransportInfo(@NonNull android.net.TransportInfo);
     field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
     field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18
   }
@@ -4347,6 +4495,14 @@
     method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
   }
 
+  public final class StringNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+    ctor public StringNetworkSpecifier(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.StringNetworkSpecifier> CREATOR;
+    field @NonNull public final String specifier;
+  }
+
   public class TrafficStats {
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
@@ -4467,11 +4623,14 @@
     method @NonNull public java.util.List<android.net.LinkAddress> getInternalAddresses();
     method @NonNull public java.util.List<java.net.InetAddress> getInternalDhcpServers();
     method @NonNull public java.util.List<java.net.InetAddress> getInternalDnsServers();
-    method @NonNull public java.util.List<android.net.LinkAddress> getInternalSubnets();
+    method @NonNull public java.util.List<android.net.IpPrefix> getInternalSubnets();
     method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getOutboundTrafficSelectors();
   }
 
   public abstract class ChildSessionParams {
+    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getLocalTrafficSelectors();
+    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getRemoteTrafficSelectors();
+    method @NonNull public java.util.List<android.net.ipsec.ike.ChildSaProposal> getSaProposals();
   }
 
   public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification {
@@ -4533,21 +4692,29 @@
   public final class IkeSessionConfiguration {
     ctor public IkeSessionConfiguration();
     method @NonNull public String getRemoteApplicationVersion();
+    method @NonNull public java.util.List<byte[]> getRemoteVendorIDs();
     method public boolean isIkeExtensionEnabled(int);
     field public static final int EXTENSION_TYPE_FRAGMENTATION = 1; // 0x1
     field public static final int EXTENSION_TYPE_MOBIKE = 2; // 0x2
   }
 
   public final class IkeSessionParams {
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig();
+    method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification();
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getRemoteAuthConfig();
+    method @NonNull public android.net.ipsec.ike.IkeIdentification getRemoteIdentification();
+    method @NonNull public java.util.List<android.net.ipsec.ike.IkeSaProposal> getSaProposals();
+    method @NonNull public java.net.InetAddress getServerAddress();
+    method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket getUdpEncapsulationSocket();
   }
 
   public static final class IkeSessionParams.Builder {
     ctor public IkeSessionParams.Builder();
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal);
     method @NonNull public android.net.ipsec.ike.IkeSessionParams build();
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthEap(@NonNull java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey);
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey);
+    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthEap(@Nullable java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthPsk(@NonNull byte[]);
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
@@ -4555,6 +4722,27 @@
     method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket);
   }
 
+  public abstract static class IkeSessionParams.IkeAuthConfig {
+  }
+
+  public static class IkeSessionParams.IkeAuthDigitalSignLocalConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+    method @NonNull public java.security.cert.X509Certificate getClientEndCertificate();
+    method @NonNull public java.util.List<java.security.cert.X509Certificate> getIntermediateCertificates();
+    method @NonNull public java.security.PrivateKey getPrivateKey();
+  }
+
+  public static class IkeSessionParams.IkeAuthDigitalSignRemoteConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+    method @Nullable public java.security.cert.X509Certificate getRemoteCaCert();
+  }
+
+  public static class IkeSessionParams.IkeAuthEapConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+    method @NonNull public android.net.eap.EapSessionConfig getEapConfig();
+  }
+
+  public static class IkeSessionParams.IkeAuthPskConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
+    method @NonNull public byte[] getPsk();
+  }
+
   public final class IkeTrafficSelector {
     ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
     field public final int endPort;
@@ -4601,23 +4789,49 @@
   }
 
   public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams {
+    method @NonNull public java.util.List<android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest> getConfigurationRequests();
   }
 
   public static final class TunnelModeChildSessionParams.Builder {
     ctor public TunnelModeChildSessionParams.Builder();
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.InetAddress, int);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.Inet4Address);
+    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.Inet6Address, int);
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDhcpServerRequest(int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDhcpServerRequest(@NonNull java.net.InetAddress);
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDnsServerRequest(int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDnsServerRequest(@NonNull java.net.InetAddress);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalSubnetRequest(int);
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
     method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams build();
   }
 
+  public static interface TunnelModeChildSessionParams.ConfigRequest {
+  }
+
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+    method @Nullable public java.net.Inet4Address getAddress();
+  }
+
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+    method @Nullable public java.net.Inet4Address getAddress();
+  }
+
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+    method @Nullable public java.net.Inet4Address getAddress();
+  }
+
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Netmask extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+  }
+
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+    method @Nullable public java.net.Inet6Address getAddress();
+    method public int getPrefixLength();
+  }
+
+  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequest {
+    method @Nullable public java.net.Inet6Address getAddress();
+  }
+
 }
 
 package android.net.ipsec.ike.exceptions {
@@ -5812,6 +6026,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
     field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
     field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
+    field public static final String REBOOT_USERSPACE = "userspace";
     field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
@@ -6019,6 +6234,14 @@
 
 }
 
+package android.os.ext {
+
+  public class SdkExtensions {
+    method public static int getExtensionVersion(int);
+  }
+
+}
+
 package android.os.image {
 
   public class DynamicSystemClient {
@@ -6452,6 +6675,7 @@
     field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
     field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
     field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
+    field public static final String TETHER_SUPPORTED = "tether_supported";
     field public static final String THEATER_MODE_ON = "theater_mode_on";
     field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
     field public static final String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
@@ -6523,7 +6747,9 @@
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
     field public static final String APN_SET_ID = "apn_set_id";
     field public static final int CARRIER_EDITED = 4; // 0x4
+    field @NonNull public static final android.net.Uri DPC_URI;
     field public static final String EDITED_STATUS = "edited";
+    field public static final int INVALID_APN_ID = -1; // 0xffffffff
     field public static final String MAX_CONNECTIONS = "max_conns";
     field public static final String MODEM_PERSIST = "modem_cognitive";
     field public static final String MTU = "mtu";
@@ -6568,6 +6794,10 @@
     field public static final String SUB_ID = "sub_id";
   }
 
+  public static final class Telephony.SimInfo {
+    field @NonNull public static final android.net.Uri CONTENT_URI;
+  }
+
   public static final class Telephony.Sms.Intents {
     field public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = "android.provider.action.SMS_EMERGENCY_CB_RECEIVED";
   }
@@ -7645,6 +7875,7 @@
     method public void addNewUnknownCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method @Deprecated public void clearAccounts();
     method public void clearPhoneAccounts();
+    method @NonNull public android.content.Intent createLaunchEmergencyDialerIntent(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.DUMP) public android.telecom.TelecomAnalytics dumpAnalytics();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
     method public java.util.List<android.telecom.PhoneAccountHandle> getAllPhoneAccountHandles();
@@ -7716,6 +7947,7 @@
   }
 
   public class CarrierConfigManager {
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
     method @NonNull public static android.os.PersistableBundle getDefaultConfig();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String);
@@ -7751,6 +7983,13 @@
   public class CbGeoUtils {
   }
 
+  public static class CbGeoUtils.Circle implements android.telephony.CbGeoUtils.Geometry {
+    ctor public CbGeoUtils.Circle(@NonNull android.telephony.CbGeoUtils.LatLng, double);
+    method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+    method @NonNull public android.telephony.CbGeoUtils.LatLng getCenter();
+    method public double getRadius();
+  }
+
   public static interface CbGeoUtils.Geometry {
     method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
   }
@@ -7763,6 +8002,16 @@
     field public final double lng;
   }
 
+  public static class CbGeoUtils.Polygon implements android.telephony.CbGeoUtils.Geometry {
+    ctor public CbGeoUtils.Polygon(@NonNull java.util.List<android.telephony.CbGeoUtils.LatLng>);
+    method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+    method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices();
+  }
+
+  public class CellBroadcastIntents {
+    method public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
+  }
+
   public abstract class CellBroadcastService extends android.app.Service {
     ctor public CellBroadcastService();
     method @CallSuper @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent);
@@ -8089,6 +8338,7 @@
     field public static final int UE_SECURITY_CAPABILITIES_MISMATCH = 2185; // 0x889
     field public static final int UMTS_HANDOVER_TO_IWLAN = 2199; // 0x897
     field public static final int UMTS_REACTIVATION_REQ = 39; // 0x27
+    field public static final int UNACCEPTABLE_NETWORK_PARAMETER = 65538; // 0x10002
     field public static final int UNACCEPTABLE_NON_EPS_AUTHENTICATION = 2187; // 0x88b
     field public static final int UNKNOWN = 65536; // 0x10000
     field public static final int UNKNOWN_INFO_ELEMENT = 99; // 0x63
@@ -8233,6 +8483,24 @@
     field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
   }
 
+  public final class ModemActivityInfo implements android.os.Parcelable {
+    ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
+    method public int describeContents();
+    method public int getIdleTimeMillis();
+    method public int getReceiveTimeMillis();
+    method public int getSleepTimeMillis();
+    method public long getTimestamp();
+    method @NonNull public java.util.List<android.telephony.ModemActivityInfo.TransmitPower> getTransmitPowerInfo();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+    field public static final int TX_POWER_LEVELS = 5; // 0x5
+  }
+
+  public class ModemActivityInfo.TransmitPower {
+    method @NonNull public android.util.Range<java.lang.Integer> getPowerRangeInDbm();
+    method public int getTimeInMillis();
+  }
+
   public final class NetworkRegistrationInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getAccessNetworkTechnology();
@@ -8331,28 +8599,23 @@
 
   public class PhoneStateListener {
     method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
-    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
-    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
     method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
     method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
     method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
-    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
     method public void onRadioPowerStateChanged(int);
     method public void onSrvccStateChanged(int);
     method public void onVoiceActivationStateChanged(int);
     field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
     field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
     field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
     field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
     field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
     field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
   }
 
   public final class PreciseCallState implements android.os.Parcelable {
+    ctor public PreciseCallState(int, int, int, int, int);
     method public int describeContents();
     method public int getBackgroundCallState();
     method public int getForegroundCallState();
@@ -8372,13 +8635,12 @@
   }
 
   public final class PreciseDataConnectionState implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public String getDataConnectionApn();
-    method public int getDataConnectionApnTypeBitMask();
-    method public int getDataConnectionFailCause();
-    method public int getDataConnectionState();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR;
+    method @Deprecated @NonNull public String getDataConnectionApn();
+    method @Deprecated public int getDataConnectionApnTypeBitMask();
+    method @Deprecated public int getDataConnectionFailCause();
+    method @Deprecated @Nullable public android.net.LinkProperties getDataConnectionLinkProperties();
+    method @Deprecated public int getDataConnectionNetworkType();
+    method @Deprecated public int getDataConnectionState();
   }
 
   public final class PreciseDisconnectCause {
@@ -8583,6 +8845,7 @@
     method @NonNull public android.content.ContentValues getContentValues();
     method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo();
     method public int getGeographicalScope();
+    method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries();
     method @Nullable public String getLanguageCode();
     method @NonNull public android.telephony.SmsCbLocation getLocation();
     method public int getMaximumWaitingDuration();
@@ -8616,11 +8879,13 @@
   public final class SmsManager {
     method public boolean disableCellBroadcastRange(int, int, int);
     method public boolean enableCellBroadcastRange(int, int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
     method public void sendMultipartTextMessage(@NonNull String, @NonNull String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
   }
 
   public class SubscriptionInfo implements android.os.Parcelable {
+    method public boolean areUiccApplicationsEnabled();
     method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
     method public int getProfileClass();
     method public boolean isGroupDisabled();
@@ -8639,6 +8904,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
+    field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
     field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
     field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
     field public static final int PROFILE_CLASS_OPERATIONAL = 2; // 0x2
@@ -8679,10 +8945,8 @@
   }
 
   public class TelephonyManager {
+    method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void carrierActionReportDefaultNetworkStatus(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void carrierActionResetAll(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void carrierActionSetRadioEnabled(int, boolean);
     method public int checkCarrierPrivilegesForPackage(String);
     method public int checkCarrierPrivilegesForPackageAnyPhone(String);
     method public void dial(String);
@@ -8695,6 +8959,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
@@ -8707,6 +8972,7 @@
     method @Deprecated public boolean getDataEnabled();
     method @Deprecated public boolean getDataEnabled(int);
     method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+    method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method public int getEmergencyNumberDbVersion();
@@ -8715,7 +8981,7 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
     method public int getMaxNumberOfSimultaneouslyActiveSims();
     method public static long getMaxNumberVerificationTimeoutMillis();
-    method @NonNull public String getNetworkCountryIso(int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getNetworkCountryIso(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
@@ -8734,6 +9000,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
     method public boolean isDataConnectivityPossible();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
@@ -8749,11 +9016,14 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetheringApnRequired();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+    method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
     method public boolean needsOtaServiceProvisioning();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
     method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
@@ -8767,11 +9037,13 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
     method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
@@ -8781,6 +9053,8 @@
     method public void updateServiceLocation();
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
+    field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
+    field public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
     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";
@@ -9375,6 +9649,11 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
   }
 
+  public class ImsManager {
+    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
+    method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+  }
+
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
     method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
@@ -9418,6 +9697,22 @@
     ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
   }
 
+  public class ImsRcsManager implements android.telephony.ims.RegistrationManager {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerRcsAvailabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsRcsManager.AvailabilityCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterRcsAvailabilityCallback(@NonNull android.telephony.ims.ImsRcsManager.AvailabilityCallback) throws android.telephony.ims.ImsException;
+  }
+
+  public static class ImsRcsManager.AvailabilityCallback {
+    ctor public ImsRcsManager.AvailabilityCallback();
+    method public void onAvailabilityChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
+  }
+
   public final class ImsReasonInfo implements android.os.Parcelable {
     field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
   }
@@ -9779,9 +10074,22 @@
 
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public RcsFeature();
-    method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
+    method public boolean queryCapabilityConfiguration(int, int);
+    method @NonNull public final android.telephony.ims.feature.RcsFeature.RcsImsCapabilities queryCapabilityStatus();
+  }
+
+  public static class RcsFeature.RcsImsCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
+    ctor public RcsFeature.RcsImsCapabilities(int);
+    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
   }
 
 }
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index c64e3d8..432a5fd 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -144,6 +144,16 @@
 ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
     
 
+PublicTypedef: android.content.integrity.AtomicFormula.Key: Don't expose @IntDef: @Key must be hidden.
+
+PublicTypedef: android.content.integrity.AtomicFormula.Operator: Don't expose @IntDef: @Operator must be hidden.
+
+PublicTypedef: android.content.integrity.CompoundFormula.Connector: Don't expose @IntDef: @Connector must be hidden.
+
+PublicTypedef: android.content.integrity.Formula.Tag: Don't expose @IntDef: @Tag must be hidden.
+
+PublicTypedef: android.content.integrity.Rule.Effect: Don't expose @IntDef: @Effect must be hidden.
+
 
 SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
     
diff --git a/api/test-current.txt b/api/test-current.txt
index c29ef99..80f7e4b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -653,6 +653,7 @@
     field public static final String PERMISSION_SERVICE = "permission";
     field public static final String ROLLBACK_SERVICE = "rollback";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
+    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
 
@@ -3003,6 +3004,10 @@
     field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
   }
 
+  public final class PreciseDataConnectionState implements android.os.Parcelable {
+    ctor @Deprecated public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int);
+  }
+
   public class ServiceState implements android.os.Parcelable {
     method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo);
     method public void setCdmaSystemAndNetworkId(int, int);
@@ -3035,14 +3040,17 @@
   }
 
   public class TelephonyManager {
+    method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
     method public int checkCarrierPrivilegesForPackage(String);
     method public int getCarrierIdListVersion();
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+    method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
     method public int getEmergencyNumberDbVersion();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
-    method @NonNull public String getNetworkCountryIso(int);
+    method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
     method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
+    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);
     method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
@@ -3269,6 +3277,11 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
   }
 
+  public class ImsManager {
+    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
+    method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+  }
+
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
     method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
@@ -3312,6 +3325,22 @@
     ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
   }
 
+  public class ImsRcsManager implements android.telephony.ims.RegistrationManager {
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(int) throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(int, int) throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerRcsAvailabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsRcsManager.AvailabilityCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterRcsAvailabilityCallback(@NonNull android.telephony.ims.ImsRcsManager.AvailabilityCallback) throws android.telephony.ims.ImsException;
+  }
+
+  public static class ImsRcsManager.AvailabilityCallback {
+    ctor public ImsRcsManager.AvailabilityCallback();
+    method public void onAvailabilityChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
+  }
+
   public class ImsService extends android.app.Service {
     ctor public ImsService();
     method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
@@ -3669,9 +3698,22 @@
 
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public RcsFeature();
-    method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
+    method public boolean queryCapabilityConfiguration(int, int);
+    method @NonNull public final android.telephony.ims.feature.RcsFeature.RcsImsCapabilities queryCapabilityStatus();
+  }
+
+  public static class RcsFeature.RcsImsCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
+    ctor public RcsFeature.RcsImsCapabilities(int);
+    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
   }
 
 }
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index bf21ce7..3af392c 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -2444,6 +2444,12 @@
 ProtectedMember: android.view.ViewGroup#resetResolvedDrawables():
     
 
+PublicTypedef: android.os.HwParcel.Status: Don't expose @IntDef: @Status must be hidden.
+
+PublicTypedef: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability: Don't expose @IntDef: @MmTelCapability must be hidden.
+
+PublicTypedef: android.telephony.ims.feature.MmTelFeature.ProcessCallResult: Don't expose @IntDef: @ProcessCallResult must be hidden.
+
 
 RawAidl: android.telephony.mbms.vendor.MbmsDownloadServiceBase:
     
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp
index 6c3d197..eb2b98a 100644
--- a/cmds/incident/main.cpp
+++ b/cmds/incident/main.cpp
@@ -375,7 +375,7 @@
     if (destination == DEST_STDOUT) {
         // Call into the service
         sp<StatusListener> listener(new StatusListener());
-        status = service->reportIncidentToStream(args, listener, writeEnd);
+        status = service->reportIncidentToStream(args, listener, std::move(writeEnd));
 
         if (!status.isOk()) {
             fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string());
@@ -388,7 +388,7 @@
     } else if (destination == DEST_DUMPSTATE) {
         // Call into the service
         sp<StatusListener> listener(new StatusListener());
-        status = service->reportIncidentToDumpstate(writeEnd, listener);
+        status = service->reportIncidentToDumpstate(std::move(writeEnd), listener);
         if (!status.isOk()) {
             fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string());
             return 1;
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 999936b..cfd77c2 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -279,7 +279,7 @@
 
 Status IncidentService::reportIncidentToStream(const IncidentReportArgs& args,
                                                const sp<IIncidentReportStatusListener>& listener,
-                                               const unique_fd& stream) {
+                                               unique_fd stream) {
     IncidentReportArgs argsCopy(args);
 
     // Streaming reports can not also be broadcast.
@@ -306,7 +306,7 @@
     return Status::ok();
 }
 
-Status IncidentService::reportIncidentToDumpstate(const unique_fd& stream,
+Status IncidentService::reportIncidentToDumpstate(unique_fd stream,
         const sp<IIncidentReportStatusListener>& listener) {
     uid_t caller = IPCThreadState::self()->getCallingUid();
     if (caller != AID_ROOT && caller != AID_SHELL) {
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index fb013d0..b2c7f23 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -121,9 +121,9 @@
 
     virtual Status reportIncidentToStream(const IncidentReportArgs& args,
                                           const sp<IIncidentReportStatusListener>& listener,
-                                          const unique_fd& stream);
+                                          unique_fd stream);
 
-    virtual Status reportIncidentToDumpstate(const unique_fd& stream,
+    virtual Status reportIncidentToDumpstate(unique_fd stream,
             const sp<IIncidentReportStatusListener>& listener);
 
     virtual Status systemRunning();
diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp
index 7e7c642..9963533 100644
--- a/cmds/incidentd/src/WorkDirectory.cpp
+++ b/cmds/incidentd/src/WorkDirectory.cpp
@@ -666,7 +666,7 @@
         clock_gettime(CLOCK_REALTIME, &spec);
         timestampNs = int64_t(spec.tv_sec) * 1000 + spec.tv_nsec;
     } while (file_exists_locked(timestampNs));
-    return timestampNs;
+    return (timestampNs >= 0)? timestampNs : -timestampNs;
 }
 
 /**
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4440bf8..c923156 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3957,7 +3957,7 @@
     // rx time in ms at power level 5
     optional uint64 controller_rx_time_millis = 9;
     // product of current(mA), voltage(V) and time(ms)
-    optional uint64 energy_used = 10;
+    optional uint64 energy_used = 10 [deprecated=true];
 }
 
 /**
diff --git a/cmds/svc/src/com/android/commands/svc/DataCommand.java b/cmds/svc/src/com/android/commands/svc/DataCommand.java
deleted file mode 100644
index 35510cf..0000000
--- a/cmds/svc/src/com/android/commands/svc/DataCommand.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.commands.svc;
-
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.content.Context;
-import com.android.internal.telephony.ITelephony;
-
-public class DataCommand extends Svc.Command {
-    public DataCommand() {
-        super("data");
-    }
-
-    public String shortHelp() {
-        return "Control mobile data connectivity";
-    }
-
-    public String longHelp() {
-        return shortHelp() + "\n"
-                + "\n"
-                + "usage: svc data [enable|disable]\n"
-                + "         Turn mobile data on or off.\n\n";
-    }
-
-    public void run(String[] args) {
-        boolean validCommand = false;
-        if (args.length >= 2) {
-            boolean flag = false;
-            if ("enable".equals(args[1])) {
-                flag = true;
-                validCommand = true;
-            } else if ("disable".equals(args[1])) {
-                flag = false;
-                validCommand = true;
-            }
-            if (validCommand) {
-                ITelephony phoneMgr
-                        = ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
-                try {
-                    if (flag) {
-                        phoneMgr.enableDataConnectivity();
-                    } else
-                        phoneMgr.disableDataConnectivity();
-                }
-                catch (RemoteException e) {
-                    System.err.println("Mobile data operation failed: " + e);
-                }
-                return;
-            }
-        }
-        System.err.println(longHelp());
-    }
-}
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index 68fb8e6..de6e885 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -93,7 +93,6 @@
     public static final Command[] COMMANDS = new Command[] {
             COMMAND_HELP,
             new PowerCommand(),
-            new DataCommand(),
             new WifiCommand(),
             new UsbCommand(),
             new NfcCommand(),
diff --git a/cmds/svc/svc b/cmds/svc/svc
index c122e98..7431aea 100755
--- a/cmds/svc/svc
+++ b/cmds/svc/svc
@@ -1,3 +1,18 @@
 #!/system/bin/sh
+
+if [ "x$1" == "xdata" ]; then
+    if [ "x$2" == "xenable" ]; then
+        exec cmd phone data enable
+    elif [ "x$2" == "xdisable" ]; then
+        exec cmd phone data disable
+    else
+        echo "Enable/Disable Mobile Data Connectivity"
+        echo ""
+        echo "usage: svc data [enable|disable]"
+        echo ""
+    fi
+    exit 1
+fi
+
 export CLASSPATH=/system/framework/svc.jar
 exec app_process /system/bin com.android.commands.svc.Svc "$@"
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 5ffe2f2..1987440 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -16,15 +16,17 @@
 
 package com.android.commands.telecom;
 
+import android.app.ActivityThread;
 import android.content.ComponentName;
 import android.content.Context;
 import android.net.Uri;
 import android.os.IUserManager;
+import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.sysprop.TelephonyProperties;
 import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -33,8 +35,6 @@
 
 import com.android.internal.os.BaseCommand;
 import com.android.internal.telecom.ITelecomService;
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.TelephonyProperties;
 
 import java.io.PrintStream;
 
@@ -83,7 +83,7 @@
     private ComponentName mComponent;
     private String mAccountId;
     private ITelecomService mTelecomService;
-    private ITelephony mTelephonyService;
+    private TelephonyManager mTelephonyManager;
     private IUserManager mUserManager;
 
     @Override
@@ -154,9 +154,10 @@
             return;
         }
 
-        mTelephonyService = ITelephony.Stub.asInterface(
-                ServiceManager.getService(Context.TELEPHONY_SERVICE));
-        if (mTelephonyService == null) {
+        Looper.prepareMainLooper();
+        Context context = ActivityThread.systemMain().getSystemContext();
+        mTelephonyManager = context.getSystemService(TelephonyManager.class);
+        if (mTelephonyManager == null) {
             Log.w(this, "onRun: Can't access telephony service.");
             showError("Error: Could not access the Telephony Service. Is the system running?");
             return;
@@ -352,7 +353,7 @@
         }
         int numSims = Integer.parseInt(nextArgRequired());
         System.out.println("Setting sim count to " + numSims + ". Device may reboot");
-        mTelephonyService.switchMultiSimConfig(numSims);
+        mTelephonyManager.switchMultiSimConfig(numSims);
     }
 
     /**
@@ -361,13 +362,12 @@
      * "" (empty string) for a phone in SS mode
      */
     private void runGetSimConfig() throws RemoteException {
-        System.out.println(SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG));
+        System.out.println(TelephonyProperties.multi_sim_config().orElse(""));
     }
 
     private void runGetMaxPhones() throws RemoteException {
         // This assumes the max number of SIMs is 2, which it currently is
-        if (TelephonyManager.MULTISIM_ALLOWED
-                == mTelephonyService.isMultiSimSupported("com.android.commands.telecom")) {
+        if (TelephonyManager.MULTISIM_ALLOWED == mTelephonyManager.isMultiSimSupported()) {
             System.out.println("2");
         } else {
             System.out.println("1");
diff --git a/cmds/uiautomator/library/Android.bp b/cmds/uiautomator/library/Android.bp
index 1173d57..3a26063 100644
--- a/cmds/uiautomator/library/Android.bp
+++ b/cmds/uiautomator/library/Android.bp
@@ -22,6 +22,7 @@
         "android.test.runner",
         "junit",
         "android.test.base",
+        "unsupportedappusage",
     ],
     custom_template: "droiddoc-templates-sdk",
     installable: false,
diff --git a/core/java/android/annotation/Hide.java b/core/java/android/annotation/Hide.java
new file mode 100644
index 0000000..c8e5a4a
--- /dev/null
+++ b/core/java/android/annotation/Hide.java
@@ -0,0 +1,41 @@
+/*
+ * 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.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PACKAGE;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that an API is hidden by default, in a similar fashion to the
+ * <pre>@hide</pre> javadoc tag.
+ *
+ * <p>Note that, in order for this to work, metalava has to be invoked with
+ * the flag {@code --hide-annotation android.annotation.Hide}.
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
+@Retention(RetentionPolicy.CLASS)
+public @interface Hide {
+}
diff --git a/core/java/android/annotation/OWNERS b/core/java/android/annotation/OWNERS
index e07028b..8aceb56 100644
--- a/core/java/android/annotation/OWNERS
+++ b/core/java/android/annotation/OWNERS
@@ -1,2 +1,3 @@
 tnorbye@google.com
+aurimas@google.com
 per-file UnsupportedAppUsage.java = mathewi@google.com, dbrazdil@google.com, atrost@google.com, andreionea@google.com
diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java
index 59d419f..e5c0654 100644
--- a/core/java/android/annotation/RequiresPermission.java
+++ b/core/java/android/annotation/RequiresPermission.java
@@ -15,8 +15,6 @@
  */
 package android.annotation;
 
-import android.content.Intent;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
@@ -57,7 +55,7 @@
  * <p>
  * When specified on a parameter, the annotation indicates that the method requires
  * a permission which depends on the value of the parameter. For example, consider
- * {@link android.app.Activity#startActivity(Intent)}:
+ * {@link android.app.Activity#startActivity(android.content.Intent)}:
  * <pre>{@code
  *   public void startActivity(@RequiresPermission Intent intent) { ... }
  * }</pre>
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index e96ff01..2cb93e4 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -41,4 +41,49 @@
 @Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface SystemApi {
+    enum Client {
+        /**
+         * Specifies that the intended clients of a SystemApi are privileged apps.
+         * This is the default value for {@link #client}. This implies
+         * MODULE_APPS and MODULE_LIBRARIES as well, which means that APIs will also
+         * be available to module apps and jars.
+         */
+        PRIVILEGED_APPS,
+
+        /**
+         * Specifies that the intended clients of a SystemApi are modules implemented
+         * as apps, like the NetworkStack app. This implies MODULE_LIBRARIES as well,
+         * which means that APIs will also be available to module jars.
+         */
+        MODULE_APPS,
+
+        /**
+         * Specifies that the intended clients of a SystemApi are modules implemented
+         * as libraries, like the conscrypt.jar in the conscrypt APEX.
+         */
+        MODULE_LIBRARIES
+    }
+
+    enum Process {
+        /**
+         * Specifies that the SystemAPI is available in every Java processes.
+         * This is the default value for {@link #process}.
+         */
+        ALL,
+
+        /**
+         * Specifies that the SystemAPI is available only in the system server process.
+         */
+        SYSTEM_SERVER
+    }
+
+    /**
+     * The intended client of this SystemAPI.
+     */
+    Client client() default android.annotation.SystemApi.Client.PRIVILEGED_APPS;
+
+    /**
+     * The process(es) that this SystemAPI is available
+     */
+    Process process() default android.annotation.SystemApi.Process.ALL;
 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index f0b3546..4efaaad 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -46,7 +46,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.sysprop.ProductProperties;
+import android.sysprop.VndkProperties;
 import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
@@ -785,13 +785,12 @@
         // Similar to vendor apks, we should add /product/lib for apks from product partition
         // when product apps are marked as unbundled. We cannot use the same way from vendor
         // to check if lib path exists because there is possibility that /product/lib would not
-        // exist from legacy device while product apks are bundled. To make this clear, new
-        // property ("ro.product.apps.unbundled") is defined which should be true only when
-        // product apks are unbundled.
+        // exist from legacy device while product apks are bundled. To make this clear, we use
+        // "ro.product.vndk.version" property. If the property is defined, we regard all product
+        // apks as unbundled.
         if (mApplicationInfo.getCodePath() != null
-                && mApplicationInfo.isProduct() && ProductProperties.unbundled_apps().orElse(false)
-                // TODO(b/128557860): Change target SDK version when version code R is available.
-                && getTargetSdkVersion() == Build.VERSION_CODES.CUR_DEVELOPMENT) {
+                && mApplicationInfo.isProduct()
+                && VndkProperties.product_vndk_version().isPresent()) {
             isBundledApp = false;
         }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d8ccc62..82df702 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -111,6 +111,7 @@
 import android.net.NetworkScoreManager;
 import android.net.NetworkWatchlistManager;
 import android.net.TestNetworkManager;
+import android.net.TetheringManager;
 import android.net.lowpan.ILowpanManager;
 import android.net.lowpan.LowpanManager;
 import android.net.nsd.INsdManager;
@@ -340,6 +341,17 @@
             }
         });
 
+        registerService(Context.TETHERING_SERVICE, TetheringManager.class,
+                new CachedServiceFetcher<TetheringManager>() {
+            @Override
+            public TetheringManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getService(Context.TETHERING_SERVICE);
+                if (b == null) return null;
+
+                return new TetheringManager(ctx, b);
+            }});
+
+
         registerService(Context.IPSEC_SERVICE, IpSecManager.class,
                 new CachedServiceFetcher<IpSecManager>() {
             @Override
@@ -1245,6 +1257,14 @@
                         return new TimeZoneDetector();
                     }});
 
+        registerService(Context.TELEPHONY_IMS_SERVICE, android.telephony.ims.ImsManager.class,
+                new CachedServiceFetcher<android.telephony.ims.ImsManager>() {
+                    @Override
+                    public android.telephony.ims.ImsManager createService(ContextImpl ctx) {
+                        return new android.telephony.ims.ImsManager(ctx.getOuterContext());
+                    }
+                });
+
         registerService(Context.PERMISSION_SERVICE, PermissionManager.class,
                 new CachedServiceFetcher<PermissionManager>() {
                     @Override
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index d8cea28..6d790b3 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -19,7 +19,6 @@
 import android.app.role.IOnRoleHoldersChangedListener;
 import android.os.Bundle;
 import android.os.RemoteCallback;
-import android.telephony.IFinancialSmsCallback;
 
 /**
  * @hide
@@ -55,9 +54,4 @@
     List<String> getHeldRolesFromController(in String packageName);
 
     String getDefaultSmsPackage(int userId);
-
-    /**
-     * Get filtered SMS messages for financial app.
-     */
-    void getSmsMessagesForFinancialApp(in String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
 }
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index bb04a2e..b9cda6c 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -629,9 +629,12 @@
      * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as required by
      * {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}
      *
+     * @param userId The user ID to get the default SMS package for.
+     * @return the package name of the default SMS app, or {@code null} if not configured.
      * @hide
      */
     @Nullable
+    @SystemApi
     public String getDefaultSmsPackage(@UserIdInt int userId) {
         try {
             return mService.getDefaultSmsPackage(userId);
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index e7d619a..55f92be 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -56,6 +56,7 @@
 
     public ManualTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
         mUtcTime = Objects.requireNonNull(utcTime);
+        Objects.requireNonNull(utcTime.getValue());
     }
 
     private static ManualTimeSuggestion createFromParcel(Parcel in) {
@@ -85,7 +86,8 @@
 
     @NonNull
     public List<String> getDebugInfo() {
-        return Collections.unmodifiableList(mDebugInfo);
+        return mDebugInfo == null
+                ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
     }
 
     /**
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index 233dbbc..4a89a12 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -23,7 +23,6 @@
 import android.util.TimestampedValue;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -52,20 +51,25 @@
             };
 
     private final int mPhoneId;
-    @Nullable private TimestampedValue<Long> mUtcTime;
+    @Nullable private final TimestampedValue<Long> mUtcTime;
     @Nullable private ArrayList<String> mDebugInfo;
 
-    public PhoneTimeSuggestion(int phoneId) {
-        mPhoneId = phoneId;
+    private PhoneTimeSuggestion(Builder builder) {
+        mPhoneId = builder.mPhoneId;
+        mUtcTime = builder.mUtcTime;
+        mDebugInfo = builder.mDebugInfo != null ? new ArrayList<>(builder.mDebugInfo) : null;
     }
 
     private static PhoneTimeSuggestion createFromParcel(Parcel in) {
         int phoneId = in.readInt();
-        PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId);
-        suggestion.setUtcTime(in.readParcelable(null /* classLoader */));
+        PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion.Builder(phoneId)
+                .setUtcTime(in.readParcelable(null /* classLoader */))
+                .build();
         @SuppressWarnings("unchecked")
         ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
-        suggestion.mDebugInfo = debugInfo;
+        if (debugInfo != null) {
+            suggestion.addDebugInfo(debugInfo);
+        }
         return suggestion;
     }
 
@@ -85,10 +89,6 @@
         return mPhoneId;
     }
 
-    public void setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
-        mUtcTime = utcTime;
-    }
-
     @Nullable
     public TimestampedValue<Long> getUtcTime() {
         return mUtcTime;
@@ -96,7 +96,8 @@
 
     @NonNull
     public List<String> getDebugInfo() {
-        return Collections.unmodifiableList(mDebugInfo);
+        return mDebugInfo == null
+                ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
     }
 
     /**
@@ -104,11 +105,23 @@
      * information is present in {@link #toString()} but is not considered for
      * {@link #equals(Object)} and {@link #hashCode()}.
      */
-    public void addDebugInfo(String... debugInfos) {
+    public void addDebugInfo(String debugInfo) {
         if (mDebugInfo == null) {
             mDebugInfo = new ArrayList<>();
         }
-        mDebugInfo.addAll(Arrays.asList(debugInfos));
+        mDebugInfo.add(debugInfo);
+    }
+
+    /**
+     * Associates information with the instance that can be useful for debugging / logging. The
+     * information is present in {@link #toString()} but is not considered for
+     * {@link #equals(Object)} and {@link #hashCode()}.
+     */
+    public void addDebugInfo(@NonNull List<String> debugInfo) {
+        if (mDebugInfo == null) {
+            mDebugInfo = new ArrayList<>(debugInfo.size());
+        }
+        mDebugInfo.addAll(debugInfo);
     }
 
     @Override
@@ -137,4 +150,44 @@
                 + ", mDebugInfo=" + mDebugInfo
                 + '}';
     }
+
+    /**
+     * Builds {@link PhoneTimeSuggestion} instances.
+     *
+     * @hide
+     */
+    public static class Builder {
+        private final int mPhoneId;
+        private TimestampedValue<Long> mUtcTime;
+        private List<String> mDebugInfo;
+
+        public Builder(int phoneId) {
+            mPhoneId = phoneId;
+        }
+
+        /** Returns the builder for call chaining. */
+        public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
+            if (utcTime != null) {
+                // utcTime can be null, but the value it holds cannot.
+                Objects.requireNonNull(utcTime.getValue());
+            }
+
+            mUtcTime = utcTime;
+            return this;
+        }
+
+        /** Returns the builder for call chaining. */
+        public Builder addDebugInfo(@NonNull String debugInfo) {
+            if (mDebugInfo == null) {
+                mDebugInfo = new ArrayList<>();
+            }
+            mDebugInfo.add(debugInfo);
+            return this;
+        }
+
+        /** Returns the {@link PhoneTimeSuggestion}. */
+        public PhoneTimeSuggestion build() {
+            return new PhoneTimeSuggestion(this);
+        }
+    }
 }
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 48d5cd2..611b66b 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -48,7 +48,7 @@
      * signal if better signals are available such as those that come from more reliable sources or
      * were determined more recently.
      */
-    @RequiresPermission(android.Manifest.permission.SET_TIME)
+    @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
     public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
         if (DEBUG) {
             Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
@@ -63,7 +63,7 @@
     /**
      * Suggests the user's manually entered current time to the detector.
      */
-    @RequiresPermission(android.Manifest.permission.SET_TIME)
+    @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
     public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) {
         if (DEBUG) {
             Log.d(TAG, "suggestManualTime called: " + timeSuggestion);
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index 387a36b..e165d8a 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -47,7 +47,7 @@
      * detector may ignore the signal based on system settings, whether better information is
      * available, and so on.
      */
-    @RequiresPermission(android.Manifest.permission.SET_TIME_ZONE)
+    @RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
     public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
         if (DEBUG) {
             Log.d(TAG, "suggestPhoneTimeZone called: " + timeZoneSuggestion);
@@ -63,7 +63,7 @@
      * Suggests the current time zone, determined for the user's manually information, to the
      * detector. The detector may ignore the signal based on system settings.
      */
-    @RequiresPermission(android.Manifest.permission.SET_TIME_ZONE)
+    @RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
     public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
         if (DEBUG) {
             Log.d(TAG, "suggestManualTimeZone called: " + timeZoneSuggestion);
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 749a011..92e1b30 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1041,8 +1041,11 @@
 
     /**
      * Inform usage stats that the carrier privileged apps access rules have changed.
+     * <p> The caller must have {@link android.Manifest.permission#BIND_CARRIER_SERVICES} </p>
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES)
     public void onCarrierPrivilegedAppsChanged() {
         try {
             mService.onCarrierPrivilegedAppsChanged();
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 8ed61b6..64df0e8 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -32,6 +33,8 @@
 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;
 
@@ -154,13 +157,22 @@
      */
     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
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
 
     /**
@@ -168,7 +180,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
 
     /**
@@ -176,16 +188,25 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @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.
+     * We don't have a stored preference for whether optional codecs should be enabled or
+     * disabled for the given A2DP device.
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
 
     /**
@@ -193,7 +214,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
 
     /**
@@ -201,7 +222,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
 
     private BluetoothAdapter mAdapter;
@@ -248,13 +269,12 @@
      * the state. Users can get the connection state of the profile
      * from this intent.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
      *
      * @param device Remote Bluetooth Device
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     @UnsupportedAppUsage
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
@@ -289,13 +309,12 @@
      * {@link #STATE_DISCONNECTING} can be used to distinguish between the
      * two scenarios.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
      *
      * @param device Remote Bluetooth Device
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
@@ -384,14 +403,12 @@
      * {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
      * with the active device.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
-     *
      * @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
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     @UnsupportedAppUsage
     public boolean setActiveDevice(@Nullable BluetoothDevice device) {
         if (DBG) log("setActiveDevice(" + device + ")");
@@ -412,16 +429,13 @@
     /**
      * Get the connected device that is active.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
-     * permission.
-     *
      * @return the connected device that is active or null if no device
      * is active
      * @hide
      */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    @SystemApi
     @Nullable
-    @UnsupportedAppUsage
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public BluetoothDevice getActiveDevice() {
         if (VDBG) log("getActiveDevice()");
         try {
@@ -441,7 +455,7 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
      *
      * @param device Paired bluetooth device
      * @param priority
@@ -626,8 +640,10 @@
      * @return the current codec status
      * @hide
      */
-    @UnsupportedAppUsage
-    public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
+    @SystemApi
+    @Nullable
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothCodecStatus getCodecStatus(@Nullable BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
         try {
             final IBluetoothA2dp service = getService();
@@ -652,9 +668,10 @@
      * @param codecConfig the codec configuration preference
      * @hide
      */
-    @UnsupportedAppUsage
-    public void setCodecConfigPreference(BluetoothDevice device,
-                                         BluetoothCodecConfig codecConfig) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public void setCodecConfigPreference(@Nullable BluetoothDevice device,
+                                         @Nullable BluetoothCodecConfig codecConfig) {
         if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
         try {
             final IBluetoothA2dp service = getService();
@@ -676,8 +693,9 @@
      * active A2DP Bluetooth device.
      * @hide
      */
-    @UnsupportedAppUsage
-    public void enableOptionalCodecs(BluetoothDevice device) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public void enableOptionalCodecs(@Nullable BluetoothDevice device) {
         if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
         enableDisableOptionalCodecs(device, true);
     }
@@ -689,8 +707,9 @@
      * active A2DP Bluetooth device.
      * @hide
      */
-    @UnsupportedAppUsage
-    public void disableOptionalCodecs(BluetoothDevice device) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public void disableOptionalCodecs(@Nullable BluetoothDevice device) {
         if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
         enableDisableOptionalCodecs(device, false);
     }
@@ -728,8 +747,10 @@
      * OPTIONAL_CODECS_SUPPORTED.
      * @hide
      */
-    @UnsupportedAppUsage
-    public int supportsOptionalCodecs(BluetoothDevice device) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    @OptionalCodecsSupportStatus
+    public int supportsOptionalCodecs(@Nullable BluetoothDevice device) {
         try {
             final IBluetoothA2dp service = getService();
             if (service != null && isEnabled() && isValidDevice(device)) {
@@ -738,7 +759,7 @@
             if (service == null) Log.w(TAG, "Proxy not attached to service");
             return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
         } catch (RemoteException e) {
-            Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+            Log.e(TAG, "Error talking to BT service in supportsOptionalCodecs()", e);
             return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
         }
     }
@@ -751,8 +772,10 @@
      * OPTIONAL_CODECS_PREF_DISABLED.
      * @hide
      */
-    @UnsupportedAppUsage
-    public int getOptionalCodecsEnabled(BluetoothDevice device) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    @OptionalCodecsPreferenceStatus
+    public int getOptionalCodecsEnabled(@Nullable BluetoothDevice device) {
         try {
             final IBluetoothA2dp service = getService();
             if (service != null && isEnabled() && isValidDevice(device)) {
@@ -761,7 +784,7 @@
             if (service == null) Log.w(TAG, "Proxy not attached to service");
             return OPTIONAL_CODECS_PREF_UNKNOWN;
         } catch (RemoteException e) {
-            Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+            Log.e(TAG, "Error talking to BT service in getOptionalCodecsEnabled()", e);
             return OPTIONAL_CODECS_PREF_UNKNOWN;
         }
     }
@@ -775,8 +798,10 @@
      * OPTIONAL_CODECS_PREF_DISABLED.
      * @hide
      */
-    @UnsupportedAppUsage
-    public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public void setOptionalCodecsEnabled(@Nullable BluetoothDevice device,
+            @OptionalCodecsPreferenceStatus int value) {
         try {
             if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
                     && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index c17834a..c6957e1 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -17,7 +17,9 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -39,6 +41,7 @@
  *
  * @hide
  */
+@SystemApi
 public final class BluetoothA2dpSink implements BluetoothProfile {
     private static final String TAG = "BluetoothA2dpSink";
     private static final boolean DBG = true;
@@ -59,71 +62,14 @@
      * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
+     * @hide
      */
+    @SystemApi
+    @SuppressLint("ActionValue")
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
 
-    /**
-     * Intent used to broadcast the change in the Playing 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_PLAYING}, {@link #STATE_NOT_PLAYING},
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
-     */
-    public static final String ACTION_PLAYING_STATE_CHANGED =
-            "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_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;
-
-    /**
-     * Intent used to broadcast the change in the Playing state of the A2DP Sink
-     * profile.
-     *
-     * <p>This intent will have 3 extras:
-     * <ul>
-     * <li> {@link #EXTRA_AUDIO_CONFIG} - The audio configuration for the remote device. </li>
-     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
-     * </ul>
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
-     * receive.
-     */
-    public static final String ACTION_AUDIO_CONFIG_CHANGED =
-            "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED";
-
-    /**
-     * Extra for the {@link #ACTION_AUDIO_CONFIG_CHANGED} intent.
-     *
-     * This extra represents the current audio configuration of the A2DP source device.
-     * {@see BluetoothAudioConfig}
-     */
-    public static final String EXTRA_AUDIO_CONFIG =
-            "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
-
     private BluetoothAdapter mAdapter;
     private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
             new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
@@ -170,13 +116,11 @@
      * the state. Users can get the connection state of the profile
      * from this intent.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
-     *
      * @param device Remote Bluetooth Device
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
         final IBluetoothA2dpSink service = getService();
@@ -210,14 +154,12 @@
      * {@link #STATE_DISCONNECTING} can be used to distinguish between the
      * two scenarios.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
-     *
      * @param device Remote Bluetooth Device
      * @return false on immediate error, true otherwise
      * @hide
      */
     @UnsupportedAppUsage
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
         final IBluetoothA2dpSink service = getService();
@@ -235,6 +177,8 @@
 
     /**
      * {@inheritDoc}
+     *
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
@@ -254,6 +198,8 @@
 
     /**
      * {@inheritDoc}
+     *
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -273,6 +219,8 @@
 
     /**
      * {@inheritDoc}
+     *
+     * @hide
      */
     @Override
     public int getConnectionState(BluetoothDevice device) {
@@ -300,6 +248,8 @@
      * @return audio configuration for the device, or null
      *
      * {@see BluetoothAudioConfig}
+     *
+     * @hide
      */
     public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
         if (VDBG) log("getAudioConfig(" + device + ")");
@@ -320,7 +270,7 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
      *
      * @param device Paired bluetooth device
      * @param priority
@@ -347,7 +297,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
-    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+    public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) {
         if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -395,7 +345,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getConnectionPolicy(BluetoothDevice device) {
+    public int getConnectionPolicy(@Nullable BluetoothDevice device) {
         if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
@@ -411,13 +361,16 @@
     }
 
     /**
-     * Check if A2DP profile is streaming music.
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     * 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
      */
-    public boolean isA2dpPlaying(BluetoothDevice device) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public boolean isAudioPlaying(@Nullable BluetoothDevice device) {
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
@@ -448,9 +401,9 @@
                 return "connected";
             case STATE_DISCONNECTING:
                 return "disconnecting";
-            case STATE_PLAYING:
+            case BluetoothA2dp.STATE_PLAYING:
                 return "playing";
-            case STATE_NOT_PLAYING:
+            case BluetoothA2dp.STATE_NOT_PLAYING:
                 return "not playing";
             default:
                 return "<unknown state " + state + ">";
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9b5280d..291d1d9 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -847,7 +847,8 @@
         }
         synchronized (mLock) {
             if (sBluetoothLeScanner == null) {
-                sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
+                sBluetoothLeScanner = new BluetoothLeScanner(mManagerService, getOpPackageName(),
+                        getFeatureId());
             }
         }
         return sBluetoothLeScanner;
@@ -862,18 +863,7 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public boolean isEnabled() {
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isEnabled();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-
-        return false;
+        return getState() == BluetoothAdapter.STATE_ON;
     }
 
     /**
@@ -1648,6 +1638,15 @@
         return ActivityThread.currentOpPackageName();
     }
 
+    private String getFeatureId() {
+        // Workaround for legacy API for getting a BluetoothAdapter not
+        // passing a context
+        if (mContext != null) {
+            return null;
+        }
+        return null;
+    }
+
     /**
      * Start the remote device discovery process.
      * <p>The discovery process usually involves an inquiry scan of about 12
@@ -1685,7 +1684,7 @@
         try {
             mServiceLock.readLock().lock();
             if (mService != null) {
-                return mService.startDiscovery(getOpPackageName());
+                return mService.startDiscovery(getOpPackageName(), getFeatureId());
             }
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 36f3a1e..08d0797 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -16,10 +16,15 @@
 
 package android.bluetooth;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
@@ -29,78 +34,131 @@
  *
  * {@hide}
  */
+@SystemApi
 public final class BluetoothCodecConfig implements Parcelable {
     // Add an entry for each source codec here.
     // NOTE: The values should be same as those listed in the following file:
     //   hardware/libhardware/include/hardware/bt_av.h
-    @UnsupportedAppUsage
+
+    /** @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_MAX,
+            SOURCE_CODEC_TYPE_INVALID
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SourceCodecType {}
+
     public static final int SOURCE_CODEC_TYPE_SBC = 0;
-    @UnsupportedAppUsage
+
     public static final int SOURCE_CODEC_TYPE_AAC = 1;
-    @UnsupportedAppUsage
+
     public static final int SOURCE_CODEC_TYPE_APTX = 2;
-    @UnsupportedAppUsage
+
     public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
-    @UnsupportedAppUsage
+
     public static final int SOURCE_CODEC_TYPE_LDAC = 4;
-    @UnsupportedAppUsage
+
     public static final int SOURCE_CODEC_TYPE_MAX = 5;
 
-    @UnsupportedAppUsage
+
     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
 
-    @UnsupportedAppUsage
+    /** @hide */
+    @IntDef(prefix = "CODEC_PRIORITY_", value = {
+            CODEC_PRIORITY_DISABLED,
+            CODEC_PRIORITY_DEFAULT,
+            CODEC_PRIORITY_HIGHEST
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CodecPriority {}
+
     public static final int CODEC_PRIORITY_DISABLED = -1;
-    @UnsupportedAppUsage
+
     public static final int CODEC_PRIORITY_DEFAULT = 0;
-    @UnsupportedAppUsage
+
     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
 
-    @UnsupportedAppUsage
+
+    /** @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 {}
+
     public static final int SAMPLE_RATE_NONE = 0;
-    @UnsupportedAppUsage
+
     public static final int SAMPLE_RATE_44100 = 0x1 << 0;
-    @UnsupportedAppUsage
+
     public static final int SAMPLE_RATE_48000 = 0x1 << 1;
-    @UnsupportedAppUsage
+
     public static final int SAMPLE_RATE_88200 = 0x1 << 2;
-    @UnsupportedAppUsage
+
     public static final int SAMPLE_RATE_96000 = 0x1 << 3;
-    @UnsupportedAppUsage
+
     public static final int SAMPLE_RATE_176400 = 0x1 << 4;
-    @UnsupportedAppUsage
+
     public static final int SAMPLE_RATE_192000 = 0x1 << 5;
 
-    @UnsupportedAppUsage
+
+    /** @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 {}
+
     public static final int BITS_PER_SAMPLE_NONE = 0;
-    @UnsupportedAppUsage
+
     public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
-    @UnsupportedAppUsage
+
     public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
-    @UnsupportedAppUsage
+
     public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
 
-    @UnsupportedAppUsage
+
+    /** @hide */
+    @IntDef(prefix = "CHANNEL_MODE_", value = {
+            CHANNEL_MODE_NONE,
+            CHANNEL_MODE_MONO,
+            CHANNEL_MODE_STEREO
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ChannelMode {}
+
     public static final int CHANNEL_MODE_NONE = 0;
-    @UnsupportedAppUsage
+
     public static final int CHANNEL_MODE_MONO = 0x1 << 0;
-    @UnsupportedAppUsage
+
     public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
 
-    private final int mCodecType;
-    private int mCodecPriority;
-    private final int mSampleRate;
-    private final int mBitsPerSample;
-    private final int mChannelMode;
+    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;
 
-    @UnsupportedAppUsage
-    public BluetoothCodecConfig(int codecType, int codecPriority,
-            int sampleRate, int bitsPerSample,
-            int channelMode, long codecSpecific1,
+    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;
@@ -114,8 +172,7 @@
         mCodecSpecific4 = codecSpecific4;
     }
 
-    @UnsupportedAppUsage
-    public BluetoothCodecConfig(int codecType) {
+    public BluetoothCodecConfig(@SourceCodecType int codecType) {
         mCodecType = codecType;
         mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
         mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
@@ -144,6 +201,12 @@
         return false;
     }
 
+    /**
+     * Returns a hash based on the config values
+     *
+     * @return a hash based on the config values
+     * @hide
+     */
     @Override
     public int hashCode() {
         return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
@@ -155,6 +218,7 @@
      * Checks whether the object contains valid codec configuration.
      *
      * @return true if the object contains valid codec configuration, otherwise false.
+     * @hide
      */
     public boolean isValid() {
         return (mSampleRate != SAMPLE_RATE_NONE)
@@ -242,6 +306,12 @@
                 + ",mCodecSpecific4:" + mCodecSpecific4 + "}";
     }
 
+    /**
+     * Always returns 0
+     *
+     * @return 0
+     * @hide
+     */
     @Override
     public int describeContents() {
         return 0;
@@ -271,6 +341,14 @@
                 }
             };
 
+    /**
+     * 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);
@@ -289,7 +367,7 @@
      *
      * @return the codec name
      */
-    public String getCodecName() {
+    public @NonNull String getCodecName() {
         switch (mCodecType) {
             case SOURCE_CODEC_TYPE_SBC:
                 return "SBC";
@@ -315,8 +393,7 @@
      *
      * @return the codec type
      */
-    @UnsupportedAppUsage
-    public int getCodecType() {
+    public @SourceCodecType int getCodecType() {
         return mCodecType;
     }
 
@@ -336,8 +413,7 @@
      *
      * @return the codec priority
      */
-    @UnsupportedAppUsage
-    public int getCodecPriority() {
+    public @CodecPriority int getCodecPriority() {
         return mCodecPriority;
     }
 
@@ -347,9 +423,10 @@
      * means higher priority. If 0, reset to default.
      *
      * @param codecPriority the codec priority
+     * @hide
      */
     @UnsupportedAppUsage
-    public void setCodecPriority(int codecPriority) {
+    public void setCodecPriority(@CodecPriority int codecPriority) {
         mCodecPriority = codecPriority;
     }
 
@@ -366,8 +443,7 @@
      *
      * @return the codec sample rate
      */
-    @UnsupportedAppUsage
-    public int getSampleRate() {
+    public @SampleRate int getSampleRate() {
         return mSampleRate;
     }
 
@@ -381,8 +457,7 @@
      *
      * @return the codec bits per sample
      */
-    @UnsupportedAppUsage
-    public int getBitsPerSample() {
+    public @BitsPerSample int getBitsPerSample() {
         return mBitsPerSample;
     }
 
@@ -394,9 +469,10 @@
      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
      *
      * @return the codec channel mode
+     * @hide
      */
     @UnsupportedAppUsage
-    public int getChannelMode() {
+    public @ChannelMode int getChannelMode() {
         return mChannelMode;
     }
 
@@ -405,7 +481,6 @@
      *
      * @return a codec specific value1.
      */
-    @UnsupportedAppUsage
     public long getCodecSpecific1() {
         return mCodecSpecific1;
     }
@@ -414,6 +489,7 @@
      * Gets a codec specific value2.
      *
      * @return a codec specific value2
+     * @hide
      */
     @UnsupportedAppUsage
     public long getCodecSpecific2() {
@@ -424,6 +500,7 @@
      * Gets a codec specific value3.
      *
      * @return a codec specific value3
+     * @hide
      */
     @UnsupportedAppUsage
     public long getCodecSpecific3() {
@@ -434,6 +511,7 @@
      * Gets a codec specific value4.
      *
      * @return a codec specific value4
+     * @hide
      */
     @UnsupportedAppUsage
     public long getCodecSpecific4() {
@@ -445,6 +523,7 @@
      *
      * @param valueSet the value set presented by a bitmask
      * @return true if the valueSet contains zero or single bit, otherwise false.
+     * @hide
      */
     private static boolean hasSingleBit(int valueSet) {
         return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
@@ -454,6 +533,7 @@
      * Checks whether the object contains none or single sample rate.
      *
      * @return true if the object contains none or single sample rate, otherwise false.
+     * @hide
      */
     public boolean hasSingleSampleRate() {
         return hasSingleBit(mSampleRate);
@@ -463,6 +543,7 @@
      * Checks whether the object contains none or single bits per sample.
      *
      * @return true if the object contains none or single bits per sample, otherwise false.
+     * @hide
      */
     public boolean hasSingleBitsPerSample() {
         return hasSingleBit(mBitsPerSample);
@@ -472,6 +553,7 @@
      * Checks whether the object contains none or single channel mode.
      *
      * @return true if the object contains none or single channel mode, otherwise false.
+     * @hide
      */
     public boolean hasSingleChannelMode() {
         return hasSingleBit(mChannelMode);
@@ -482,6 +564,7 @@
      *
      * @param other the codec config to compare against
      * @return true if the audio feeding parameters are same, otherwise false
+     * @hide
      */
     public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
         return (other != null && other.mSampleRate == mSampleRate
@@ -495,6 +578,7 @@
      *
      * @param other the codec config to compare against
      * @return true if the audio feeding parameters are similar, otherwise false.
+     * @hide
      */
     public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
         if (other == null || mCodecType != other.mCodecType) {
@@ -526,6 +610,7 @@
      *
      * @param other the codec config to compare against
      * @return true if the codec specific parameters are the same, otherwise false.
+     * @hide
      */
     public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
         if (other == null && mCodecType != other.mCodecType) {
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 58a764a..b6e7739 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -17,7 +17,7 @@
 package android.bluetooth;
 
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,6 +32,7 @@
  *
  * {@hide}
  */
+@SystemApi
 public final class BluetoothCodecStatus implements Parcelable {
     /**
      * Extra for the codec configuration intents of the individual profiles.
@@ -39,17 +40,16 @@
      * This extra represents the current codec status of the A2DP
      * profile.
      */
-    @UnsupportedAppUsage
     public static final String EXTRA_CODEC_STATUS =
-            "android.bluetooth.codec.extra.CODEC_STATUS";
+            "android.bluetooth.extra.CODEC_STATUS";
 
     private final @Nullable BluetoothCodecConfig mCodecConfig;
     private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
     private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
 
-    public BluetoothCodecStatus(BluetoothCodecConfig codecConfig,
-            BluetoothCodecConfig[] codecsLocalCapabilities,
-            BluetoothCodecConfig[] codecsSelectableCapabilities) {
+    public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
+            @Nullable BluetoothCodecConfig[] codecsLocalCapabilities,
+            @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) {
         mCodecConfig = codecConfig;
         mCodecsLocalCapabilities = codecsLocalCapabilities;
         mCodecsSelectableCapabilities = codecsSelectableCapabilities;
@@ -74,6 +74,7 @@
      * @param c1 the first array of capabilities to compare
      * @param c2 the second array of capabilities to compare
      * @return true if both arrays contain same capabilities
+     * @hide
      */
     public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
                                            BluetoothCodecConfig[] c2) {
@@ -95,6 +96,7 @@
      *
      * @param codecConfig the codec config to compare against
      * @return true if the codec config matches, otherwise false
+     * @hide
      */
     public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
         if (codecConfig == null || !codecConfig.hasSingleSampleRate()
@@ -125,7 +127,12 @@
         return false;
     }
 
-
+    /**
+     * Returns a hash based on the codec config and local capabilities
+     *
+     * @return a hash based on the config values
+     * @hide
+     */
     @Override
     public int hashCode() {
         return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
@@ -140,6 +147,12 @@
                 + "}";
     }
 
+    /**
+     * Always returns 0
+     *
+     * @return 0
+     * @hide
+     */
     @Override
     public int describeContents() {
         return 0;
@@ -165,6 +178,14 @@
                 }
             };
 
+    /**
+     * 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.writeTypedObject(mCodecConfig, 0);
@@ -177,7 +198,6 @@
      *
      * @return the current codec configuration
      */
-    @UnsupportedAppUsage
     public @Nullable BluetoothCodecConfig getCodecConfig() {
         return mCodecConfig;
     }
@@ -187,8 +207,7 @@
      *
      * @return an array with the codecs local capabilities
      */
-    @UnsupportedAppUsage
-    public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
+    public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
         return mCodecsLocalCapabilities;
     }
 
@@ -197,8 +216,7 @@
      *
      * @return an array with the codecs selectable capabilities
      */
-    @UnsupportedAppUsage
-    public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
+    public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
         return mCodecsSelectableCapabilities;
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 0be3eca..323c7d1 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -33,8 +34,12 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.UUID;
 
 /**
@@ -771,6 +776,13 @@
     @UnsupportedAppUsage
     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}.
@@ -1096,15 +1108,14 @@
 
     /**
      * Get the most recent identified battery level of this Bluetooth device
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
      *
      * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if
      * Bluetooth is disabled, or device is disconnected, or does not have any battery reporting
      * service, or return value is invalid
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    @UnsupportedAppUsage
     public int getBatteryLevel() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1131,20 +1142,7 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean createBond() {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
-            return false;
-        }
-        try {
-            Log.i(TAG, "createBond() for device " + getAddress()
-                    + " called by pid: " + Process.myPid()
-                    + " tid: " + Process.myTid());
-            return service.createBond(this, TRANSPORT_AUTO);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
+        return createBond(TRANSPORT_AUTO);
     }
 
     /**
@@ -1165,23 +1163,7 @@
      */
     @UnsupportedAppUsage
     public boolean createBond(int transport) {
-        final IBluetooth service = sService;
-        if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
-            return false;
-        }
-        if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) {
-            throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
-        }
-        try {
-            Log.i(TAG, "createBond() for device " + getAddress()
-                    + " called by pid: " + Process.myPid()
-                    + " tid: " + Process.myTid());
-            return service.createBond(this, transport);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        }
-        return false;
+        return createBondOutOfBand(transport, null);
     }
 
     /**
@@ -1209,15 +1191,22 @@
             return false;
         }
         try {
-            return service.createBondOutOfBand(this, transport, oobData);
+            return service.createBond(this, transport, oobData);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
         return false;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
+    /**
+     * Gets whether bonding was initiated locally
+     *
+     * @return true if bonding is initiated locally, false otherwise
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public boolean isBondingInitiatedLocally() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1509,15 +1498,20 @@
         return false;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
-    public boolean setPasskey(int passkey) {
-        //TODO(BT)
-        /*
-        try {
-            return sService.setPasskey(this, true, 4, passkey);
-        } 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setPin(@Nullable String pin) {
+        byte[] pinBytes = convertPinToBytes(pin);
+        if (pinBytes == null) {
+            return false;
+        }
+        return setPin(pinBytes);
     }
 
     /**
@@ -1540,22 +1534,18 @@
         return false;
     }
 
-    /** @hide */
-    public boolean setRemoteOutOfBandData() {
-        // TODO(BT)
-        /*
-        try {
-          return sService.setRemoteOutOfBandData(this);
-      } catch (RemoteException e) {Log.e(TAG, "", e);}*/
-        return false;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public boolean cancelPairingUserInput() {
+    /**
+     * Cancels pairing to this device
+     *
+     * @return true if pairing cancelled successfully, false otherwise
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean cancelPairing() {
         final IBluetooth service = sService;
         if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot create pairing user input");
+            Log.e(TAG, "BT not enabled. Cannot cancel pairing");
             return false;
         }
         try {
@@ -1566,17 +1556,6 @@
         return false;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
-    public boolean isBluetoothDock() {
-        // TODO(BT)
-        /*
-        try {
-            return sService.isBluetoothDock(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
-        return false;
-    }
-
     boolean isBluetoothEnabled() {
         boolean ret = false;
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1587,13 +1566,14 @@
     }
 
     /**
-     * Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * 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
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPhonebookAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1696,14 +1676,14 @@
     }
 
     /**
-     * Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * Gets whether message access is allowed to this bluetooth device
      *
-     * @return Whether the message access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
-     * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
+     * @return Whether the message access is allowed to this device.
      * @hide
      */
-    @UnsupportedAppUsage
-    public int getMessageAccessPermission() {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @AccessPermission int getMessageAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
             return ACCESS_UNKNOWN;
@@ -1718,15 +1698,18 @@
 
     /**
      * Sets whether the message access is allowed to this device.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
      *
-     * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
-     * #ACCESS_REJECTED}.
+     * @param value is the value we are setting the message access permission to
      * @return Whether the value has been successfully set.
      * @hide
      */
-    @UnsupportedAppUsage
-    public boolean setMessageAccessPermission(int value) {
+    @SystemApi
+    @RequiresPermission(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;
@@ -1740,13 +1723,14 @@
     }
 
     /**
-     * Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * Gets whether sim access is allowed for this bluetooth device
      *
-     * @return Whether the Sim access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
-     * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
+     * @return Whether the Sim access is allowed to this device.
      * @hide
      */
-    public int getSimAccessPermission() {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @AccessPermission int getSimAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
             return ACCESS_UNKNOWN;
@@ -1761,14 +1745,14 @@
 
     /**
      * Sets whether the Sim access is allowed to this device.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
      *
      * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
      * #ACCESS_REJECTED}.
      * @return Whether the value has been successfully set.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
     public boolean setSimAccessPermission(int value) {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1999,7 +1983,7 @@
      * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
      * @hide
      */
-    @UnsupportedAppUsage
+    @VisibleForTesting
     public static byte[] convertPinToBytes(String pin) {
         if (pin == null) {
             return null;
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index ead8429..a65162a 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -335,9 +335,9 @@
      * is not active, it will be null on that position. Returns empty list on error.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public List<BluetoothDevice> getActiveDevices() {
+    public @NonNull List<BluetoothDevice> getActiveDevices() {
         if (VDBG) log("getActiveDevices()");
         final IBluetoothHearingAid service = getService();
         try {
@@ -472,63 +472,6 @@
     }
 
     /**
-     * Get the volume of the device.
-     *
-     * <p> The volume is between -128 dB (mute) to 0 dB.
-     *
-     * @return volume of the hearing aid device.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getVolume() {
-        if (VDBG) {
-            log("getVolume()");
-        }
-        final IBluetoothHearingAid service = getService();
-        try {
-            if (service != null && isEnabled()) {
-                return service.getVolume();
-            }
-            if (service == null) Log.w(TAG, "Proxy not attached to service");
-            return 0;
-        } catch (RemoteException e) {
-            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-            return 0;
-        }
-    }
-
-    /**
-     * Tells remote device to adjust volume. Uses the following values:
-     * <ul>
-     * <li>{@link AudioManager#ADJUST_LOWER}</li>
-     * <li>{@link AudioManager#ADJUST_RAISE}</li>
-     * <li>{@link AudioManager#ADJUST_MUTE}</li>
-     * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
-     * </ul>
-     *
-     * @param direction One of the supported adjust values.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public void adjustVolume(int direction) {
-        if (DBG) log("adjustVolume(" + direction + ")");
-
-        final IBluetoothHearingAid service = getService();
-        try {
-            if (service == null) {
-                Log.w(TAG, "Proxy not attached to service");
-                return;
-            }
-
-            if (!isEnabled()) return;
-
-            service.adjustVolume(direction);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-        }
-    }
-
-    /**
      * Tells remote device to set an absolute volume.
      *
      * @param volume Absolute volume to be set on remote
@@ -559,8 +502,9 @@
      * @return the CustomerId of the device
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public long getHiSyncId(BluetoothDevice device) {
+    public long getHiSyncId(@Nullable BluetoothDevice device) {
         if (VDBG) {
             log("getCustomerId(" + device + ")");
         }
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index adedff3..cff4c2d 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -22,7 +22,9 @@
 import android.annotation.SystemService;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -60,22 +62,34 @@
      * @hide
      */
     public BluetoothManager(Context context) {
-        context = context.getApplicationContext();
-        if (context == null) {
-            throw new IllegalArgumentException(
-                    "context not associated with any application (using a mock context?)");
+        if (null == null) {
+            context = context.getApplicationContext();
+            if (context == null) {
+                throw new IllegalArgumentException(
+                        "context not associated with any application (using a mock context?)");
+            }
+
+            mAdapter = BluetoothAdapter.getDefaultAdapter();
+        } else {
+            IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
+            if (b != null) {
+                mAdapter = new BluetoothAdapter(IBluetoothManager.Stub.asInterface(b));
+            } else {
+                Log.e(TAG, "Bluetooth binder is null");
+                mAdapter = null;
+            }
         }
-        // Legacy api - getDefaultAdapter does not take in the context
-        mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+        // Context is not initialized in constructor
         if (mAdapter != null) {
             mAdapter.setContext(context);
         }
     }
 
     /**
-     * Get the default BLUETOOTH Adapter for this device.
+     * Get the BLUETOOTH Adapter for this device.
      *
-     * @return the default BLUETOOTH Adapter
+     * @return the BLUETOOTH Adapter
      */
     public BluetoothAdapter getAdapter() {
         return mAdapter;
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index d94c657..df02896 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -16,7 +16,10 @@
 
 package android.bluetooth;
 
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -54,6 +57,7 @@
  *
  * @hide
  */
+@SystemApi
 public class BluetoothPbap implements BluetoothProfile {
 
     private static final String TAG = "BluetoothPbap";
@@ -75,7 +79,11 @@
      *  {@link BluetoothProfile#STATE_DISCONNECTING}.
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
      * receive.
+     *
+     * @hide
      */
+    @SuppressLint("ActionValue")
+    @SystemApi
     @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
@@ -85,33 +93,16 @@
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
 
+    /** @hide */
     public static final int RESULT_FAILURE = 0;
+    /** @hide */
     public static final int RESULT_SUCCESS = 1;
-    /** Connection canceled before completion. */
-    public static final int RESULT_CANCELED = 2;
-
     /**
-     * An interface for notifying Bluetooth PCE IPC clients when they have
-     * been connected to the BluetoothPbap service.
+     * Connection canceled before completion.
+     *
+     * @hide
      */
-    public interface ServiceListener {
-        /**
-         * Called to notify the client when this proxy object has been
-         * connected to the BluetoothPbap service. Clients must wait for
-         * this callback before making IPC calls on the BluetoothPbap
-         * service.
-         */
-        public void onServiceConnected(BluetoothPbap proxy);
-
-        /**
-         * Called to notify the client that this proxy object has been
-         * disconnected from the BluetoothPbap service. Clients must not
-         * make IPC calls on the BluetoothPbap service after this callback.
-         * This callback will currently only occur if the application hosting
-         * the BluetoothPbap service, but may be called more often in future.
-         */
-        public void onServiceDisconnected();
-    }
+    public static final int RESULT_CANCELED = 2;
 
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
             new IBluetoothStateChangeCallback.Stub() {
@@ -127,6 +118,8 @@
 
     /**
      * Create a BluetoothPbap proxy object.
+     *
+     * @hide
      */
     public BluetoothPbap(Context context, ServiceListener l) {
         mContext = context;
@@ -181,6 +174,7 @@
         }
     }
 
+    /** @hide */
     protected void finalize() throws Throwable {
         try {
             close();
@@ -194,6 +188,8 @@
      * 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() {
         IBluetoothManager mgr = mAdapter.getBluetoothManager();
@@ -210,6 +206,8 @@
 
     /**
      * {@inheritDoc}
+     *
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
@@ -229,17 +227,22 @@
 
     /**
      * {@inheritDoc}
+     *
+     * @hide
      */
+    @SystemApi
     @Override
-    public int getConnectionState(BluetoothDevice device) {
+    public int getConnectionState(@Nullable BluetoothDevice device) {
         log("getConnectionState: device=" + device);
-        final IBluetoothPbap service = mService;
-        if (service == null) {
-            Log.w(TAG, "Proxy not attached to service");
-            return BluetoothProfile.STATE_DISCONNECTED;
-        }
         try {
-            return service.getConnectionState(device);
+            final IBluetoothPbap service = mService;
+            if (service != null && isEnabled() && isValidDevice(device)) {
+                return service.getConnectionState(device);
+            }
+            if (service == null) {
+                Log.w(TAG, "Proxy not attached to service");
+            }
+            return BluetoothProfile.STATE_DISCONNECTED;
         } catch (RemoteException e) {
             Log.e(TAG, e.toString());
         }
@@ -248,6 +251,8 @@
 
     /**
      * {@inheritDoc}
+     *
+     * @hide
      */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -266,22 +271,12 @@
     }
 
     /**
-     * Returns true if the specified Bluetooth device is connected (does not
-     * include connecting). Returns false if not connected, or if this proxy
-     * object is not currently connected to the Pbap service.
-     */
-    // TODO: This is currently being used by SettingsLib and internal app.
-    public boolean isConnected(BluetoothDevice device) {
-        return getConnectionState(device) == BluetoothAdapter.STATE_CONNECTED;
-    }
-
-    /**
      * 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
      */
-    // TODO: This is currently being used by SettingsLib and will be used in the future.
-    // TODO: Must specify target device. Implement this in the service.
     @UnsupportedAppUsage
     public boolean disconnect(BluetoothDevice device) {
         log("disconnect()");
@@ -304,7 +299,7 @@
             log("Proxy object connected");
             mService = IBluetoothPbap.Stub.asInterface(service);
             if (mServiceListener != null) {
-                mServiceListener.onServiceConnected(BluetoothPbap.this);
+                mServiceListener.onServiceConnected(BluetoothProfile.PBAP, BluetoothPbap.this);
             }
         }
 
@@ -312,11 +307,23 @@
             log("Proxy object disconnected");
             doUnbind();
             if (mServiceListener != null) {
-                mServiceListener.onServiceDisconnected();
+                mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP);
             }
         }
     };
 
+    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/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index ac126ae..9a17346 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -21,7 +21,6 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.app.ActivityThread;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothGatt;
@@ -84,17 +83,25 @@
     private BluetoothAdapter mBluetoothAdapter;
     private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients;
 
+    private final String mOpPackageName;
+    private final String mFeatureId;
+
     /**
      * 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(IBluetoothManager bluetoothManager) {
+    public BluetoothLeScanner(IBluetoothManager bluetoothManager,
+            @NonNull String opPackageName, @Nullable String featureId) {
         mBluetoothManager = bluetoothManager;
         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         mHandler = new Handler(Looper.getMainLooper());
         mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>();
+        mOpPackageName = opPackageName;
+        mFeatureId = featureId;
     }
 
     /**
@@ -246,8 +253,8 @@
                 wrapper.startRegistration();
             } else {
                 try {
-                    gatt.startScanForIntent(callbackIntent, settings, filters,
-                            ActivityThread.currentOpPackageName());
+                    gatt.startScanForIntent(callbackIntent, settings, filters, mOpPackageName,
+                            mFeatureId);
                 } catch (RemoteException e) {
                     return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
                 }
@@ -288,7 +295,7 @@
         IBluetoothGatt gatt;
         try {
             gatt = mBluetoothManager.getBluetoothGatt();
-            gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
+            gatt.stopScanForIntent(callbackIntent, mOpPackageName);
         } catch (RemoteException e) {
         }
     }
@@ -448,8 +455,7 @@
                         } else {
                             mScannerId = scannerId;
                             mBluetoothGatt.startScan(mScannerId, mSettings, mFilters,
-                                    mResultStorages,
-                                    ActivityThread.currentOpPackageName());
+                                    mResultStorages, mOpPackageName, mFeatureId);
                         }
                     } catch (RemoteException e) {
                         Log.e(TAG, "fail to start le scan: " + e);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2086053..902c6b9d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3858,6 +3858,15 @@
     public static final String NETWORK_STACK_SERVICE = "network_stack";
 
     /**
+     * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+     * {@link ITetheringConnector} IBinder for communicating with the tethering service
+     * @hide
+     * @see TetheringClient
+     */
+    @SystemApi
+    public static final String TETHERING_SERVICE = "tethering";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.net.IpSecManager} for encrypting Sockets or Networks with
      * IPSec.
@@ -4821,6 +4830,8 @@
      * {@link android.telephony.ims.ImsManager}.
      * @hide
      */
+    @SystemApi
+    @TestApi
     public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
 
     /**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 22b345f..877557f 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -943,6 +943,12 @@
         return mBase.getUserId();
     }
 
+    /** @hide */
+    @Override
+    public UserHandle getUser() {
+        return mBase.getUser();
+    }
+
     @Override
     public Context createConfigurationContext(Configuration overrideConfiguration) {
         return mBase.createConfigurationContext(overrideConfiguration);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2a17800..a6867ff 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1134,6 +1134,18 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
     /**
+     * Activity Action: Dial a emergency number specified by the data.  This shows a
+     * UI with the number being dialed, allowing the user to explicitly
+     * initiate the call.
+     * <p>Input: If nothing, an empty emergency dialer is started; else {@link #getData}
+     * is a tel: URI of an explicit emergency phone number.
+     * <p>Output: nothing.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_DIAL_EMERGENCY = "android.intent.action.DIAL_EMERGENCY";
+    /**
      * Activity action: Perform a call to any number (emergency or not)
      * specified by the data.
      * <p>Input: {@link #getData} is URI of a phone number to be dialed or a
@@ -3995,9 +4007,15 @@
      * Broadcast Action: The sim card state has changed.
      * For more details see TelephonyIntents.ACTION_SIM_STATE_CHANGED. This is here
      * because TelephonyIntents is an internal class.
-     * @hide
+     * The intent will have following extras.</p>
+     * <p>
+     * @see #EXTRA_SIM_STATE
+     * @see #EXTRA_SIM_LOCKED_REASON
+     *
      * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
      * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     *
+     * @hide
      */
     @Deprecated
     @SystemApi
@@ -4005,6 +4023,170 @@
     public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
 
     /**
+     * The extra used with {@link #ACTION_SIM_STATE_CHANGED} for broadcasting SIM STATE.
+     * This will have one of the following intent values.
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_NOT_READY
+     * @see #SIM_STATE_ABSENT
+     * @see #SIM_STATE_PRESENT
+     * @see #SIM_STATE_CARD_IO_ERROR
+     * @see #SIM_STATE_CARD_RESTRICTED
+     * @see #SIM_STATE_LOCKED
+     * @see #SIM_STATE_READY
+     * @see #SIM_STATE_IMSI
+     * @see #SIM_STATE_LOADED
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_SIM_STATE = "ss";
+
+    /**
+     * The intent value UNKNOWN represents the SIM state unknown
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_UNKNOWN = "UNKNOWN";
+
+    /**
+     * The intent value NOT_READY means that the SIM is not ready eg. radio is off or powering on
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_NOT_READY = "NOT_READY";
+
+    /**
+     * The intent value ABSENT means the SIM card is missing
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_ABSENT = "ABSENT";
+
+    /**
+     * The intent value PRESENT means the device has a SIM card inserted
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_PRESENT = "PRESENT";
+
+    /**
+     * The intent value CARD_IO_ERROR means for three consecutive times there was SIM IO error
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    static public final String SIM_STATE_CARD_IO_ERROR = "CARD_IO_ERROR";
+
+    /**
+     * The intent value CARD_RESTRICTED means card is present but not usable due to carrier
+     * restrictions
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    static public final String SIM_STATE_CARD_RESTRICTED = "CARD_RESTRICTED";
+
+    /**
+     * The intent value LOCKED means the SIM is locked by PIN or by network
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_LOCKED = "LOCKED";
+
+    /**
+     * The intent value READY means the SIM is ready to be accessed
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_READY = "READY";
+
+    /**
+     * The intent value IMSI means the SIM IMSI is ready in property
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_IMSI = "IMSI";
+
+    /**
+     * The intent value LOADED means all SIM records, including IMSI, are loaded
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_STATE_LOADED = "LOADED";
+
+    /**
+     * The extra used with {@link #ACTION_SIM_STATE_CHANGED} for broadcasting SIM STATE.
+     * This extra will have one of the following intent values.
+     * <p>
+     * @see #SIM_LOCKED_ON_PIN
+     * @see #SIM_LOCKED_ON_PUK
+     * @see #SIM_LOCKED_NETWORK
+     * @see #SIM_ABSENT_ON_PERM_DISABLED
+     *
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_SIM_LOCKED_REASON = "reason";
+
+    /**
+     * The intent value PIN means the SIM is locked on PIN1
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_LOCKED_ON_PIN = "PIN";
+
+    /**
+     * The intent value PUK means the SIM is locked on PUK1
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     */
+    /* PUK means ICC is locked on PUK1 */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_LOCKED_ON_PUK = "PUK";
+
+    /**
+     * The intent value NETWORK means the SIM is locked on NETWORK PERSONALIZATION
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_LOCKED_NETWORK = "NETWORK";
+
+    /**
+     * The intent value PERM_DISABLED means SIM is permanently disabled due to puk fails
+     * @hide
+     * @deprecated Use {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
+     */
+    @Deprecated
+    @SystemApi
+    public static final String SIM_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
+
+    /**
      * Broadcast Action: indicate that the phone service state has changed.
      * The intent will have the following extra values:</p>
      * <p>
diff --git a/core/java/android/content/pm/ParceledListSlice.aidl b/core/java/android/content/pm/ParceledListSlice.aidl
index c02cc6a..5031fba 100644
--- a/core/java/android/content/pm/ParceledListSlice.aidl
+++ b/core/java/android/content/pm/ParceledListSlice.aidl
@@ -16,4 +16,4 @@
 
 package android.content.pm;
 
-parcelable ParceledListSlice;
+parcelable ParceledListSlice<T>;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a6e070e..82cecb6 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -50,6 +50,7 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -57,7 +58,6 @@
 import android.util.Log;
 import android.util.SparseIntArray;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.Protocol;
 
@@ -802,6 +802,7 @@
 
     private INetworkManagementService mNMService;
     private INetworkPolicyManager mNPManager;
+    private TetheringManager mTetheringManager;
 
     /**
      * Tests if a given integer represents a valid network type.
@@ -2340,6 +2341,28 @@
         return getInstanceOrNull();
     }
 
+    private static final int TETHERING_TIMEOUT_MS = 60_000;
+    private final Object mTetheringLock = new Object();
+
+    private TetheringManager getTetheringManager() {
+        synchronized (mTetheringLock) {
+            if (mTetheringManager != null) {
+                return mTetheringManager;
+            }
+            final long before = System.currentTimeMillis();
+            while ((mTetheringManager = (TetheringManager) mContext.getSystemService(
+                    Context.TETHERING_SERVICE)) == null) {
+                if (System.currentTimeMillis() - before > TETHERING_TIMEOUT_MS) {
+                    Log.e(TAG, "Timeout waiting tethering service not ready yet");
+                    throw new IllegalStateException("No tethering service yet");
+                }
+                SystemClock.sleep(100);
+            }
+
+            return mTetheringManager;
+        }
+    }
+
     /**
      * Get the set of tetherable, available interfaces.  This list is limited by
      * device configuration and current interface existence.
@@ -2351,11 +2374,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public String[] getTetherableIfaces() {
-        try {
-            return mService.getTetherableIfaces();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetherableIfaces();
     }
 
     /**
@@ -2368,11 +2387,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public String[] getTetheredIfaces() {
-        try {
-            return mService.getTetheredIfaces();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetheredIfaces();
     }
 
     /**
@@ -2391,11 +2406,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public String[] getTetheringErroredIfaces() {
-        try {
-            return mService.getTetheringErroredIfaces();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetheringErroredIfaces();
     }
 
     /**
@@ -2406,11 +2417,7 @@
      */
     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
     public String[] getTetheredDhcpRanges() {
-        try {
-            return mService.getTetheredDhcpRanges();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetheredDhcpRanges();
     }
 
     /**
@@ -2439,13 +2446,7 @@
      */
     @UnsupportedAppUsage
     public int tether(String iface) {
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "tether caller:" + pkgName);
-            return mService.tether(iface, pkgName);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().tether(iface);
     }
 
     /**
@@ -2468,13 +2469,7 @@
      */
     @UnsupportedAppUsage
     public int untether(String iface) {
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "untether caller:" + pkgName);
-            return mService.untether(iface, pkgName);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().untether(iface);
     }
 
     /**
@@ -2499,16 +2494,7 @@
     @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
             android.Manifest.permission.WRITE_SETTINGS})
     public boolean isTetheringSupported() {
-        String pkgName = mContext.getOpPackageName();
-        try {
-            return mService.isTetheringSupported(pkgName);
-        } catch (SecurityException e) {
-            // This API is not available to this caller, but for backward-compatibility
-            // this will just return false instead of throwing.
-            return false;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().isTetheringSupported();
     }
 
     /**
@@ -2577,14 +2563,7 @@
             }
         };
 
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "startTethering caller:" + pkgName);
-            mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Exception trying to start tethering.", e);
-            wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);
-        }
+        getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi);
     }
 
     /**
@@ -2600,13 +2579,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void stopTethering(int type) {
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "stopTethering caller:" + pkgName);
-            mService.stopTethering(type, pkgName);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        getTetheringManager().stopTethering(type);
     }
 
     /**
@@ -2628,10 +2601,6 @@
         public void onUpstreamChanged(@Nullable Network network) {}
     }
 
-    @GuardedBy("mTetheringEventCallbacks")
-    private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
-            mTetheringEventCallbacks = new ArrayMap<>();
-
     /**
      * Start listening to tethering change events. Any new added callback will receive the last
      * tethering status right away. If callback is registered when tethering has no upstream or
@@ -2649,27 +2618,7 @@
             @NonNull final OnTetheringEventCallback callback) {
         Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
 
-        synchronized (mTetheringEventCallbacks) {
-            Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
-                    "callback was already registered.");
-            ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
-                @Override
-                public void onUpstreamChanged(Network network) throws RemoteException {
-                    Binder.withCleanCallingIdentity(() ->
-                            executor.execute(() -> {
-                                callback.onUpstreamChanged(network);
-                            }));
-                }
-            };
-            try {
-                String pkgName = mContext.getOpPackageName();
-                Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
-                mService.registerTetheringEventCallback(remoteCallback, pkgName);
-                mTetheringEventCallbacks.put(callback, remoteCallback);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
+        getTetheringManager().registerTetheringEventCallback(executor, callback);
     }
 
     /**
@@ -2683,17 +2632,7 @@
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void unregisterTetheringEventCallback(
             @NonNull final OnTetheringEventCallback callback) {
-        synchronized (mTetheringEventCallbacks) {
-            ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
-            Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
-            try {
-                String pkgName = mContext.getOpPackageName();
-                Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
-                mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
+        getTetheringManager().unregisterTetheringEventCallback(callback);
     }
 
 
@@ -2710,11 +2649,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public String[] getTetherableUsbRegexs() {
-        try {
-            return mService.getTetherableUsbRegexs();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetherableUsbRegexs();
     }
 
     /**
@@ -2730,11 +2665,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public String[] getTetherableWifiRegexs() {
-        try {
-            return mService.getTetherableWifiRegexs();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetherableWifiRegexs();
     }
 
     /**
@@ -2750,11 +2681,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public String[] getTetherableBluetoothRegexs() {
-        try {
-            return mService.getTetherableBluetoothRegexs();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getTetherableBluetoothRegexs();
     }
 
     /**
@@ -2776,13 +2703,7 @@
      */
     @UnsupportedAppUsage
     public int setUsbTethering(boolean enable) {
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "setUsbTethering caller:" + pkgName);
-            return mService.setUsbTethering(enable, pkgName);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().setUsbTethering(enable);
     }
 
     /** {@hide} */
@@ -2830,11 +2751,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
     public int getLastTetherError(String iface) {
-        try {
-            return mService.getLastTetherError(iface);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return getTetheringManager().getLastTetherError(iface);
     }
 
     /** @hide */
@@ -2900,14 +2817,8 @@
             }
         };
 
-        try {
-            String pkgName = mContext.getOpPackageName();
-            Log.i(TAG, "getLatestTetheringEntitlementResult:" + pkgName);
-            mService.getLatestTetheringEntitlementResult(type, wrappedListener,
-                    showEntitlementUi, pkgName);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        getTetheringManager().requestLatestTetheringEntitlementResult(type, wrappedListener,
+                    showEntitlementUi);
     }
 
     /**
@@ -4332,6 +4243,7 @@
     public void factoryReset() {
         try {
             mService.factoryReset();
+            getTetheringManager().stopAllTethering();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 5f662f9..09c02ef 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.net.ConnectionInfo;
 import android.net.LinkProperties;
-import android.net.ITetheringEventCallback;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
@@ -78,41 +77,31 @@
 
     boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
 
-    int tether(String iface, String callerPkg);
-
-    int untether(String iface, String callerPkg);
-
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 29,
+            publicAlternatives = "Use {@code TetheringManager#getLastTetherError} as alternative")
     int getLastTetherError(String iface);
 
-    boolean isTetheringSupported(String callerPkg);
-
-    void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
-            String callerPkg);
-
-    void stopTethering(int type, String callerPkg);
-
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 29,
+            publicAlternatives = "Use {@code TetheringManager#getTetherableIfaces} as alternative")
     String[] getTetherableIfaces();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 29,
+            publicAlternatives = "Use {@code TetheringManager#getTetheredIfaces} as alternative")
     String[] getTetheredIfaces();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 29,
+            publicAlternatives = "Use {@code TetheringManager#getTetheringErroredIfaces} "
+            + "as Alternative")
     String[] getTetheringErroredIfaces();
 
-    String[] getTetheredDhcpRanges();
-
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 29,
+            publicAlternatives = "Use {@code TetheringManager#getTetherableUsbRegexs} as alternative")
     String[] getTetherableUsbRegexs();
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 29,
+            publicAlternatives = "Use {@code TetheringManager#getTetherableWifiRegexs} as alternative")
     String[] getTetherableWifiRegexs();
 
-    String[] getTetherableBluetoothRegexs();
-
-    int setUsbTethering(boolean enable, String callerPkg);
-
     @UnsupportedAppUsage(maxTargetSdk = 28)
     void reportInetCondition(int networkType, int percentage);
 
@@ -217,11 +206,5 @@
     boolean isCallerCurrentAlwaysOnVpnApp();
     boolean isCallerCurrentAlwaysOnVpnLockdownApp();
 
-    void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
-            boolean showEntitlementUi, String callerPkg);
-
-    void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
-    void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
-
     IBinder startOrGetTestNetworkService();
 }
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index c9a999c..1ae44e1 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -20,8 +20,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.google.android.collect.Sets;
-
 import java.util.HashSet;
 
 /**
@@ -32,7 +30,7 @@
 public class InterfaceConfiguration implements Parcelable {
     private String mHwAddr;
     private LinkAddress mAddr;
-    private HashSet<String> mFlags = Sets.newHashSet();
+    private HashSet<String> mFlags = new HashSet<>();
 
     // Must be kept in sync with constant in INetd.aidl
     private static final String FLAG_UP = "up";
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 8e18341..ed509cb 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -74,6 +74,8 @@
     private static final int MIN_MTU_V6 = 1280;
     private static final int MAX_MTU    = 10000;
 
+    private static final int INET6_ADDR_LENGTH = 16;
+
     // Stores the properties of links that are "stacked" above this link.
     // Indexed by interface name to allow modification and to prevent duplicates being added.
     private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
@@ -227,7 +229,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public @NonNull List<String> getAllInterfaceNames() {
         List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
         if (mIfaceName != null) interfaceNames.add(mIfaceName);
@@ -247,7 +249,7 @@
      * @return An unmodifiable {@link List} of {@link InetAddress} for this link.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public @NonNull List<InetAddress> getAddresses() {
         final List<InetAddress> addresses = new ArrayList<>();
         for (LinkAddress linkAddress : mLinkAddresses) {
@@ -342,8 +344,8 @@
      * Returns all the addresses on this link and all the links stacked above it.
      * @hide
      */
-    @UnsupportedAppUsage
-    public List<LinkAddress> getAllLinkAddresses() {
+    @SystemApi
+    public @NonNull List<LinkAddress> getAllLinkAddresses() {
         List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
         for (LinkProperties stacked: mStackedLinks.values()) {
             addresses.addAll(stacked.getAllLinkAddresses());
@@ -542,6 +544,7 @@
      * @return true if the PCSCF server was added, false otherwise.
      * @hide
      */
+    @SystemApi
     public boolean addPcscfServer(@NonNull InetAddress pcscfServer) {
         if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) {
             mPcscfs.add(pcscfServer);
@@ -729,7 +732,7 @@
      * Returns all the routes on this link and all the links stacked above it.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public @NonNull List<RouteInfo> getAllRoutes() {
         List<RouteInfo> routes = new ArrayList<>(mRoutes);
         for (LinkProperties stacked: mStackedLinks.values()) {
@@ -1025,7 +1028,7 @@
      * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public boolean hasIpv4DefaultRoute() {
         for (RouteInfo r : mRoutes) {
             if (r.isIPv4Default()) {
@@ -1082,7 +1085,7 @@
      * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public boolean hasIpv4DnsServer() {
         for (InetAddress ia : mDnses) {
             if (ia instanceof Inet4Address) {
@@ -1110,7 +1113,7 @@
      * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public boolean hasIpv6DnsServer() {
         for (InetAddress ia : mDnses) {
             if (ia instanceof Inet6Address) {
@@ -1626,20 +1629,11 @@
             dest.writeParcelable(linkAddress, flags);
         }
 
-        dest.writeInt(mDnses.size());
-        for (InetAddress d : mDnses) {
-            dest.writeByteArray(d.getAddress());
-        }
-        dest.writeInt(mValidatedPrivateDnses.size());
-        for (InetAddress d : mValidatedPrivateDnses) {
-            dest.writeByteArray(d.getAddress());
-        }
+        writeAddresses(dest, mDnses);
+        writeAddresses(dest, mValidatedPrivateDnses);
         dest.writeBoolean(mUsePrivateDns);
         dest.writeString(mPrivateDnsServerName);
-        dest.writeInt(mPcscfs.size());
-        for (InetAddress d : mPcscfs) {
-            dest.writeByteArray(d.getAddress());
-        }
+        writeAddresses(dest, mPcscfs);
         dest.writeString(mDomains);
         dest.writeInt(mMtu);
         dest.writeString(mTcpBufferSizes);
@@ -1662,6 +1656,35 @@
         dest.writeBoolean(mWakeOnLanSupported);
     }
 
+    private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
+        dest.writeInt(list.size());
+        for (InetAddress d : list) {
+            writeAddress(dest, d);
+        }
+    }
+
+    private static void writeAddress(@NonNull Parcel dest, @NonNull InetAddress addr) {
+        dest.writeByteArray(addr.getAddress());
+        if (addr instanceof Inet6Address) {
+            final Inet6Address v6Addr = (Inet6Address) addr;
+            final boolean hasScopeId = v6Addr.getScopeId() != 0;
+            dest.writeBoolean(hasScopeId);
+            if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
+        }
+    }
+
+    @NonNull
+    private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
+        final byte[] addr = p.createByteArray();
+        if (addr.length == INET6_ADDR_LENGTH) {
+            final boolean hasScopeId = p.readBoolean();
+            final int scopeId = hasScopeId ? p.readInt() : 0;
+            return Inet6Address.getByAddress(null /* host */, addr, scopeId);
+        }
+
+        return InetAddress.getByAddress(addr);
+    }
+
     /**
      * Implement the Parcelable interface.
      */
@@ -1681,14 +1704,13 @@
                 addressCount = in.readInt();
                 for (int i = 0; i < addressCount; i++) {
                     try {
-                        netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
+                        netProp.addDnsServer(readAddress(in));
                     } catch (UnknownHostException e) { }
                 }
                 addressCount = in.readInt();
                 for (int i = 0; i < addressCount; i++) {
                     try {
-                        netProp.addValidatedPrivateDnsServer(
-                                InetAddress.getByAddress(in.createByteArray()));
+                        netProp.addValidatedPrivateDnsServer(readAddress(in));
                     } catch (UnknownHostException e) { }
                 }
                 netProp.setUsePrivateDns(in.readBoolean());
@@ -1696,7 +1718,7 @@
                 addressCount = in.readInt();
                 for (int i = 0; i < addressCount; i++) {
                     try {
-                        netProp.addPcscfServer(InetAddress.getByAddress(in.createByteArray()));
+                        netProp.addPcscfServer(readAddress(in));
                     } catch (UnknownHostException e) { }
                 }
                 netProp.setDomains(in.readString());
diff --git a/core/java/android/net/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java
index ab4f627..68a3935 100644
--- a/core/java/android/net/MatchAllNetworkSpecifier.java
+++ b/core/java/android/net/MatchAllNetworkSpecifier.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,10 +29,12 @@
  *
  * @hide
  */
+@SystemApi
 public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable {
     /**
      * Utility method which verifies that the ns argument is not a MatchAllNetworkSpecifier and
      * throws an IllegalArgumentException if it is.
+     * @hide
      */
     public static void checkNotMatchAllNetworkSpecifier(NetworkSpecifier ns) {
         if (ns instanceof MatchAllNetworkSpecifier) {
@@ -38,6 +42,7 @@
         }
     }
 
+    /** @hide */
     public boolean satisfiedBy(NetworkSpecifier other) {
         /*
          * The method is called by a NetworkRequest to see if it is satisfied by a proposed
@@ -64,11 +69,11 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // Nothing to write.
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR =
+    public static final @NonNull Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR =
             new Parcelable.Creator<MatchAllNetworkSpecifier>() {
         public MatchAllNetworkSpecifier createFromParcel(Parcel in) {
             return new MatchAllNetworkSpecifier();
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 88877e2..421e61b 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -60,10 +60,6 @@
     // Set to true when private DNS is broken.
     private boolean mPrivateDnsBroken;
 
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage
     public NetworkCapabilities() {
         clearAll();
         mNetworkCapabilities = DEFAULT_CAPABILITIES;
@@ -78,7 +74,6 @@
     /**
      * Completely clears the contents of this object, removing even the capabilities that are set
      * by default when the object is constructed.
-     * @hide
      */
     public void clearAll() {
         mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
@@ -402,16 +397,15 @@
      * Adds the given capability to this {@code NetworkCapability} instance.
      * Multiple capabilities may be applied sequentially.  Note that when searching
      * for a network to satisfy a request, all capabilities requested must be satisfied.
-     * <p>
-     * If the given capability was previously added to the list of unwanted capabilities
-     * then the capability will also be removed from the list of unwanted capabilities.
      *
      * @param capability the capability to be added.
      * @return This NetworkCapabilities instance, to facilitate chaining.
-     * @hide
      */
-    @UnsupportedAppUsage
     public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) {
+        // If the given capability was previously added to the list of unwanted capabilities
+        // then the capability will also be removed from the list of unwanted capabilities.
+        // TODO: Consider adding unwanted capabilities to the public API and mention this
+        // in the documentation.
         checkValidCapability(capability);
         mNetworkCapabilities |= 1 << capability;
         mUnwantedNetworkCapabilities &= ~(1 << capability);  // remove from unwanted capability list
@@ -439,16 +433,13 @@
 
     /**
      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
-     * <p>
-     * Note that this method removes capabilities that were added via {@link #addCapability(int)},
-     * {@link #addUnwantedCapability(int)} or {@link #setCapabilities(int[], int[])} .
      *
      * @param capability the capability to be removed.
      * @return This NetworkCapabilities instance, to facilitate chaining.
-     * @hide
      */
-    @UnsupportedAppUsage
     public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) {
+        // Note that this method removes capabilities that were added via addCapability(int),
+        // addUnwantedCapability(int) or setCapabilities(int[], int[]).
         checkValidCapability(capability);
         final long mask = ~(1 << capability);
         mNetworkCapabilities &= mask;
@@ -460,7 +451,6 @@
      * Sets (or clears) the given capability on this {@link NetworkCapabilities}
      * instance.
      *
-     * @hide
      */
     public @NonNull NetworkCapabilities setCapability(@NetCapability int capability,
             boolean value) {
@@ -722,9 +712,7 @@
      *
      * @param transportType the transport type to be added.
      * @return This NetworkCapabilities instance, to facilitate chaining.
-     * @hide
      */
-    @UnsupportedAppUsage
     public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) {
         checkValidTransportType(transportType);
         mTransportTypes |= 1 << transportType;
@@ -863,7 +851,6 @@
      * fast backhauls and slow backhauls.
      *
      * @param upKbps the estimated first hop upstream (device to network) bandwidth.
-     * @hide
      */
     public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) {
         mLinkUpBandwidthKbps = upKbps;
@@ -893,7 +880,6 @@
      * fast backhauls and slow backhauls.
      *
      * @param downKbps the estimated first hop downstream (network to device) bandwidth.
-     * @hide
      */
     public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) {
         mLinkDownBandwidthKbps = downKbps;
@@ -952,9 +938,9 @@
      * @param networkSpecifier A concrete, parcelable framework class that extends
      *                         NetworkSpecifier.
      * @return This NetworkCapabilities instance, to facilitate chaining.
-     * @hide
      */
-    public @NonNull NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+    public @NonNull NetworkCapabilities setNetworkSpecifier(
+            @NonNull NetworkSpecifier networkSpecifier) {
         if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
             throw new IllegalStateException("Must have a single transport specified to use " +
                     "setNetworkSpecifier");
@@ -973,7 +959,8 @@
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
-    public @NonNull NetworkCapabilities setTransportInfo(TransportInfo transportInfo) {
+    @SystemApi
+    public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) {
         mTransportInfo = transportInfo;
         return this;
     }
@@ -983,9 +970,7 @@
      *
      * @return The optional {@link NetworkSpecifier} specifying the bearer specific network
      *         specifier or {@code null}. See {@link #setNetworkSpecifier}.
-     * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public @Nullable NetworkSpecifier getNetworkSpecifier() {
         return mNetworkSpecifier;
     }
@@ -1054,9 +1039,7 @@
      * effect when requesting a callback.
      *
      * @param signalStrength the bearer-specific signal strength.
-     * @hide
      */
-    @UnsupportedAppUsage
     public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) {
         mSignalStrength = signalStrength;
         return this;
@@ -1282,6 +1265,7 @@
      * Sets the SSID of this network.
      * @hide
      */
+    @SystemApi
     public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) {
         mSSID = ssid;
         return this;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 4270740..471b23e 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
@@ -461,6 +462,14 @@
         return networkCapabilities.hasTransport(transportType);
     }
 
+    /**
+     * @see Builder#setNetworkSpecifier(NetworkSpecifier)
+     */
+    @Nullable
+    public NetworkSpecifier getNetworkSpecifier() {
+        return networkCapabilities.getNetworkSpecifier();
+    }
+
     public String toString() {
         return "NetworkRequest [ " + type + " id=" + requestId +
                 (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
index 21dee55..83dbc63 100644
--- a/core/java/android/net/StringNetworkSpecifier.java
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -16,7 +16,8 @@
 
 package android.net;
 
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -26,18 +27,20 @@
 import java.util.Objects;
 
 /** @hide */
+@SystemApi
 public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
     /**
      * Arbitrary string used to pass (additional) information to the network factory.
      */
-    @UnsupportedAppUsage
+    @NonNull
     public final String specifier;
 
-    public StringNetworkSpecifier(String specifier) {
+    public StringNetworkSpecifier(@NonNull String specifier) {
         Preconditions.checkStringNotEmpty(specifier);
         this.specifier = specifier;
     }
 
+    /** @hide */
     @Override
     public boolean satisfiedBy(NetworkSpecifier other) {
         return equals(other);
@@ -65,11 +68,11 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(specifier);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<StringNetworkSpecifier> CREATOR =
+    public static final @NonNull Parcelable.Creator<StringNetworkSpecifier> CREATOR =
             new Parcelable.Creator<StringNetworkSpecifier>() {
         public StringNetworkSpecifier createFromParcel(Parcel in) {
             return new StringNetworkSpecifier(in.readString());
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 1c6a484..bf4884a 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -595,8 +596,15 @@
         return total;
     }
 
-    /** {@hide} */
-    public static long getTxPackets(String iface) {
+    /**
+     * Return the number of packets transmitted on the specified interface since
+     * device boot. Statistics are measured at the network layer, so both TCP and
+     * UDP usage are included.
+     *
+     * @param iface The name of the interface.
+     * @return The number of transmitted packets.
+     */
+    public static long getTxPackets(@NonNull String iface) {
         try {
             return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
         } catch (RemoteException e) {
@@ -604,8 +612,15 @@
         }
     }
 
-    /** {@hide} */
-    public static long getRxPackets(String iface) {
+    /**
+     * Return the number of packets received on the specified interface since
+     * device boot. Statistics are measured at the network layer, so both TCP
+     * and UDP usage are included.
+     *
+     * @param iface The name of the interface.
+     * @return The number of received packets.
+     */
+    public static long getRxPackets(@NonNull String iface) {
         try {
             return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
         } catch (RemoteException e) {
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index dd2c0d4..848b6d5 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -39,4 +39,5 @@
     boolean setPreferredService(in ComponentName service);
     boolean unsetPreferredService();
     boolean supportsAidPrefixRegistration();
+    ApduServiceInfo getPreferredPaymentService(int userHandle);
 }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index bc698f9..7ab984f 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -151,7 +151,7 @@
     public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
 
     /**
-     * Broadcast Action: Intent to notify an application that an transaction event has occurred
+     * Broadcast Action: Intent to notify an application that a transaction event has occurred
      * on the Secure Element.
      *
      * <p>This intent will only be sent if the application has requested permission for
@@ -164,6 +164,18 @@
             "android.nfc.action.TRANSACTION_DETECTED";
 
     /**
+     * Broadcast Action: Intent to notify if the preferred payment service changed.
+     *
+     * <p>This intent will only be sent to the application has requested permission for
+     * {@link android.Manifest.permission#NFC_PREFERRED_PAYMENT_INFO} and if the application
+     * has the necessary access to Secure Element which witnessed the particular event.
+     */
+    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PREFERRED_PAYMENT_CHANGED =
+            "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
+
+    /**
      * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
      * @hide
      */
@@ -231,6 +243,17 @@
      */
     public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
 
+    /**
+     * Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED}
+     * Indicates the condition when trigger this event.
+     */
+    public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON =
+            "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
+
+    public static final int PREFERRED_PAYMENT_LOADED = 1;
+    public static final int PREFERRED_PAYMENT_CHANGED = 2;
+    public static final int PREFERRED_PAYMENT_UPDATED = 3;
+
     public static final int STATE_OFF = 1;
     public static final int STATE_TURNING_ON = 2;
     public static final int STATE_ON = 3;
@@ -1410,7 +1433,7 @@
     /**
      * Enable foreground dispatch to the given Activity.
      *
-     * <p>This will give give priority to the foreground activity when
+     * <p>This will give priority to the foreground activity when
      * dispatching a discovered {@link Tag} to an application.
      *
      * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index aa93611..f1c74a6 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -17,6 +17,7 @@
 package android.nfc.cardemulation;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -657,6 +658,109 @@
     }
 
     /**
+     * Retrieves the registered AIDs for the preferred payment service.
+     *
+     * @return The list of AIDs registered for this category, or null if it couldn't be found.
+     */
+    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+    @Nullable
+    public List<String> getAidsForPreferredPaymentService() {
+        try {
+            ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+            return (serviceInfo != null ? serviceInfo.getAids() : null);
+        } catch (RemoteException e) {
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+            try {
+                ApduServiceInfo serviceInfo =
+                        sService.getPreferredPaymentService(mContext.getUserId());
+                return (serviceInfo != null ? serviceInfo.getAids() : null);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the route destination for the preferred payment service.
+     *
+     * @return The route destination secure element name of the preferred payment service.
+     *         HCE payment: "Host"
+     *         OffHost payment: prefix SIM or prefix eSE string.
+     *                          "OffHost" if the payment service does not specify secure element
+     *                          name.
+     */
+    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+    @Nullable
+    public String getRouteDestinationForPreferredPaymentService() {
+        try {
+            ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+            if (serviceInfo != null) {
+                if (!serviceInfo.isOnHost()) {
+                    return serviceInfo.getOffHostSecureElement() == null ?
+                            "OffHost" : serviceInfo.getOffHostSecureElement();
+                }
+                return "Host";
+            }
+            return null;
+        } catch (RemoteException e) {
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+            try {
+                ApduServiceInfo serviceInfo =
+                        sService.getPreferredPaymentService(mContext.getUserId());
+                if (serviceInfo != null) {
+                    if (!serviceInfo.isOnHost()) {
+                        return serviceInfo.getOffHostSecureElement() == null ?
+                                "Offhost" : serviceInfo.getOffHostSecureElement();
+                    }
+                    return "Host";
+                }
+                return null;
+
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Returns a user-visible description of the preferred payment service.
+     *
+     * @return the preferred payment service description
+     */
+    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
+    @Nullable
+    public String getDescriptionForPreferredPaymentService() {
+        try {
+            ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+            return (serviceInfo != null ? serviceInfo.getDescription() : null);
+        } catch (RemoteException e) {
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+            try {
+                ApduServiceInfo serviceInfo =
+                        sService.getPreferredPaymentService(mContext.getUserId());
+                return (serviceInfo != null ? serviceInfo.getDescription() : null);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+        }
+    }
+
+    /**
      * @hide
      */
     public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d016ec4..6efe1de4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2421,7 +2421,7 @@
 
     public static final int DATA_CONNECTION_OUT_OF_SERVICE = 0;
     public static final int DATA_CONNECTION_EMERGENCY_SERVICE =
-            TelephonyManager.MAX_NETWORK_TYPE + 1;
+            TelephonyManager.getAllNetworkTypes().length + 1;
     public static final int DATA_CONNECTION_OTHER = DATA_CONNECTION_EMERGENCY_SERVICE + 1;
 
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1eda4d9..1d25bc1 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -26,17 +26,17 @@
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.Context;
+import android.sysprop.TelephonyProperties;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.view.View;
 
-import com.android.internal.telephony.TelephonyProperties;
-
 import dalvik.system.VMRuntime;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * Information about the current build, extracted from system properties.
@@ -99,7 +99,8 @@
      * {@link #getRadioVersion} instead.
      */
     @Deprecated
-    public static final String RADIO = getString(TelephonyProperties.PROPERTY_BASEBAND_VERSION);
+    public static final String RADIO = joinListOrElse(
+            TelephonyProperties.baseband_version(), UNKNOWN);
 
     /** The name of the hardware (from the kernel command line or /proc). */
     public static final String HARDWARE = getString("ro.hardware");
@@ -1088,7 +1089,8 @@
         final String requiredBootloader = SystemProperties.get("ro.build.expect.bootloader");
         final String currentBootloader = SystemProperties.get("ro.bootloader");
         final String requiredRadio = SystemProperties.get("ro.build.expect.baseband");
-        final String currentRadio = SystemProperties.get("gsm.version.baseband");
+        final String currentRadio = joinListOrElse(
+                TelephonyProperties.baseband_version(), "");
 
         if (TextUtils.isEmpty(system)) {
             Slog.e(TAG, "Required ro.system.build.fingerprint is empty!");
@@ -1262,8 +1264,7 @@
      * null (if, for instance, the radio is not currently on).
      */
     public static String getRadioVersion() {
-        String propVal = SystemProperties.get(TelephonyProperties.PROPERTY_BASEBAND_VERSION);
-        return TextUtils.isEmpty(propVal) ? null : propVal;
+        return joinListOrElse(TelephonyProperties.baseband_version(), null);
     }
 
     @UnsupportedAppUsage
@@ -1288,4 +1289,10 @@
             return -1;
         }
     }
+
+    private static <T> String joinListOrElse(List<T> list, String defaultValue) {
+        String ret = list.stream().map(elem -> elem == null ? "" : elem.toString())
+                .collect(Collectors.joining(","));
+        return ret.isEmpty() ? defaultValue : ret;
+    }
 }
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 4ed7b17..d7ed055 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1874,8 +1874,14 @@
     public static final int MEMINFO_PAGE_TABLES = 13;
     /** @hide */
     public static final int MEMINFO_KERNEL_STACK = 14;
+    /**
+     * Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE (see KReclaimable field
+     * description in kernel documentation).
+     * @hide
+     */
+    public static final int MEMINFO_KRECLAIMABLE = 15;
     /** @hide */
-    public static final int MEMINFO_COUNT = 15;
+    public static final int MEMINFO_COUNT = 16;
 
     /**
      * Retrieves /proc/meminfo.  outSizes is filled with fields
@@ -2497,4 +2503,35 @@
      * @hide
      */
     public static native long getZramFreeKb();
+
+    /**
+     * Return memory size in kilobytes allocated for ION heaps.
+     *
+     * @hide
+     */
+    public static native long getIonHeapsSizeKb();
+
+    /**
+     * Return memory size in kilobytes allocated for ION pools.
+     *
+     * @hide
+     */
+    public static native long getIonPoolsSizeKb();
+
+    /**
+     * Return ION memory mapped by processes in kB.
+     * Notes:
+     *  * Warning: Might impact performance as it reads /proc/<pid>/maps files for each process.
+     *
+     * @hide
+     */
+    public static native long getIonMappedSizeKb();
+
+    /**
+     * Return whether virtually-mapped kernel stacks are enabled (CONFIG_VMAP_STACK).
+     * Note: caller needs config_gz read sepolicy permission
+     *
+     * @hide
+     */
+    public static native boolean isVmapStack();
 }
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 1456ff7..6b881fe 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -24,6 +24,7 @@
 {
     boolean hasVibrator();
     boolean hasAmplitudeControl();
+    boolean setAlwaysOnEffect(int id, in VibrationEffect effect, in AudioAttributes attributes);
     void vibrate(int uid, String opPkg, in VibrationEffect effect, in AudioAttributes attributes,
             String reason, IBinder token);
     void cancelVibrate(IBinder token);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index ab4d424..c618dbc 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -20,6 +20,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
@@ -605,6 +606,13 @@
     public static final String REBOOT_SAFE_MODE = "safemode";
 
     /**
+     * The 'reason' value used for rebooting userspace.
+     * @hide
+     */
+    @SystemApi
+    public static final String REBOOT_USERSPACE = "userspace";
+
+    /**
      * The 'reason' value used when rebooting the device without turning on the screen.
      * @hide
      */
@@ -1383,6 +1391,14 @@
     }
 
     /**
+     * Returns {@code true} if this device supports rebooting userspace.
+     */
+    // TODO(b/138605180): add link to documentation once it's ready.
+    public boolean isRebootingUserspaceSupported() {
+        return SystemProperties.getBoolean("ro.init.userspace_reboot.is_supported", false);
+    }
+
+    /**
      * Reboot the device.  Will not return if the reboot is successful.
      * <p>
      * Requires the {@link android.Manifest.permission#REBOOT} permission.
@@ -1390,8 +1406,14 @@
      *
      * @param reason code to pass to the kernel (e.g., "recovery") to
      *               request special boot modes, or null.
+     * @throws UnsupportedOperationException if userspace reboot was requested on a device that
+     *                                       doesn't support it.
      */
-    public void reboot(String reason) {
+    public void reboot(@Nullable String reason) {
+        if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
+            throw new UnsupportedOperationException(
+                    "Attempted userspace reboot on a device that doesn't support it");
+        }
         try {
             mService.reboot(false, reason, true);
         } catch (RemoteException e) {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 450bfae..1130f1d 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -519,11 +519,12 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
      * @param packageName null-ok the name of the package this process belongs to.
-     *
+     * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
+     *                             started.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws RuntimeException on fatal start failure
-     * 
+     *
      * {@hide}
      */
     public static ProcessStartResult start(@NonNull final String processClass,
@@ -538,11 +539,12 @@
                                            @Nullable String appDataDir,
                                            @Nullable String invokeWith,
                                            @Nullable String packageName,
+                                           @Nullable long[] disabledCompatChanges,
                                            @Nullable String[] zygoteArgs) {
         return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
-                    /*useUsapPool=*/ true, zygoteArgs);
+                    /*useUsapPool=*/ true, disabledCompatChanges, zygoteArgs);
     }
 
     /** @hide */
@@ -558,11 +560,12 @@
                                                   @Nullable String appDataDir,
                                                   @Nullable String invokeWith,
                                                   @Nullable String packageName,
+                                                  @Nullable long[] disabledCompatChanges,
                                                   @Nullable String[] zygoteArgs) {
         return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
-                    /*useUsapPool=*/ false, zygoteArgs);
+                    /*useUsapPool=*/ false, disabledCompatChanges, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 124b6c6..94671c8 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -90,6 +90,15 @@
         throw new RemoteException();
     }
 
+    public void registerClientCallback(String name, IBinder service, IClientCallback cb)
+            throws RemoteException {
+        throw new RemoteException();
+    }
+
+    public void tryUnregisterService(String name, IBinder service) throws RemoteException {
+        throw new RemoteException();
+    }
+
     /**
      * Same as mServiceManager but used by apps.
      *
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index a5188e7..fbd11ca 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -70,6 +70,20 @@
     }
 
     @Override
+    public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attributes) {
+        if (mService == null) {
+            Log.w(TAG, "Failed to set always-on effect; no vibrator service.");
+            return false;
+        }
+        try {
+            return mService.setAlwaysOnEffect(id, effect, attributes);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to set always-on effect.", e);
+        }
+        return false;
+    }
+
+    @Override
     public void vibrate(int uid, String opPkg, VibrationEffect effect,
             String reason, AudioAttributes attributes) {
         if (mService == null) {
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 1456a73..e132c11 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -21,6 +21,7 @@
 
 import com.android.internal.os.Zygote;
 
+import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 
 /**
@@ -107,12 +108,15 @@
     private static final int MAX_SECTION_NAME_LEN = 127;
 
     // Must be volatile to avoid word tearing.
+    // This is only kept in case any apps get this by reflection but do not
+    // check the return value for null.
     @UnsupportedAppUsage
     private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
 
     private static int sZygoteDebugFlags = 0;
 
     @UnsupportedAppUsage
+    @CriticalNative
     private static native long nativeGetEnabledTags();
     private static native void nativeSetAppTracingAllowed(boolean allowed);
     private static native void nativeSetTracingEnabled(boolean allowed);
@@ -128,47 +132,10 @@
     @FastNative
     private static native void nativeAsyncTraceEnd(long tag, String name, int cookie);
 
-    static {
-        // We configure two separate change callbacks, one in Trace.cpp and one here.  The
-        // native callback reads the tags from the system property, and this callback
-        // reads the value that the native code retrieved.  It's essential that the native
-        // callback executes first.
-        //
-        // The system provides ordering through a priority level.  Callbacks made through
-        // SystemProperties.addChangeCallback currently have a negative priority, while
-        // our native code is using a priority of zero.
-        SystemProperties.addChangeCallback(() -> {
-            cacheEnabledTags();
-            if ((sZygoteDebugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
-                traceCounter(TRACE_TAG_ALWAYS, "java_debuggable", 1);
-            }
-        });
-    }
-
     private Trace() {
     }
 
     /**
-     * Caches a copy of the enabled-tag bits.  The "master" copy is held by the native code,
-     * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
-     * <p>
-     * If the native code hasn't yet read the property, we will cause it to do one-time
-     * initialization.  We don't want to do this during class init, because this class is
-     * preloaded, so all apps would be stuck with whatever the zygote saw.  (The zygote
-     * doesn't see the system-property update broadcasts.)
-     * <p>
-     * We want to defer initialization until the first use by an app, post-zygote.
-     * <p>
-     * We're okay if multiple threads call here simultaneously -- the native state is
-     * synchronized, and sEnabledTags is volatile (prevents word tearing).
-     */
-    private static long cacheEnabledTags() {
-        long tags = nativeGetEnabledTags();
-        sEnabledTags = tags;
-        return tags;
-    }
-
-    /**
      * Returns true if a trace tag is enabled.
      *
      * @param traceTag The trace tag to check.
@@ -178,10 +145,7 @@
      */
     @UnsupportedAppUsage
     public static boolean isTagEnabled(long traceTag) {
-        long tags = sEnabledTags;
-        if (tags == TRACE_TAG_NOT_READY) {
-            tags = cacheEnabledTags();
-        }
+        long tags = nativeGetEnabledTags();
         return (tags & traceTag) != 0;
     }
 
@@ -210,10 +174,6 @@
     @UnsupportedAppUsage
     public static void setAppTracingAllowed(boolean allowed) {
         nativeSetAppTracingAllowed(allowed);
-
-        // Setting whether app tracing is allowed may change the tags, so we update the cached
-        // tags here.
-        cacheEnabledTags();
     }
 
     /**
@@ -227,10 +187,6 @@
     public static void setTracingEnabled(boolean enabled, int debugFlags) {
         nativeSetTracingEnabled(enabled);
         sZygoteDebugFlags = debugFlags;
-
-        // Setting whether tracing is enabled may change the tags, so we update the cached tags
-        // here.
-        cacheEnabledTags();
     }
 
     /**
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 28909c8..6456d72 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
@@ -152,6 +153,24 @@
     public abstract boolean hasAmplitudeControl();
 
     /**
+     * Configure an always-on haptics effect.
+     *
+     * @param id The board-specific always-on ID to configure.
+     * @param effect Vibration effect to assign to always-on id. Passing null will disable it.
+     * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
+     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *        vibrations associated with incoming calls. May only be null when effect is null.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
+    public boolean setAlwaysOnEffect(int id, @Nullable VibrationEffect effect,
+                                  @Nullable AudioAttributes attributes) {
+        Log.w(TAG, "Always-on effects aren't supported");
+        return false;
+    }
+
+    /**
      * Vibrate constantly for the specified period of time.
      *
      * @param milliseconds The number of milliseconds to vibrate.
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index 1c78b08..7af8f71 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.TestApi;
+import android.util.Slog;
 
 import java.util.Map;
 
@@ -28,6 +29,8 @@
 @TestApi
 public class VintfObject {
 
+    private static final String LOG_TAG = "VintfObject";
+
     /**
      * Slurps all device information (both manifests and both matrices)
      * and report them.
@@ -46,12 +49,33 @@
      * @param packageInfo a list of serialized form of HalManifest's /
      * CompatibilityMatri'ces (XML).
      * @return = 0 if success (compatible)
-     *         > 0 if incompatible
-     *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     *         &gt; 0 if incompatible
+     *         &lt; 0 if any error (mount partition fails, illformed XML, etc.)
+     *
+     * @deprecated Checking compatibility against an OTA package is no longer
+     * supported because the format of VINTF metadata in the OTA package may not
+     * be recognized by the current system.
+     *
+     * <p>
+     * <ul>
+     * <li>This function always returns 0 for non-empty {@code packageInfo}.
+     * </li>
+     * <li>This function returns the result of {@link #verifyWithoutAvb} for
+     * null or empty {@code packageInfo}.</li>
+     * </ul>
      *
      * @hide
      */
-    public static native int verify(String[] packageInfo);
+    @Deprecated
+    public static int verify(String[] packageInfo) {
+        if (packageInfo != null && packageInfo.length > 0) {
+            Slog.w(LOG_TAG, "VintfObject.verify() with non-empty packageInfo is deprecated. "
+                    + "Skipping compatibility checks for update package.");
+            return 0;
+        }
+        Slog.w(LOG_TAG, "VintfObject.verify() is deprecated. Call verifyWithoutAvb() instead.");
+        return verifyWithoutAvb();
+    }
 
     /**
      * Verify Vintf compatibility on the device without checking AVB
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 3a55aff..c2d3ecc 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -306,6 +306,8 @@
      * @param appDataDir null-ok the data directory of the app.
      * @param invokeWith null-ok the command to invoke with.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
+     *                             started.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      *
      * @return An object that describes the result of the attempt to start the process.
@@ -323,6 +325,7 @@
                                                   @Nullable String invokeWith,
                                                   @Nullable String packageName,
                                                   boolean useUsapPool,
+                                                  @Nullable long[] disabledCompatChanges,
                                                   @Nullable String[] zygoteArgs) {
         // TODO (chriswailes): Is there a better place to check this value?
         if (fetchUsapPoolEnabledPropWithMinInterval()) {
@@ -333,7 +336,7 @@
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
-                    packageName, useUsapPool, zygoteArgs);
+                    packageName, useUsapPool, disabledCompatChanges, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -534,6 +537,7 @@
      * @param startChildZygote Start a sub-zygote. This creates a new zygote process
      * that has its state cloned from this zygote process.
      * @param packageName null-ok the name of the package this process belongs to.
+     * @param disabledCompatChanges a list of disabled compat changes for the process being started.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -552,6 +556,7 @@
                                                       boolean startChildZygote,
                                                       @Nullable String packageName,
                                                       boolean useUsapPool,
+                                                      @Nullable long[] disabledCompatChanges,
                                                       @Nullable String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
         ArrayList<String> argsForZygote = new ArrayList<>();
@@ -623,6 +628,21 @@
             argsForZygote.add("--package-name=" + packageName);
         }
 
+        if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
+            final StringBuilder sb = new StringBuilder();
+            sb.append("--disabled-compat-changes=");
+
+            final int sz = disabledCompatChanges.length;
+            for (int i = 0; i < sz; i++) {
+                if (i != 0) {
+                    sb.append(',');
+                }
+                sb.append(disabledCompatChanges[i]);
+            }
+
+            argsForZygote.add(sb.toString());
+        }
+
         argsForZygote.add(processClass);
 
         if (extraArgs != null) {
@@ -1170,7 +1190,8 @@
                     gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                     abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
                     true /* startChildZygote */, null /* packageName */,
-                    false /* useUsapPool */, extraArgs);
+                    false /* useUsapPool */,
+                    null /* disabledCompatChanges */, extraArgs);
         } catch (ZygoteStartFailedEx ex) {
             throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index da4bd27..e348b5f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10402,35 +10402,37 @@
          */
         public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
 
-       /**
-        * Used to select TCP's default initial receiver window size in segments - defaults to a build config value
-        * @hide
-        */
-       public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
+        /**
+         * Used to select TCP's default initial receiver window size in segments - defaults to a
+         * build config value.
+         * @hide
+         */
+        public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
 
-       /**
-        * Used to disable Tethering on a device - defaults to true
-        * @hide
-        */
-       public static final String TETHER_SUPPORTED = "tether_supported";
+        /**
+         * Used to disable Tethering on a device - defaults to true.
+         * @hide
+         */
+        @SystemApi
+        public static final String TETHER_SUPPORTED = "tether_supported";
 
-       /**
-        * Used to require DUN APN on the device or not - defaults to a build config value
-        * which defaults to false
-        * @hide
-        */
-       public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
+        /**
+         * Used to require DUN APN on the device or not - defaults to a build config value
+         * which defaults to false.
+         * @hide
+         */
+        public static final String TETHER_DUN_REQUIRED = "tether_dun_required";
 
-       /**
-        * Used to hold a gservices-provisioned apn value for DUN.  If set, or the
-        * corresponding build config values are set it will override the APN DB
-        * values.
-        * Consists of a comma seperated list of strings:
-        * "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
-        * note that empty fields can be omitted: "name,apn,,,,,,,,,310,260,,DUN"
-        * @hide
-        */
-       public static final String TETHER_DUN_APN = "tether_dun_apn";
+        /**
+         * Used to hold a gservices-provisioned apn value for DUN.  If set, or the
+         * corresponding build config values are set it will override the APN DB
+         * values.
+         * Consists of a comma separated list of strings:
+         * "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
+         * note that empty fields can be omitted: "name,apn,,,,,,,,,310,260,,DUN"
+         * @hide
+         */
+        public static final String TETHER_DUN_APN = "tether_dun_apn";
 
         /**
          * Used to disable trying to talk to any available tethering offload HAL.
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index ebdde0a..13d167d 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -25,7 +25,6 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
-import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -1272,8 +1271,7 @@
              * Broadcast action: When SMS-MMS db is being created. If file-based encryption is
              * supported, this broadcast indicates creation of the db in credential-encrypted
              * storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if
-             * this is the initial create of the db. Requires
-             * {@link android.Manifest.permission#READ_SMS} to receive.
+             * this is the initial create of the db.
              *
              * @see #EXTRA_IS_INITIAL_CREATE
              *
@@ -1354,7 +1352,6 @@
                 for (int i = 0; i < pduCount; i++) {
                     byte[] pdu = (byte[]) messages[i];
                     msgs[i] = SmsMessage.createFromPdu(pdu, format);
-                    if (msgs[i] != null) msgs[i].setSubId(subId);
                 }
                 return msgs;
             }
@@ -3525,7 +3522,8 @@
          * can manage DPC-owned APNs.
          * @hide
          */
-        public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
+        @SystemApi
+        public static final @NonNull Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
 
         /**
          * The {@code content://} style URL to be called from Telephony to query APNs.
@@ -3834,6 +3832,13 @@
         public static final String USER_EDITABLE = "user_editable";
 
         /**
+         * Integer value denoting an invalid APN id
+         * @hide
+         */
+        @SystemApi
+        public static final int INVALID_APN_ID = -1;
+
+        /**
          * {@link #EDITED_STATUS APN edit status} indicates that this APN has not been edited or
          * fails to edit.
          * <p>Type: INTEGER </p>
@@ -4119,20 +4124,6 @@
         public static final String CID = "cid";
 
         /**
-         * Message code. <em>OBSOLETE: merged into SERIAL_NUMBER.</em>
-         * <P>Type: INTEGER</P>
-         * @hide
-         */
-        public static final String V1_MESSAGE_CODE = "message_code";
-
-        /**
-         * Message identifier. <em>OBSOLETE: renamed to SERVICE_CATEGORY.</em>
-         * <P>Type: INTEGER</P>
-         * @hide
-         */
-        public static final String V1_MESSAGE_IDENTIFIER = "message_id";
-
-        /**
          * Service category which represents the general topic of the message.
          * <p>
          * For GSM/UMTS: message identifier (see 3GPP TS 23.041 section 9.4.1.2.2)
@@ -4380,9 +4371,11 @@
          * ServiceState provider.
          * <p>
          * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
-         * {@link ServiceState} while your app is running.  You can also use a {@link JobService} to
+         * {@link ServiceState} while your app is running.
+         * You can also use a {@link android.app.job.JobService} to
          * ensure your app is notified of changes to the {@link Uri} even when it is not running.
-         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+         * Note, however, that using a {@link android.app.job.JobService}
+         * does not guarantee timely delivery of
          * updates to the {@link Uri}.
          *
          * @param subscriptionId the subscriptionId to receive updates on
@@ -4399,9 +4392,11 @@
          * ServiceState provider.
          * <p>
          * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
-         * {@link ServiceState} while your app is running.  You can also use a {@link JobService} to
+         * {@link ServiceState} while your app is running.  You can also use a
+         * {@link android.app.job.JobService} to
          * ensure your app is notified of changes to the {@link Uri} even when it is not running.
-         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+         * Note, however, that using a {@link android.app.job.JobService}
+         * does not guarantee timely delivery of
          * updates to the {@link Uri}.
          *
          * @param subscriptionId the subscriptionId to receive updates on
@@ -4479,7 +4474,7 @@
         /**
          * The current registered voice network operator name in long alphanumeric format.
          * <p>
-         * This is the same as {@link ServiceState#getVoiceOperatorAlphaLong()}.
+         * This is the same as {@link ServiceState#getOperatorAlphaLong()}.
          * @hide
          */
         public static final String VOICE_OPERATOR_ALPHA_LONG = "voice_operator_alpha_long";
@@ -4490,12 +4485,11 @@
          * In GSM/UMTS, short format can be up to 8 characters long. The current registered voice
          * network operator name in long alphanumeric format.
          * <p>
-         * This is the same as {@link ServiceState#getVoiceOperatorAlphaShort()}.
+         * This is the same as {@link ServiceState#getOperatorAlphaShort()}.
          * @hide
          */
         public static final String VOICE_OPERATOR_ALPHA_SHORT = "voice_operator_alpha_short";
 
-
         /**
          * The current registered operator numeric id.
          * <p>
@@ -4509,7 +4503,7 @@
         /**
          * The current registered data network operator name in long alphanumeric format.
          * <p>
-         * This is the same as {@link ServiceState#getDataOperatorAlphaLong()}.
+         * This is the same as {@link ServiceState#getOperatorAlphaLong()}.
          * @hide
          */
         public static final String DATA_OPERATOR_ALPHA_LONG = "data_operator_alpha_long";
@@ -4517,7 +4511,7 @@
         /**
          * The current registered data network operator name in short alphanumeric format.
          * <p>
-         * This is the same as {@link ServiceState#getDataOperatorAlphaShort()}.
+         * This is the same as {@link ServiceState#getOperatorAlphaShort()}.
          * @hide
          */
         public static final String DATA_OPERATOR_ALPHA_SHORT = "data_operator_alpha_short";
@@ -4525,7 +4519,7 @@
         /**
          * The current registered data network operator numeric id.
          * <p>
-         * This is the same as {@link ServiceState#getDataOperatorNumeric()}.
+         * This is the same as {@link ServiceState#getOperatorNumeric()}.
          * @hide
          */
         public static final String DATA_OPERATOR_NUMERIC = "data_operator_numeric";
@@ -4656,10 +4650,11 @@
          * <p>
          * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
          * carrier identity {@link TelephonyManager#getSimCarrierId()}
-         * while your app is running. You can also use a {@link JobService} to ensure your app
+         * while your app is running. You can also use a {@link android.app.job.JobService}
+         * to ensure your app
          * is notified of changes to the {@link Uri} even when it is not running.
-         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-         * updates to the {@link Uri}.
+         * Note, however, that using a {@link android.app.job.JobService} does not guarantee
+         * timely delivery of updates to the {@link Uri}.
          *
          * @param subscriptionId the subscriptionId to receive updates on
          * @return the Uri used to observe carrier identity changes
@@ -4677,10 +4672,11 @@
          * <p>
          * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
          * specific carrier identity {@link TelephonyManager#getSimSpecificCarrierId()}
-         * while your app is running. You can also use a {@link JobService} to ensure your app
+         * while your app is running. You can also use a {@link android.app.job.JobService}
+         * to ensure your app
          * is notified of changes to the {@link Uri} even when it is not running.
-         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-         * updates to the {@link Uri}.
+         * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+         * delivery of updates to the {@link Uri}.
          *
          * @param subscriptionId the subscriptionId to receive updates on
          * @return the Uri used to observe specific carrier identity changes
@@ -4811,4 +4807,23 @@
             public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all");
         }
     }
+
+    /**
+     * Contains SIM Information
+     * @hide
+     */
+    @SystemApi
+    public static final class SimInfo {
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private SimInfo() {}
+
+        /**
+         * The {@code content://} style URI for this provider.
+         */
+        @NonNull
+        public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+    }
 }
diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java
index 00060ab..d646e23 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/core/java/android/se/omapi/SEService.java
@@ -22,11 +22,14 @@
 
 package android.se.omapi;
 
+import android.app.ActivityThread;
 import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
@@ -140,6 +143,10 @@
             throw new NullPointerException("Arguments must not be null");
         }
 
+        if (!hasOMAPIReaders()) {
+            throw new UnsupportedOperationException("Device does not support any OMAPI reader");
+        }
+
         mContext = context;
         mSEListener.mListener = listener;
         mSEListener.mExecutor = executor;
@@ -270,4 +277,23 @@
             throw new IllegalStateException(e.getMessage());
         }
     }
+
+    /**
+     * Helper to check if this device support any OMAPI readers
+     */
+    private static boolean hasOMAPIReaders() {
+        IPackageManager pm = ActivityThread.getPackageManager();
+        if (pm == null) {
+            Log.e(TAG, "Cannot get package manager, assuming OMAPI readers supported");
+            return true;
+        }
+        try {
+            return pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_UICC, 0)
+                || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_ESE, 0)
+                || pm.hasSystemFeature(PackageManager.FEATURE_SE_OMAPI_SD, 0);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Package manager query failed, assuming OMAPI readers supported", e);
+            return true;
+        }
+    }
 }
diff --git a/core/java/android/service/carrier/ApnService.java b/core/java/android/service/carrier/ApnService.java
index 57e4b1b..0c12fd4 100644
--- a/core/java/android/service/carrier/ApnService.java
+++ b/core/java/android/service/carrier/ApnService.java
@@ -26,7 +26,7 @@
 import android.os.IBinder;
 import android.util.Log;
 
-import com.android.internal.telephony.IApnSourceService;
+import android.service.carrier.IApnSourceService;
 
 import java.util.List;
 
diff --git a/telephony/java/com/android/internal/telephony/IApnSourceService.aidl b/core/java/android/service/carrier/IApnSourceService.aidl
similarity index 93%
rename from telephony/java/com/android/internal/telephony/IApnSourceService.aidl
rename to core/java/android/service/carrier/IApnSourceService.aidl
index 34c9067..fadd2ff 100644
--- a/telephony/java/com/android/internal/telephony/IApnSourceService.aidl
+++ b/core/java/android/service/carrier/IApnSourceService.aidl
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.service.carrier;
 
 import android.content.ContentValues;
 
+/** @hide */
 interface IApnSourceService {
     /** Retreive APNs. */
     ContentValues[] getApns(int subId);
diff --git a/core/java/android/telephony/CellBroadcastIntents.java b/core/java/android/telephony/CellBroadcastIntents.java
new file mode 100644
index 0000000..8446253
--- /dev/null
+++ b/core/java/android/telephony/CellBroadcastIntents.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+
+/**
+ * A static helper class used to send Intents with prepopulated flags.
+ * <p>
+ * This is intended to be used by the CellBroadcastService and will throw a security exception if
+ * used from a UID besides the network stack UID.
+ *
+ * @hide
+ */
+@SystemApi
+public class CellBroadcastIntents {
+    private static final String LOG_TAG = "CellBroadcastIntents";
+
+    /**
+     * @hide
+     */
+    private CellBroadcastIntents() {
+    }
+
+    /**
+     * Returns an intent which can be received by background BroadcastReceivers. This is only
+     * intended to be used by the CellBroadcastService and will throw a security exception if called
+     * from another UID.
+     *
+     * @param context            The context from which to send the broadcast
+     * @param user               The user from which to send the broadcast
+     * @param intent             The Intent to broadcast; all receivers matching this Intent will
+     *                           receive the broadcast.
+     * @param receiverPermission String naming a permissions that a receiver must hold in order to
+     *                           receive your broadcast. If null, no permission is required.
+     * @param receiverAppOp      The app op associated with the broadcast. If null, no appOp is
+     *                           required. If both receiverAppOp and receiverPermission are
+     *                           non-null, a receiver must have both of them to receive the
+     *                           broadcast
+     * @param resultReceiver     Your own BroadcastReceiver to treat as the final receiver of the
+     *                           broadcast.
+     * @param scheduler          A custom Handler with which to schedule the resultReceiver
+     *                           callback; if null it will be scheduled in the Context's main
+     *                           thread.
+     * @param initialCode        An initial value for the result code.  Often Activity.RESULT_OK.
+     * @param initialData        An initial value for the result data.  Often null.
+     * @param initialExtras      An initial value for the result extras.  Often null.
+     */
+    public static void sendOrderedBroadcastForBackgroundReceivers(@NonNull Context context,
+            @Nullable UserHandle user, @NonNull Intent intent, @Nullable String receiverPermission,
+            @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver,
+            @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
+            @Nullable Bundle initialExtras) {
+        int status = context.checkCallingOrSelfPermission(
+                "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS");
+        if (status == PackageManager.PERMISSION_DENIED) {
+            throw new SecurityException(
+                    "Caller does not have permission to send broadcast for background receivers");
+        }
+        Intent backgroundIntent = new Intent(intent);
+        backgroundIntent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        if (user != null) {
+            context.createContextAsUser(user, 0).sendOrderedBroadcast(backgroundIntent,
+                    receiverPermission, receiverAppOp, resultReceiver, scheduler, initialCode,
+                    initialData, initialExtras);
+        } else {
+            context.sendOrderedBroadcast(backgroundIntent, receiverPermission,
+                    receiverAppOp, resultReceiver, scheduler, initialCode, initialData,
+                    initialExtras);
+        }
+    }
+}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index a65c8fd..146c1c3 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -35,8 +35,8 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
-import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.IPhoneStateListener;
 
 import dalvik.system.VMRuntime;
 
@@ -169,14 +169,6 @@
     public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
 
     /**
-     * Listen for changes to OTASP mode.
-     *
-     * @see #onOtaspChanged
-     * @hide
-     */
-    public static final int LISTEN_OTASP_CHANGED                            = 0x00000200;
-
-    /**
      * Listen for changes to observed cell info.
      *
      * @see #onCellInfoChanged
@@ -196,12 +188,13 @@
     /**
      * Listen for {@link PreciseDataConnectionState} on the data connection (cellular).
      *
-     * @see #onPreciseDataConnectionStateChanged
+     * <p>Requires permission {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
-     * @hide
+     * @see #onPreciseDataConnectionStateChanged
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    @SystemApi
+    @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
     public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE            = 0x00001000;
 
     /**
@@ -286,14 +279,6 @@
     public static final int LISTEN_USER_MOBILE_DATA_STATE                  = 0x00080000;
 
     /**
-     *  Listen for changes to the physical channel configuration.
-     *
-     *  @see #onPhysicalChannelConfigurationChanged
-     *  @hide
-     */
-    public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION          = 0x00100000;
-
-    /**
      *  Listen for changes to the phone capability.
      *
      *  @see #onPhoneCapabilityChanged
@@ -334,10 +319,8 @@
      * Listen for call disconnect causes which contains {@link DisconnectCause} and
      * {@link PreciseDisconnectCause}.
      *
-     * @hide
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    @SystemApi
     public static final int LISTEN_CALL_DISCONNECT_CAUSES                  = 0x02000000;
 
     /**
@@ -357,10 +340,8 @@
      * {@link android.telephony.ims.ImsReasonInfo}
      *
      * @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
-     * @hide
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    @SystemApi
     public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES              = 0x08000000;
 
     /**
@@ -632,29 +613,6 @@
         // default implementation empty
     }
 
-
-    /**
-     * The Over The Air Service Provisioning (OTASP) has changed on the registered subscription.
-     * Note, the registration subId comes from {@link TelephonyManager} object which registers
-     * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
-     * If this TelephonyManager object was created with
-     * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
-     * subId. Otherwise, this callback applies to
-     * {@link SubscriptionManager#getDefaultSubscriptionId()}.
-     *
-     * Requires the READ_PHONE_STATE permission.
-     * @param otaspMode is integer <code>OTASP_UNKNOWN=1<code>
-     *   means the value is currently unknown and the system should wait until
-     *   <code>OTASP_NEEDED=2<code> or <code>OTASP_NOT_NEEDED=3<code> is received before
-     *   making the decision to perform OTASP or not.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void onOtaspChanged(int otaspMode) {
-        // default implementation empty
-    }
-
     /**
      * Callback invoked when a observed cell info has changed or new cells have been added
      * or removed on the registered subscription.
@@ -699,10 +657,8 @@
      * @param disconnectCause {@link DisconnectCause}.
      * @param preciseDisconnectCause {@link PreciseDisconnectCause}.
      *
-     * @hide
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    @SystemApi
     public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
         // default implementation empty
     }
@@ -718,17 +674,16 @@
      *
      * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
      *
-     * @hide
      */
     @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    @SystemApi
     public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when data connection state changes with precise information
-     * on the registered subscription.
+     * Callback providing update about the default/internet data connection on the registered
+     * subscription.
+     *
      * Note, the registration subId comes from {@link TelephonyManager} object which registers
      * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
      * If this TelephonyManager object was created with
@@ -736,12 +691,13 @@
      * subId. Otherwise, this callback applies to
      * {@link SubscriptionManager#getDefaultSubscriptionId()}.
      *
-     * @param dataConnectionState {@link PreciseDataConnectionState}
+     * <p>Requires permission {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
-     * @hide
+     * @param dataConnectionState {@link PreciseDataConnectionState}
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    @SystemApi
+    @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
     public void onPreciseDataConnectionStateChanged(
             @NonNull PreciseDataConnectionState dataConnectionState) {
         // default implementation empty
@@ -831,24 +787,6 @@
     }
 
     /**
-     * Callback invoked when the current physical channel configuration has changed on the
-     * registered subscription.
-     * Note, the registration subId comes from {@link TelephonyManager} object which registers
-     * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
-     * If this TelephonyManager object was created with
-     * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
-     * subId. Otherwise, this callback applies to
-     * {@link SubscriptionManager#getDefaultSubscriptionId()}.
-     *
-     * @param configs List of the current {@link PhysicalChannelConfig}s
-     * @hide
-     */
-    public void onPhysicalChannelConfigurationChanged(
-            @NonNull List<PhysicalChannelConfig> configs) {
-        // default implementation empty
-    }
-
-    /**
      * Callback invoked when the current emergency number list has changed on the registered
      * subscription.
      * Note, the registration subId comes from {@link TelephonyManager} object which registers
@@ -965,8 +903,7 @@
      * subId. Otherwise, this callback applies to
      * {@link SubscriptionManager#getDefaultSubscriptionId()}.
      *
-     * Requires
-     * the READ_PRIVILEGED_PHONE_STATE permission.
+     * @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}
      * @param state the modem radio power state
      * @hide
      */
@@ -1068,11 +1005,21 @@
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
 
-            Binder.withCleanCallingIdentity(() -> mExecutor.execute(
-                    () -> {
-                        psl.onDataConnectionStateChanged(state, networkType);
-                        psl.onDataConnectionStateChanged(state);
-                    }));
+            if (state == TelephonyManager.DATA_DISCONNECTING
+                    && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+                Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+                        () -> {
+                            psl.onDataConnectionStateChanged(
+                                    TelephonyManager.DATA_CONNECTED, networkType);
+                            psl.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED);
+                        }));
+            } else {
+                Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+                        () -> {
+                            psl.onDataConnectionStateChanged(state, networkType);
+                            psl.onDataConnectionStateChanged(state);
+                        }));
+            }
         }
 
         public void onDataActivity(int direction) {
@@ -1091,14 +1038,6 @@
                     () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
         }
 
-        public void onOtaspChanged(int otaspMode) {
-            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
-            if (psl == null) return;
-
-            Binder.withCleanCallingIdentity(
-                    () -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode)));
-        }
-
         public void onCellInfoChanged(List<CellInfo> cellInfo) {
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
@@ -1194,15 +1133,6 @@
                     () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
         }
 
-        public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
-            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
-            if (psl == null) return;
-
-            Binder.withCleanCallingIdentity(
-                    () -> mExecutor.execute(
-                            () -> psl.onPhysicalChannelConfigurationChanged(configs)));
-        }
-
         public void onEmergencyNumberListChanged(Map emergencyNumberList) {
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
diff --git a/telephony/java/android/telephony/SubscriptionPlan.aidl b/core/java/android/telephony/SubscriptionPlan.aidl
similarity index 100%
rename from telephony/java/android/telephony/SubscriptionPlan.aidl
rename to core/java/android/telephony/SubscriptionPlan.aidl
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
similarity index 100%
rename from telephony/java/android/telephony/SubscriptionPlan.java
rename to core/java/android/telephony/SubscriptionPlan.java
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 308c8b3..c11a99d 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -21,19 +21,13 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.content.Context;
-import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.CallState;
 import android.telephony.Annotation.DataActivityType;
 import android.telephony.Annotation.DataFailureCause;
-import android.telephony.Annotation.DataState;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.Annotation.PreciseCallStates;
 import android.telephony.Annotation.RadioPowerState;
@@ -365,27 +359,18 @@
      * @param subId for which data connection state changed.
      * @param slotIndex for which data connections state changed. Can be derived from subId except
      * when subId is invalid.
-     * @param state latest data connection state, e.g,
-     * @param isDataConnectivityPossible indicates if data is allowed
-     * @param apn the APN {@link ApnSetting#getApnName()} of this data connection.
-     * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN.
-     * @param linkProperties {@link LinkProperties} associated with this data connection.
-     * @param networkCapabilities {@link NetworkCapabilities} associated with this data connection.
-     * @param networkType associated with this data connection.
-     * @param roaming {@code true} indicates in roaming, {@false} otherwise.
-     * @see TelephonyManager#DATA_DISCONNECTED
-     * @see TelephonyManager#isDataConnectivityPossible()
+     * @param apnType the APN type that triggered this update
+     * @param preciseState the PreciseDataConnectionState
      *
+     * @see android.telephony.PreciseDataConnection
+     * @see TelephonyManager#DATA_DISCONNECTED
      * @hide
      */
-    public void notifyDataConnectionForSubscriber(int slotIndex, int subId, @DataState int state,
-        boolean isDataConnectivityPossible,
-        @ApnType String apn, String apnType, LinkProperties linkProperties,
-        NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
+    public void notifyDataConnectionForSubscriber(int slotIndex, int subId,
+            String apnType, PreciseDataConnectionState preciseState) {
         try {
-            sRegistry.notifyDataConnectionForSubscriber(slotIndex, subId, state,
-                isDataConnectivityPossible,
-                apn, apnType, linkProperties, networkCapabilities, networkType, roaming);
+            sRegistry.notifyDataConnectionForSubscriber(
+                    slotIndex, subId, apnType, preciseState);
         } catch (RemoteException ex) {
             // system process is dead
         }
@@ -608,22 +593,6 @@
     }
 
     /**
-     * Notify over the air sim provisioning(OTASP) mode changed on certain subscription.
-     *
-     * @param subId for which otasp mode changed.
-     * @param otaspMode latest mode for OTASP e.g, OTASP needed.
-     *
-     * @hide
-     */
-    public void notifyOtaspChanged(int subId, int otaspMode) {
-        try {
-            sRegistry.notifyOtaspChanged(subId, otaspMode);
-        } catch (RemoteException ex) {
-            // system process is dead
-        }
-    }
-
-    /**
      * Notify precise call state changed on certain subscription, including foreground, background
      * and ringcall states.
      *
@@ -670,25 +639,6 @@
     }
 
     /**
-     * Notify data connection failed on certain subscription.
-     *
-     * @param subId for which data connection failed.
-     * @param slotIndex for which data conenction faled. Can be derived from subId except when subId
-     * is invalid.
-     * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. Note each data
-     * connection can support multiple anyTypes.
-     *
-     * @hide
-     */
-    public void notifyDataConnectionFailed(int subId, int slotIndex, String apnType) {
-        try {
-            sRegistry.notifyDataConnectionFailedForSubscriber(slotIndex, subId, apnType);
-        } catch (RemoteException ex) {
-            // system process is dead
-        }
-    }
-
-    /**
      * TODO change from bundle to CellLocation?
      * @hide
      */
diff --git a/core/java/android/text/AlteredCharSequence.java b/core/java/android/text/AlteredCharSequence.java
index 4cc71fd..971a47d 100644
--- a/core/java/android/text/AlteredCharSequence.java
+++ b/core/java/android/text/AlteredCharSequence.java
@@ -16,12 +16,14 @@
 
 package android.text;
 
-// XXX should this really be in the public API at all?
 /**
  * An AlteredCharSequence is a CharSequence that is largely mirrored from
  * another CharSequence, except that a specified range of characters are
  * mirrored from a different char array instead.
+ *
+ * @deprecated The functionality this class offers is easily implemented outside the framework.
  */
+@Deprecated
 public class AlteredCharSequence
 implements CharSequence, GetChars
 {
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index e94b800..90625183 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -56,8 +56,12 @@
     public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
     public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
     /**
-     * This constant is actually the length of 364 days, not of a year!
+     * @deprecated Not all years have the same number of days, and this constant is actually the
+     * length of 364 days. Please use other date/time constructs such as
+     * {@link java.util.concurrent.TimeUnit}, {@link java.util.Calendar} or
+     * {@link java.time.Duration} instead.
      */
+    @Deprecated
     public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
 
     // The following FORMAT_* symbols are used for specifying the format of
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java
new file mode 100644
index 0000000..6ac7696
--- /dev/null
+++ b/core/java/android/util/CloseGuard.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.annotation.NonNull;
+
+/**
+ * CloseGuard is a mechanism for flagging implicit finalizer cleanup of
+ * resources that should have been cleaned up by explicit close
+ * methods (aka "explicit termination methods" in Effective Java).
+ * <p>
+ * A simple example: <pre>   {@code
+ *   class Foo {
+ *
+ *       private final CloseGuard guard = CloseGuard.get();
+ *
+ *       ...
+ *
+ *       public Foo() {
+ *           ...;
+ *           guard.open("cleanup");
+ *       }
+ *
+ *       public void cleanup() {
+ *          guard.close();
+ *          ...;
+ *          if (Build.VERSION.SDK_INT >= 28) {
+ *              Reference.reachabilityFence(this);
+ *          }
+ *          // For full correctness in the absence of a close() call, other methods may also need
+ *          // reachabilityFence() calls.
+ *       }
+ *
+ *       protected void finalize() throws Throwable {
+ *           try {
+ *               // Note that guard could be null if the constructor threw.
+ *               if (guard != null) {
+ *                   guard.warnIfOpen();
+ *               }
+ *               cleanup();
+ *           } finally {
+ *               super.finalize();
+ *           }
+ *       }
+ *   }
+ * }</pre>
+ *
+ * In usage where the resource to be explicitly cleaned up is
+ * allocated after object construction, CloseGuard protection can
+ * be deferred. For example: <pre>   {@code
+ *   class Bar {
+ *
+ *       private final CloseGuard guard = CloseGuard.get();
+ *
+ *       ...
+ *
+ *       public Bar() {
+ *           ...;
+ *       }
+ *
+ *       public void connect() {
+ *          ...;
+ *          guard.open("cleanup");
+ *       }
+ *
+ *       public void cleanup() {
+ *          guard.close();
+ *          ...;
+ *          if (Build.VERSION.SDK_INT >= 28) {
+ *              Reference.reachabilityFence(this);
+ *          }
+ *          // For full correctness in the absence of a close() call, other methods may also need
+ *          // reachabilityFence() calls.
+ *       }
+ *
+ *       protected void finalize() throws Throwable {
+ *           try {
+ *               // Note that guard could be null if the constructor threw.
+ *               if (guard != null) {
+ *                   guard.warnIfOpen();
+ *               }
+ *               cleanup();
+ *           } finally {
+ *               super.finalize();
+ *           }
+ *       }
+ *   }
+ * }</pre>
+ *
+ * When used in a constructor, calls to {@code open} should occur at
+ * the end of the constructor since an exception that would cause
+ * abrupt termination of the constructor will mean that the user will
+ * not have a reference to the object to cleanup explicitly. When used
+ * in a method, the call to {@code open} should occur just after
+ * resource acquisition.
+ */
+public final class CloseGuard {
+    private final dalvik.system.CloseGuard mImpl;
+
+    /**
+     * Constructs a new CloseGuard instance.
+     * {@link #open(String)} can be used to set up the instance to warn on failure to close.
+     */
+    public CloseGuard() {
+        mImpl = dalvik.system.CloseGuard.get();
+    }
+
+    /**
+     * Initializes the instance with a warning that the caller should have explicitly called the
+     * {@code closeMethodName} method instead of relying on finalization.
+     *
+     * @param closeMethodName non-null name of explicit termination method. Printed by warnIfOpen.
+     * @throws NullPointerException if closeMethodName is null.
+     */
+    public void open(@NonNull String closeMethodName) {
+        mImpl.open(closeMethodName);
+    }
+
+    /** Marks this CloseGuard instance as closed to avoid warnings on finalization. */
+    public void close() {
+        mImpl.close();
+    }
+
+    /**
+     * Logs a warning if the caller did not properly cleanup by calling an explicit close method
+     * before finalization.
+     */
+    public void warnIfOpen() {
+        mImpl.warnIfOpen();
+    }
+}
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index 8b5659b..0203430 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -17,9 +17,11 @@
 package android.util;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.SystemClock;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.time.Instant;
 import java.time.LocalDateTime;
 import java.util.ArrayDeque;
 import java.util.Deque;
@@ -33,10 +35,22 @@
     private final Deque<String> mLog;
     private final int mMaxLines;
 
+    /**
+     * {@code true} to use log timestamps expressed in local date/time, {@code false} to use log
+     * timestamped expressed with the elapsed realtime clock and UTC system clock. {@code false} is
+     * useful when logging behavior that modifies device time zone or system clock.
+     */
+    private final boolean mUseLocalTimestamps;
+
     @UnsupportedAppUsage
     public LocalLog(int maxLines) {
+        this(maxLines, true /* useLocalTimestamps */);
+    }
+
+    public LocalLog(int maxLines, boolean useLocalTimestamps) {
         mMaxLines = Math.max(0, maxLines);
         mLog = new ArrayDeque<>(mMaxLines);
+        mUseLocalTimestamps = useLocalTimestamps;
     }
 
     @UnsupportedAppUsage
@@ -44,7 +58,14 @@
         if (mMaxLines <= 0) {
             return;
         }
-        append(String.format("%s - %s", LocalDateTime.now(), msg));
+        final String logLine;
+        if (mUseLocalTimestamps) {
+            logLine = String.format("%s - %s", LocalDateTime.now(), msg);
+        } else {
+            logLine = String.format(
+                    "%s / %s - %s", SystemClock.elapsedRealtime(), Instant.now(), msg);
+        }
+        append(logLine);
     }
 
     private synchronized void append(String logLine) {
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index f7077bb..ae9966b 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -224,12 +224,25 @@
     /**
      * Write an event to stats log using the raw format.
      *
-     * @param buffer    The encoded buffer of data to write..
+     * @param buffer    The encoded buffer of data to write.
      * @param size      The number of bytes from the buffer to write.
      * @hide
      */
+    // TODO(b/144935988): Mark deprecated.
     @SystemApi
-    public static native void writeRaw(@NonNull byte[] buffer, int size);
+    public static void writeRaw(@NonNull byte[] buffer, int size) {
+        // TODO(b/144935988): make this no-op once clients have migrated to StatsEvent.
+        writeImpl(buffer, size, 0);
+    }
+
+    /**
+     * Write an event to stats log using the raw format.
+     *
+     * @param buffer    The encoded buffer of data to write.
+     * @param size      The number of bytes from the buffer to write.
+     * @param atomId    The id of the atom to which the event belongs.
+     */
+    private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId);
 
     private static void enforceDumpCallingPermission(Context context) {
         context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission.");
diff --git a/telephony/java/com/android/ims/internal/uce/common/CapInfo.aidl b/core/java/com/android/ims/internal/uce/common/CapInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/CapInfo.aidl
rename to core/java/com/android/ims/internal/uce/common/CapInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/common/CapInfo.java b/core/java/com/android/ims/internal/uce/common/CapInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/CapInfo.java
rename to core/java/com/android/ims/internal/uce/common/CapInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.aidl b/core/java/com/android/ims/internal/uce/common/StatusCode.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/StatusCode.aidl
rename to core/java/com/android/ims/internal/uce/common/StatusCode.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java b/core/java/com/android/ims/internal/uce/common/StatusCode.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/StatusCode.java
rename to core/java/com/android/ims/internal/uce/common/StatusCode.java
diff --git a/telephony/java/com/android/ims/internal/uce/common/UceLong.aidl b/core/java/com/android/ims/internal/uce/common/UceLong.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/UceLong.aidl
rename to core/java/com/android/ims/internal/uce/common/UceLong.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/common/UceLong.java b/core/java/com/android/ims/internal/uce/common/UceLong.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/common/UceLong.java
rename to core/java/com/android/ims/internal/uce/common/UceLong.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl b/core/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
rename to core/java/com/android/ims/internal/uce/options/IOptionsListener.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl b/core/java/com/android/ims/internal/uce/options/IOptionsService.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl
rename to core/java/com/android/ims/internal/uce/options/IOptionsService.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsCapInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
rename to core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdId.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
rename to core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl
rename to core/java/com/android/ims/internal/uce/options/OptionsSipResponse.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
rename to core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl b/core/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
rename to core/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl b/core/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
rename to core/java/com/android/ims/internal/uce/presence/IPresenceService.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCapInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.aidl b/core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java b/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
rename to core/java/com/android/ims/internal/uce/presence/PresCmdId.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCmdStatus.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
rename to core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
rename to core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresResInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresResInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresResInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresServiceInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresSipResponse.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
rename to core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
rename to core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresTupleInfo.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
rename to core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl b/core/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
rename to core/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl b/core/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
rename to core/java/com/android/ims/internal/uce/uceservice/IUceService.aidl
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java b/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
rename to core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
diff --git a/telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java b/core/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java
similarity index 100%
rename from telephony/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java
rename to core/java/com/android/ims/internal/uce/uceservice/UceServiceBase.java
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 427474c..3bd0fd2 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -61,6 +61,7 @@
 import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
+import android.telephony.ModemActivityInfo.TransmitPower;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -5266,7 +5267,7 @@
         // Unknown is included in DATA_CONNECTION_OTHER.
         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
         if (hasData) {
-            if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
+            if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
                 bin = dataType;
             } else {
                 switch (serviceType) {
@@ -10978,7 +10979,7 @@
     }
 
     private ModemActivityInfo mLastModemActivityInfo =
-            new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
+            new ModemActivityInfo(0, 0, 0, new int[0], 0);
 
     private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) {
         if (activityInfo == null) {
@@ -10986,15 +10987,14 @@
         }
         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
-            txTimeMs[i] = activityInfo.getTxTimeMillis()[i]
-                    - mLastModemActivityInfo.getTxTimeMillis()[i];
+            txTimeMs[i] = activityInfo.getTransmitPowerInfo().get(i).getTimeInMillis()
+                    - mLastModemActivityInfo.getTransmitPowerInfo().get(i).getTimeInMillis();
         }
         ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(),
                 activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(),
                 activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(),
                 txTimeMs,
-                activityInfo.getRxTimeMillis() - mLastModemActivityInfo.getRxTimeMillis(),
-                activityInfo.getEnergyUsed() - mLastModemActivityInfo.getEnergyUsed());
+                activityInfo.getReceiveTimeMillis() - mLastModemActivityInfo.getReceiveTimeMillis());
         mLastModemActivityInfo = activityInfo;
         return deltaInfo;
     }
@@ -11037,10 +11037,11 @@
                         deltaInfo.getIdleTimeMillis());
                 mModemActivity.getSleepTimeCounter().addCountLocked(
                         deltaInfo.getSleepTimeMillis());
-                mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getRxTimeMillis());
+                mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis());
                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                     mModemActivity.getTxTimeCounters()[lvl]
-                        .addCountLocked(deltaInfo.getTxTimeMillis()[lvl]);
+                        .addCountLocked(deltaInfo.getTransmitPowerInfo()
+                            .get(lvl).getTimeInMillis());
                 }
 
                 // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -11052,13 +11053,14 @@
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_SLEEP)
                             + deltaInfo.getIdleTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE)
-                            + deltaInfo.getRxTimeMillis() *
+                            + deltaInfo.getReceiveTimeMillis() *
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
-                    int[] txTimeMs = deltaInfo.getTxTimeMillis();
-                    for (int i = 0; i < Math.min(txTimeMs.length,
-                            CellSignalStrength.getNumSignalStrengthLevels()); i++) {
-                        energyUsed += txTimeMs[i] * mPowerProfile.getAveragePower(
-                                PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
+
+                    List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo();
+                    for (int i = 0; i < Math.min(txPowerInfo.size(),
+                            SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
+                        energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile
+                            .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
                     }
 
                     // We store the power drain as mAms.
@@ -11147,15 +11149,16 @@
                             ControllerActivityCounterImpl activityCounter =
                                     u.getOrCreateModemControllerActivityLocked();
                             if (totalRxPackets > 0 && entry.rxPackets > 0) {
-                                final long rxMs = (entry.rxPackets * deltaInfo.getRxTimeMillis())
-                                        / totalRxPackets;
+                                final long rxMs = (entry.rxPackets
+                                    * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
                                 activityCounter.getRxTimeCounter().addCountLocked(rxMs);
                             }
 
                             if (totalTxPackets > 0 && entry.txPackets > 0) {
                                 for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                                     long txMs =
-                                            entry.txPackets * deltaInfo.getTxTimeMillis()[lvl];
+                                            entry.txPackets * deltaInfo.getTransmitPowerInfo()
+                                                .get(lvl).getTimeInMillis();
                                     txMs /= totalTxPackets;
                                     activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
                                 }
@@ -11186,15 +11189,16 @@
         if (activityInfo == null) {
             return;
         }
-        int[] txTimeMs = activityInfo.getTxTimeMillis();
-        if (txTimeMs == null || txTimeMs.length != ModemActivityInfo.TX_POWER_LEVELS) {
+        List<TransmitPower> txPowerInfo = activityInfo.getTransmitPowerInfo();
+        if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) {
             return;
         }
         final long elapsedRealtime = mClocks.elapsedRealtime();
         final long uptime = mClocks.uptimeMillis();
         int levelMaxTimeSpent = 0;
-        for (int i = 1; i < txTimeMs.length; i++) {
-            if (txTimeMs[i] > txTimeMs[levelMaxTimeSpent]) {
+        for (int i = 1; i < txPowerInfo.size(); i++) {
+            if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent)
+                .getTimeInMillis()) {
                 levelMaxTimeSpent = i;
             }
         }
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index fd3cd42..fa823c4 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -30,8 +30,10 @@
 import android.os.Trace;
 import android.util.Log;
 import android.util.Slog;
+
 import com.android.internal.logging.AndroidConfig;
 import com.android.server.NetworkManagementSocketTagger;
+
 import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
 
@@ -365,8 +367,8 @@
         if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
     }
 
-    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
-            ClassLoader classLoader) {
+    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
+            String[] argv, ClassLoader classLoader) {
         // If the application calls System.exit(), terminate the process
         // immediately without running any shutdown hooks.  It is not possible to
         // shutdown an Android application gracefully.  Among other things, the
@@ -374,10 +376,8 @@
         // leftover running threads to crash before the process actually exits.
         nativeSetExitWithoutCleanup(true);
 
-        // We want to be fairly aggressive about heap utilization, to avoid
-        // holding on to a lot of memory that isn't needed.
-        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
         VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
+        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
 
         final Arguments args = new Arguments(argv);
 
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index f0e7796..790d7f7 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -23,16 +23,18 @@
 import android.system.OsConstants;
 import android.system.StructCapUserData;
 import android.system.StructCapUserHeader;
-import android.util.TimingsTraceLog;
 import android.util.Slog;
+import android.util.TimingsTraceLog;
+
 import dalvik.system.VMRuntime;
+
+import libcore.io.IoUtils;
+
 import java.io.DataOutputStream;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
 
-import libcore.io.IoUtils;
-
 /**
  * Startup class for the wrapper process.
  * @hide
@@ -166,10 +168,10 @@
             System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2);
             argv = removedArgs;
         }
-
         // Perform the same initialization that would happen after the Zygote forks.
         Zygote.nativePreApplicationInit();
-        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+        return RuntimeInit.applicationInit(targetSdkVersion, /*disabledCompatChanges*/ null,
+                argv, classLoader);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 00ab45e..33adec1 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -642,6 +642,7 @@
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
             return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
+                                         args.mDisabledCompatChanges,
                                          args.mRemainingArgs,
                                          null /* classLoader */);
         } finally {
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index fc55ccf..3915ba2 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -210,6 +210,12 @@
     int mHiddenApiAccessStatslogSampleRate = -1;
 
     /**
+     * A set of disabled app compatibility changes for the running app. From
+     * --disabled-compat-changes.
+     */
+    long[] mDisabledCompatChanges = null;
+
+    /**
      * Constructs instance and parses args
      *
      * @param args zygote command-line args
@@ -416,6 +422,16 @@
                 mUsapPoolStatusSpecified = true;
                 mUsapPoolEnabled = Boolean.parseBoolean(arg.substring(arg.indexOf('=') + 1));
                 expectRuntimeArgs = false;
+            } else if (arg.startsWith("--disabled-compat-changes=")) {
+                if (mDisabledCompatChanges != null) {
+                    throw new IllegalArgumentException("Duplicate arg specified");
+                }
+                final String[] params = arg.substring(arg.indexOf('=') + 1).split(",");
+                final int length = params.length;
+                mDisabledCompatChanges = new long[length];
+                for (int i = 0; i < length; i++) {
+                    mDisabledCompatChanges[i] = Long.parseLong(params[i]);
+                }
             } else {
                 break;
             }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b15e1ef..4c37591 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -502,6 +502,7 @@
         } else {
             if (!isZygote) {
                 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
+                        parsedArgs.mDisabledCompatChanges,
                         parsedArgs.mRemainingArgs, null /* classLoader */);
             } else {
                 return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 93e6102..7b77a92 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -547,6 +547,7 @@
              * Pass the remaining arguments to SystemServer.
              */
             return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
+                    parsedArgs.mDisabledCompatChanges,
                     parsedArgs.mRemainingArgs, cl);
         }
 
@@ -972,14 +973,16 @@
      *
      * Current recognized args:
      * <ul>
-     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
+     * <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
      * </ul>
      *
      * @param targetSdkVersion target SDK version
-     * @param argv arg strings
+     * @param disabledCompatChanges set of disabled compat changes for the process (all others
+     *                              are enabled)
+     * @param argv             arg strings
      */
-    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
-            ClassLoader classLoader) {
+    public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
+            String[] argv, ClassLoader classLoader) {
         if (RuntimeInit.DEBUG) {
             Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
         }
@@ -989,7 +992,8 @@
 
         RuntimeInit.commonInit();
         ZygoteInit.nativeZygoteInit();
-        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
+                classLoader);
     }
 
     /**
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 084a3cc..cb67309 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -21,7 +21,6 @@
 import android.telephony.CellInfo;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
@@ -44,8 +43,6 @@
     void onDataConnectionStateChanged(int state, int networkType);
     void onDataActivity(int direction);
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
-    void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs);
-    void onOtaspChanged(in int otaspMode);
     void onCellInfoChanged(in List<CellInfo> cellInfo);
     void onPreciseCallStateChanged(in PreciseCallState callState);
     void onPreciseDataConnectionStateChanged(in PreciseDataConnectionState dataConnectionState);
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index d7a7af1..b1bc2d9 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -25,6 +25,7 @@
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
+import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.emergency.EmergencyNumber;
@@ -55,25 +56,16 @@
     @UnsupportedAppUsage(maxTargetSdk = 28)
     void notifyDataActivity(int state);
     void notifyDataActivityForSubscriber(in int subId, int state);
-    void notifyDataConnection(int state, boolean isDataConnectivityPossible,
-            String apn, String apnType, in LinkProperties linkProperties,
-            in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
-    void notifyDataConnectionForSubscriber(int phoneId, int subId, int state,
-            boolean isDataConnectivityPossible,
-            String apn, String apnType, in LinkProperties linkProperties,
-            in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
+    void notifyDataConnectionForSubscriber(
+            int phoneId, int subId, String apnType, in PreciseDataConnectionState preciseState);
     @UnsupportedAppUsage
     void notifyDataConnectionFailed(String apnType);
     void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType);
     @UnsupportedAppUsage(maxTargetSdk = 28)
     void notifyCellLocation(in Bundle cellLocation);
     void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
-    @UnsupportedAppUsage(maxTargetSdk = 28)
-    void notifyOtaspChanged(in int subId, in int otaspMode);
     @UnsupportedAppUsage
     void notifyCellInfo(in List<CellInfo> cellInfo);
-    void notifyPhysicalChannelConfigurationForSubscriber(in int phoneId, in int subId,
-            in List<PhysicalChannelConfig> configs);
     void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
             int foregroundCallState, int backgroundCallState);
     void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index c1d129b..580c2fa 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -91,7 +91,15 @@
      * that are mapped in to processes.
      */
     public long getCachedSizeKb() {
-        return mInfos[Debug.MEMINFO_BUFFERS] + mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE]
+        long kReclaimable = mInfos[Debug.MEMINFO_KRECLAIMABLE];
+
+        // Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE and ION pools.
+        // Fall back to using MEMINFO_SLAB_RECLAIMABLE in case of older kernels that do
+        // not include KReclaimable meminfo field.
+        if (kReclaimable == 0) {
+            kReclaimable = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE];
+        }
+        return mInfos[Debug.MEMINFO_BUFFERS] + kReclaimable
                 + mInfos[Debug.MEMINFO_CACHED] - mInfos[Debug.MEMINFO_MAPPED];
     }
 
@@ -99,9 +107,12 @@
      * Amount of RAM that is in use by the kernel for actual allocations.
      */
     public long getKernelUsedSizeKb() {
-        return mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
-                + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES]
-                + mInfos[Debug.MEMINFO_KERNEL_STACK];
+        long size = mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
+                + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES];
+        if (!Debug.isVmapStack()) {
+            size += mInfos[Debug.MEMINFO_KERNEL_STACK];
+        }
+        return size;
     }
 
     public long getSwapTotalSizeKb() {
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 731b93c..3fff5c2 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -102,6 +102,24 @@
     }
 
     /**
+     * Ensures that an string reference passed as a parameter to the calling method is not empty.
+     *
+     * @param string an string reference
+     * @param messageTemplate a printf-style message template to use if the check fails; will be
+     *     converted to a string using {@link String#format(String, Object...)}
+     * @param messageArgs arguments for {@code messageTemplate}
+     * @return the string reference that was validated
+     * @throws IllegalArgumentException if {@code string} is empty
+     */
+    public static @NonNull <T extends CharSequence> T checkStringNotEmpty(
+            final T string, final String messageTemplate, final Object... messageArgs) {
+        if (TextUtils.isEmpty(string)) {
+            throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+        }
+        return string;
+    }
+
+    /**
      * Ensures that an object reference passed as a parameter to the calling
      * method is not null.
      *
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 7cd3e95..4c399f8 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Environment;
+import android.os.FileUtils;
 import android.os.Process;
 import android.os.SystemProperties;
 import android.os.storage.StorageManager;
@@ -417,6 +418,19 @@
                 Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
         readPermissions(Environment.buildPath(
                 Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
+
+        // Skip loading configuration from apex if it is not a system process.
+        if (!isSystemProcess()) {
+            return;
+        }
+        // Read configuration of libs from apex module.
+        // TODO(146407631): Use a solid way to filter apex module folders?
+        for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
+            if (f.isFile() || f.getPath().contains("@")) {
+                continue;
+            }
+            readPermissions(Environment.buildPath(f, "etc", "permissions"), ALLOW_LIBS);
+        }
     }
 
     void readPermissions(File libraryDir, int permissionFlag) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 49c029c..f68fd57 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -233,6 +233,7 @@
 
     static_libs: [
         "libasync_safe",
+        "libdmabufinfo",
         "libgif",
         "libseccomp_policy",
         "libgrallocusage",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2383731..8e0e1c6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -693,6 +693,7 @@
     char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
     std::string fingerprintBuf;
     char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
+    char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];
     char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
 
     // Read if we are using the profile configuration, do this at the start since the last ART args
@@ -884,6 +885,14 @@
                          "default");
     }
 
+    // Only pass an explicit opaque-jni-ids to apps forked from zygote
+    if (zygote) {
+      parseRuntimeOption("dalvik.vm.opaque-jni-ids",
+                        opaqueJniIds,
+                        "-Xopaque-jni-ids:",
+                        "swapable");
+    }
+
     parseRuntimeOption("dalvik.vm.lockprof.threshold",
                        lockProfThresholdBuf,
                        "-Xlockprofthreshold:");
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 99b5f85..a3c455b 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -38,6 +38,7 @@
 #define ENCODING_AC4            17
 #define ENCODING_E_AC3_JOC      18
 #define ENCODING_DOLBY_MAT      19
+#define ENCODING_OPUS           20
 
 #define ENCODING_INVALID    0
 #define ENCODING_DEFAULT    1
@@ -88,6 +89,8 @@
         return AUDIO_FORMAT_DEFAULT;
     case ENCODING_DOLBY_MAT:
         return AUDIO_FORMAT_MAT;
+    case ENCODING_OPUS:
+        return AUDIO_FORMAT_OPUS;
     default:
         return AUDIO_FORMAT_INVALID;
     }
@@ -142,6 +145,8 @@
     case AUDIO_FORMAT_MAT_2_0:
     case AUDIO_FORMAT_MAT_2_1:
         return ENCODING_DOLBY_MAT;
+    case AUDIO_FORMAT_OPUS:
+        return ENCODING_OPUS;
     case AUDIO_FORMAT_DEFAULT:
         return ENCODING_DEFAULT;
     default:
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 81957f5..52ce54b 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -43,12 +43,14 @@
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
 #include "jni.h"
+#include <dmabufinfo/dmabufinfo.h>
 #include <meminfo/procmeminfo.h>
 #include <meminfo/sysmeminfo.h>
 #include <memtrack/memtrack.h>
 #include <memunreachable/memunreachable.h>
 #include <android-base/strings.h>
 #include "android_os_Debug.h"
+#include <vintf/VintfObject.h>
 
 namespace android
 {
@@ -560,6 +562,7 @@
     MEMINFO_VMALLOC_USED,
     MEMINFO_PAGE_TABLES,
     MEMINFO_KERNEL_STACK,
+    MEMINFO_KERNEL_RECLAIMABLE,
     MEMINFO_COUNT
 };
 
@@ -778,6 +781,76 @@
     return zramFreeKb;
 }
 
+static jlong android_os_Debug_getIonHeapsSizeKb(JNIEnv* env, jobject clazz) {
+    jlong heapsSizeKb = 0;
+    uint64_t size;
+
+    if (meminfo::ReadIonHeapsSizeKb(&size)) {
+        heapsSizeKb = size;
+    }
+
+    return heapsSizeKb;
+}
+
+static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) {
+    jlong poolsSizeKb = 0;
+    uint64_t size;
+
+    if (meminfo::ReadIonPoolsSizeKb(&size)) {
+        poolsSizeKb = size;
+    }
+
+    return poolsSizeKb;
+}
+
+static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) {
+    jlong ionPss = 0;
+    std::vector<dmabufinfo::DmaBuffer> dmabufs;
+
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir);
+    if (!dir) {
+        LOG(ERROR) << "Failed to open /proc directory";
+        return false;
+    }
+
+    struct dirent* dent;
+    while ((dent = readdir(dir.get()))) {
+        if (dent->d_type != DT_DIR) continue;
+
+        int pid = atoi(dent->d_name);
+        if (pid == 0) {
+            continue;
+        }
+
+        if (!AppendDmaBufInfo(pid, &dmabufs, false)) {
+            LOG(ERROR) << "Failed to read maps for pid " << pid;
+        }
+    }
+
+    for (const dmabufinfo::DmaBuffer& buf : dmabufs) {
+        ionPss += buf.size() / 1024;
+    }
+
+    return ionPss;
+}
+
+static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz)
+{
+    static enum {
+        CONFIG_UNKNOWN,
+        CONFIG_SET,
+        CONFIG_UNSET,
+    } cfg_state = CONFIG_UNKNOWN;
+
+    if (cfg_state == CONFIG_UNKNOWN) {
+        const std::map<std::string, std::string> configs =
+            vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs();
+        std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK");
+        cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET;
+    }
+    return cfg_state == CONFIG_SET;
+}
+
 /*
  * JNI registration.
  */
@@ -821,6 +894,14 @@
             (void*)android_os_Debug_getUnreachableMemory },
     { "getZramFreeKb", "()J",
             (void*)android_os_Debug_getFreeZramKb },
+    { "getIonHeapsSizeKb", "()J",
+            (void*)android_os_Debug_getIonHeapsSizeKb },
+    { "getIonPoolsSizeKb", "()J",
+            (void*)android_os_Debug_getIonPoolsSizeKb },
+    { "getIonMappedSizeKb", "()J",
+            (void*)android_os_Debug_getIonMappedSizeKb },
+    { "isVmapStack", "()Z",
+            (void*)android_os_Debug_isVmapStack },
 };
 
 int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index bd82bd9..0f7611a 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -50,10 +50,6 @@
     callback(buffer.data());
 }
 
-static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv*, jclass) {
-    return atrace_get_enabled_tags();
-}
-
 static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass,
         jlong tag, jstring nameStr, jlong value) {
     withString(env, nameStr, [tag, value](char* str) {
@@ -96,9 +92,6 @@
 
 static const JNINativeMethod gTraceMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeGetEnabledTags",
-            "()J",
-            (void*)android_os_Trace_nativeGetEnabledTags },
     { "nativeSetAppTracingAllowed",
             "(Z)V",
             (void*)android_os_Trace_nativeSetAppTracingAllowed },
@@ -123,6 +116,11 @@
     { "nativeAsyncTraceEnd",
             "(JLjava/lang/String;I)V",
             (void*)android_os_Trace_nativeAsyncTraceEnd },
+
+    // ----------- @CriticalNative  ----------------
+    { "nativeGetEnabledTags",
+            "()J",
+            (void*)atrace_get_enabled_tags },
 };
 
 int register_android_os_Trace(JNIEnv* env) {
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index ee11b61..25ffbab 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -96,28 +96,9 @@
     return toJavaStringArray(env, cStrings);
 }
 
-static jint android_os_VintfObject_verify(JNIEnv* env, jclass, jobjectArray packageInfo) {
-    std::vector<std::string> cPackageInfo;
-    if (packageInfo) {
-        size_t count = env->GetArrayLength(packageInfo);
-        cPackageInfo.resize(count);
-        for (size_t i = 0; i < count; ++i) {
-            jstring element = (jstring)env->GetObjectArrayElement(packageInfo, i);
-            const char *cString = env->GetStringUTFChars(element, NULL /* isCopy */);
-            cPackageInfo[i] = cString;
-            env->ReleaseStringUTFChars(element, cString);
-        }
-    }
-    std::string error;
-    int32_t status = VintfObject::CheckCompatibility(cPackageInfo, &error);
-    if (status)
-        LOG(WARNING) << "VintfObject.verify() returns " << status << ": " << error;
-    return status;
-}
-
 static jint android_os_VintfObject_verifyWithoutAvb(JNIEnv* env, jclass) {
     std::string error;
-    int32_t status = VintfObject::CheckCompatibility({}, &error,
+    int32_t status = VintfObject::GetInstance()->checkCompatibility(&error,
             ::android::vintf::CheckFlags::DISABLE_AVB_CHECK);
     if (status)
         LOG(WARNING) << "VintfObject.verifyWithoutAvb() returns " << status << ": " << error;
@@ -170,7 +151,6 @@
 
 static const JNINativeMethod gVintfObjectMethods[] = {
     {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report},
-    {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
     {"verifyWithoutAvb", "()I", (void*)android_os_VintfObject_verifyWithoutAvb},
     {"getHalNamesAndVersions", "()[Ljava/lang/String;", (void*)android_os_VintfObject_getHalNamesAndVersions},
     {"getSepolicyVersion", "()Ljava/lang/String;", (void*)android_os_VintfObject_getSepolicyVersion},
diff --git a/core/jni/android_util_StatsLog.cpp b/core/jni/android_util_StatsLog.cpp
index e749d34..9225fc2 100644
--- a/core/jni/android_util_StatsLog.cpp
+++ b/core/jni/android_util_StatsLog.cpp
@@ -18,18 +18,17 @@
 #define LOG_TAG "StatsLog_println"
 
 #include <assert.h>
-#include <cutils/properties.h>
 
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include "utils/misc.h"
 #include "core_jni_helpers.h"
-#include "stats_event_list.h"
+#include "stats_buffer_writer.h"
 
 namespace android {
 
-static void android_util_StatsLog_writeRaw(JNIEnv* env, jobject clazz, jbyteArray buf, jint size)
-{
+static void android_util_StatsLog_write(JNIEnv* env, jobject clazz, jbyteArray buf, jint size,
+        jint atomId) {
     if (buf == NULL) {
         return;
     }
@@ -42,13 +41,8 @@
     if (bufferArray == NULL) {
         return;
     }
-    const uint32_t statsEventTag = 1937006964;
-    struct iovec vec[2];
-    vec[0].iov_base = (void*) &statsEventTag;
-    vec[0].iov_len = sizeof(statsEventTag);
-    vec[1].iov_base = (void*) bufferArray;
-    vec[1].iov_len = size;
-    write_to_statsd(vec, 2);
+
+    write_buffer_to_statsd((void*) bufferArray, size, atomId);
 
     env->ReleaseByteArrayElements(buf, bufferArray, 0);
 }
@@ -58,7 +52,7 @@
  */
 static const JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "writeRaw", "([BI)V", (void*) android_util_StatsLog_writeRaw },
+    { "writeImpl", "([BII)V", (void*) android_util_StatsLog_write },
 };
 
 int register_android_util_StatsLog(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index a3f5311..58fd9c0 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -74,6 +74,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <bionic/malloc.h>
+#include <bionic/page.h>
 #include <cutils/fs.h>
 #include <cutils/multiuser.h>
 #include <private/android_filesystem_config.h>
@@ -1673,9 +1674,14 @@
 static int disable_execute_only(struct dl_phdr_info *info, size_t size, void *data) {
   // Search for any execute-only segments and mark them read+execute.
   for (int i = 0; i < info->dlpi_phnum; i++) {
-    if ((info->dlpi_phdr[i].p_type == PT_LOAD) && (info->dlpi_phdr[i].p_flags == PF_X)) {
-      mprotect(reinterpret_cast<void*>(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr),
-              info->dlpi_phdr[i].p_memsz, PROT_READ | PROT_EXEC);
+    const auto& phdr = info->dlpi_phdr[i];
+    if ((phdr.p_type == PT_LOAD) && (phdr.p_flags == PF_X)) {
+      auto addr = reinterpret_cast<void*>(info->dlpi_addr + PAGE_START(phdr.p_vaddr));
+      size_t len = PAGE_OFFSET(phdr.p_vaddr) + phdr.p_memsz;
+      if (mprotect(addr, len, PROT_READ | PROT_EXEC) == -1) {
+        ALOGE("mprotect(%p, %zu, PROT_READ | PROT_EXEC) failed: %m", addr, len);
+        return -1;
+      }
     }
   }
   // Return non-zero to exit dl_iterate_phdr.
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index fd6984b..c8e901e 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -37,6 +37,9 @@
   "/apex/com.android.ipsec/javalib/ike.jar",
   "/apex/com.android.media/javalib/updatable-media.jar",
   "/apex/com.android.sdkext/javalib/framework-sdkext.jar",
+  "/apex/com.android.telephony/javalib/telephony-common.jar",
+  "/apex/com.android.telephony/javalib/ims-common.jar",
+  "/apex/com.android.tethering/javalib/framework-tethering.jar",
   "/dev/null",
   "/dev/socket/zygote",
   "/dev/socket/zygote_secondary",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 68f3c2e..6d71c50 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -306,6 +306,7 @@
     <protected-broadcast android:name="android.net.nsd.STATE_CHANGED" />
 
     <protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" />
+    <protected-broadcast android:name="android.nfc.action.PREFERRED_PAYMENT_CHANGED" />
     <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
     <protected-broadcast android:name="com.android.nfc.action.LLCP_UP" />
     <protected-broadcast android:name="com.android.nfc.action.LLCP_DOWN" />
@@ -633,10 +634,9 @@
 
     <protected-broadcast android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY" />
 
-    <!-- NETWORK_SET_TIME / NETWORK_SET_TIMEZONE moved from com.android.phone to system server.
-         They should ultimately be removed. -->
-    <protected-broadcast android:name="android.intent.action.NETWORK_SET_TIME" />
-    <protected-broadcast android:name="android.intent.action.NETWORK_SET_TIMEZONE" />
+    <!-- NETWORK_SET_TIME moved from com.android.phone to system server. It should ultimately be
+         removed. -->
+    <protected-broadcast android:name="android.telephony.action.NETWORK_SET_TIME" />
 
     <!-- For tether entitlement recheck-->
     <protected-broadcast
@@ -1768,6 +1768,14 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+      android:protectionLevel="normal" />
+
+    <!-- Allows applications to receive NFC preferred payment service information.
+         <p>Protection level: normal
+    -->
+    <permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO"
+        android:description="@string/permdesc_preferredPaymentInfo"
+        android:label="@string/permlab_preferredPaymentInfo"
         android:protectionLevel="normal" />
 
     <!-- @deprecated This permission used to allow too broad access to sensitive methods and all its
@@ -1869,6 +1877,13 @@
         android:description="@string/permdesc_vibrate"
         android:protectionLevel="normal|instant" />
 
+    <!-- Allows access to the vibrator always-on settings.
+         <p>Protection level: signature
+         @hide
+    -->
+    <permission android:name="android.permission.VIBRATE_ALWAYS_ON"
+        android:protectionLevel="signature" />
+
     <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
          from dimming.
          <p>Protection level: normal
@@ -2031,6 +2046,11 @@
     <!-- =========================================== -->
     <eat-comment />
 
+    <!-- @SystemApi Allows granting runtime permissions to telephony related components.
+         @hide Used internally. -->
+    <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
+        android:protectionLevel="signature|telephony" />
+
     <!-- Allows modification of the telephony state - power on, mmi, etc.
          Does not include placing calls.
          <p>Not for use by third-party applications. -->
@@ -2504,17 +2524,17 @@
     <permission android:name="android.permission.READ_WALLPAPER_INTERNAL"
         android:protectionLevel="signature|privileged" />
 
-    <!-- ============================================ -->
-    <!-- Permissions for changing the system clock -->
-    <!-- ============================================ -->
+    <!-- ===================================================== -->
+    <!-- Permissions for changing the system clock / time zone -->
+    <!-- ===================================================== -->
     <eat-comment />
 
-    <!-- Allows applications to set the system time.
-    <p>Not for use by third-party applications. -->
+    <!-- Allows applications to set the system time directly.
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_TIME"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows applications to set the system time zone.
+    <!-- Allows applications to set the system time zone directly.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.SET_TIME_ZONE"
@@ -2522,6 +2542,20 @@
         android:description="@string/permdesc_setTimeZone"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows telephony to suggest the time / time zone.
+         <p>Not for use by third-party applications.
+         @hide
+     -->
+    <permission android:name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"
+        android:protectionLevel="signature|telephony" />
+
+    <!-- Allows applications like settings to suggest the user's manually chosen time / time zone.
+         <p>Not for use by third-party applications.
+         @hide
+    -->
+    <permission android:name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"
+        android:protectionLevel="signature" />
+
     <!-- ==================================================== -->
     <!-- Permissions related to changing status bar   -->
     <!-- ==================================================== -->
diff --git a/core/res/res/values-mcc510-mnc08/config.xml b/core/res/res/values-mcc510-mnc08/config.xml
index 7b27554..58fbb9e 100644
--- a/core/res/res/values-mcc510-mnc08/config.xml
+++ b/core/res/res/values-mcc510-mnc08/config.xml
@@ -23,4 +23,6 @@
          and "333" is used for other purpose -->
     <string-array translatable="false" name="config_callBarringMMI">
     </string-array>
+    <string-array translatable="false" name="config_callBarringMMI_for_ims">
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc510-mnc89/config.xml b/core/res/res/values-mcc510-mnc89/config.xml
index 82efecf..c262247 100644
--- a/core/res/res/values-mcc510-mnc89/config.xml
+++ b/core/res/res/values-mcc510-mnc89/config.xml
@@ -23,4 +23,6 @@
          and "333" is used for other purpose -->
     <string-array translatable="false" name="config_callBarringMMI">
     </string-array>
+    <string-array translatable="false" name="config_callBarringMMI_for_ims">
+    </string-array>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d5e263f..a404e2e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2797,6 +2797,18 @@
         <item>353</item>
     </string-array>
 
+    <!-- Ims supported call barring MMI code -->
+    <string-array translatable="false" name="config_callBarringMMI_for_ims">
+        <item>33</item>
+        <item>331</item>
+        <item>332</item>
+        <item>35</item>
+        <item>351</item>
+        <item>330</item>
+        <item>333</item>
+        <item>353</item>
+    </string-array>
+
     <!-- Override the default detection behavior for the framework method
          android.view.ViewConfiguration#hasPermanentMenuKey().
          Valid settings are:
@@ -3008,16 +3020,9 @@
     <!-- Whether to use voip audio mode for ims call -->
     <bool name="config_use_voip_mode_for_ims">false</bool>
 
-    <!-- ImsService package name to bind to by default. If none is specified in an overlay, an
-         empty string is passed in -->
-    <string name="config_ims_package"/>
-
     <!-- String array containing numbers that shouldn't be logged. Country-specific. -->
     <string-array name="unloggable_phone_numbers" />
 
-    <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
-    <bool name="config_dynamic_bind_ims">false</bool>
-
     <!-- Cellular data service package name to bind to by default. If none is specified in an overlay, an
          empty string is passed in -->
     <string name="config_wwan_data_service_package" translatable="false">com.android.phone</string>
@@ -3533,6 +3538,9 @@
     <!-- emergency call number for the emergency affordance -->
     <string name="config_emergency_call_number" translatable="false">112</string>
 
+    <!-- Package name that provides Emergency Dialer -->
+    <string name="config_emergency_dialer_package">com.android.phone</string>
+
     <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
          affordances-->
     <integer-array name="config_emergency_mcc_codes" translatable="false">
@@ -3677,14 +3685,13 @@
      -->
     <string name="config_defaultWellbeingPackage" translatable="false"></string>
 
-
     <!-- The package name for the system telephony apps.
          This package must be trusted, as it will be granted with permissions with special telephony
          protection level. Note, framework by default support multiple telephony apps, each package
          name is separated by comma.
          Example: "com.android.phone,com.android.stk,com.android.providers.telephony"
      -->
-    <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string>
+    <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons,com.android.cellbroadcastservice"</string>
 
     <!-- The component name for the default system attention service.
          This service must be trusted, as it can be activated without explicit consent of the user.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fdfedea..4aa44fc 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1392,6 +1392,12 @@
       connections with paired devices.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_preferredPaymentInfo">Preferred NFC Payment Service Information</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_preferredPaymentInfo">Allows the app to get preferred nfc payment service information like
+      registered aids and route destination.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_nfc">control Near Field Communication</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_nfc">Allows the app to communicate
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 18c68c3..2507787 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -295,8 +295,6 @@
   <java-symbol type="bool" name="config_enableBurnInProtection" />
   <java-symbol type="bool" name="config_hotswapCapable" />
   <java-symbol type="bool" name="config_mms_content_disposition_support" />
-  <java-symbol type="string" name="config_ims_package" />
-  <java-symbol type="bool" name="config_dynamic_bind_ims" />
   <java-symbol type="string" name="config_wwan_network_service_package" />
   <java-symbol type="string" name="config_wlan_network_service_package" />
   <java-symbol type="string" name="config_wwan_network_service_class" />
@@ -1313,6 +1311,7 @@
   <java-symbol type="array" name="config_cdma_dun_supported_types" />
   <java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
   <java-symbol type="array" name="config_callBarringMMI" />
+  <java-symbol type="array" name="config_callBarringMMI_for_ims" />
   <java-symbol type="array" name="config_globalActionsList" />
   <java-symbol type="array" name="config_telephonyEuiccDeviceCapabilities" />
   <java-symbol type="array" name="config_telephonyHardware" />
@@ -3154,6 +3153,7 @@
 
   <java-symbol type="string" name="global_action_emergency" />
   <java-symbol type="string" name="config_emergency_call_number" />
+  <java-symbol type="string" name="config_emergency_dialer_package" />
   <java-symbol type="array" name="config_emergency_mcc_codes" />
 
   <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index b906d84..ed613c3 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -176,14 +176,12 @@
                         mDevice.setPin(mPin);
                         break;
                     case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
-                        mDevice.setPasskey(mPasskey);
                         break;
                     case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
                     case BluetoothDevice.PAIRING_VARIANT_CONSENT:
                         mDevice.setPairingConfirmation(true);
                         break;
                     case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
-                        mDevice.setRemoteOutOfBandData();
                         break;
                 }
             } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 1670d49..4d4f447 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -24,6 +24,7 @@
     ],
     static_libs: [
         "frameworks-base-testutils",
+        "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
         "core-tests-support",
         "android-common",
         "frameworks-core-util-lib",
diff --git a/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
new file mode 100644
index 0000000..de6f8f7
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/ManualTimeSuggestionTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.app.timedetector;
+
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.util.TimestampedValue;
+
+import org.junit.Test;
+
+public class ManualTimeSuggestionTest {
+
+    private static final TimestampedValue<Long> ARBITRARY_TIME =
+            new TimestampedValue<>(1111L, 2222L);
+
+    @Test
+    public void testEquals() {
+        ManualTimeSuggestion one = new ManualTimeSuggestion(ARBITRARY_TIME);
+        assertEquals(one, one);
+
+        ManualTimeSuggestion two = new ManualTimeSuggestion(ARBITRARY_TIME);
+        assertEquals(one, two);
+        assertEquals(two, one);
+
+        TimestampedValue<Long> differentTime = new TimestampedValue<>(
+                ARBITRARY_TIME.getReferenceTimeMillis() + 1,
+                ARBITRARY_TIME.getValue());
+        ManualTimeSuggestion three = new ManualTimeSuggestion(differentTime);
+        assertNotEquals(one, three);
+        assertNotEquals(three, one);
+
+        // DebugInfo must not be considered in equals().
+        one.addDebugInfo("Debug info 1");
+        two.addDebugInfo("Debug info 2");
+        assertEquals(one, two);
+    }
+
+    @Test
+    public void testParcelable() {
+        ManualTimeSuggestion suggestion = new ManualTimeSuggestion(ARBITRARY_TIME);
+        assertRoundTripParcelable(suggestion);
+
+        // DebugInfo should also be stored (but is not checked by equals()
+        suggestion.addDebugInfo("This is debug info");
+        ManualTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
+        assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
+    }
+}
diff --git a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
index c9a86dc..bee270e 100644
--- a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
@@ -16,11 +16,12 @@
 
 package android.app.timedetector;
 
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.util.TimestampedValue;
 
 import org.junit.Test;
@@ -30,53 +31,67 @@
 
     @Test
     public void testEquals() {
-        PhoneTimeSuggestion one = new PhoneTimeSuggestion(PHONE_ID);
-        assertEquals(one, one);
+        PhoneTimeSuggestion.Builder builder1 = new PhoneTimeSuggestion.Builder(PHONE_ID);
+        {
+            PhoneTimeSuggestion one = builder1.build();
+            assertEquals(one, one);
+        }
 
-        PhoneTimeSuggestion two = new PhoneTimeSuggestion(PHONE_ID);
-        assertEquals(one, two);
-        assertEquals(two, one);
+        PhoneTimeSuggestion.Builder builder2 = new PhoneTimeSuggestion.Builder(PHONE_ID);
+        {
+            PhoneTimeSuggestion one = builder1.build();
+            PhoneTimeSuggestion two = builder2.build();
+            assertEquals(one, two);
+            assertEquals(two, one);
+        }
 
-        one.setUtcTime(new TimestampedValue<>(1111L, 2222L));
-        assertEquals(one, one);
+        builder1.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+        {
+            PhoneTimeSuggestion one = builder1.build();
+            assertEquals(one, one);
+        }
 
-        two.setUtcTime(new TimestampedValue<>(1111L, 2222L));
-        assertEquals(one, two);
-        assertEquals(two, one);
+        builder2.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+        {
+            PhoneTimeSuggestion one = builder1.build();
+            PhoneTimeSuggestion two = builder2.build();
+            assertEquals(one, two);
+            assertEquals(two, one);
+        }
 
-        PhoneTimeSuggestion three = new PhoneTimeSuggestion(PHONE_ID + 1);
-        three.setUtcTime(new TimestampedValue<>(1111L, 2222L));
-        assertNotEquals(one, three);
-        assertNotEquals(three, one);
+        PhoneTimeSuggestion.Builder builder3 = new PhoneTimeSuggestion.Builder(PHONE_ID + 1);
+        builder3.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+        {
+            PhoneTimeSuggestion one = builder1.build();
+            PhoneTimeSuggestion three = builder3.build();
+            assertNotEquals(one, three);
+            assertNotEquals(three, one);
+        }
 
         // DebugInfo must not be considered in equals().
-        one.addDebugInfo("Debug info 1");
-        two.addDebugInfo("Debug info 2");
-        assertEquals(one, two);
+        builder1.addDebugInfo("Debug info 1");
+        builder2.addDebugInfo("Debug info 2");
+        {
+            PhoneTimeSuggestion one = builder1.build();
+            PhoneTimeSuggestion two = builder2.build();
+            assertEquals(one, two);
+        }
     }
 
     @Test
     public void testParcelable() {
-        PhoneTimeSuggestion one = new PhoneTimeSuggestion(PHONE_ID);
-        assertEquals(one, roundTripParcelable(one));
+        PhoneTimeSuggestion.Builder builder = new PhoneTimeSuggestion.Builder(PHONE_ID);
+        assertRoundTripParcelable(builder.build());
 
-        one.setUtcTime(new TimestampedValue<>(1111L, 2222L));
-        assertEquals(one, roundTripParcelable(one));
+        builder.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+        assertRoundTripParcelable(builder.build());
 
         // DebugInfo should also be stored (but is not checked by equals()
-        one.addDebugInfo("This is debug info");
-        PhoneTimeSuggestion two = roundTripParcelable(one);
-        assertEquals(one.getDebugInfo(), two.getDebugInfo());
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T extends Parcelable> T roundTripParcelable(T one) {
-        Parcel parcel = Parcel.obtain();
-        parcel.writeTypedObject(one, 0);
-        parcel.setDataPosition(0);
-
-        T toReturn = (T) parcel.readTypedObject(PhoneTimeSuggestion.CREATOR);
-        parcel.recycle();
-        return toReturn;
+        {
+            PhoneTimeSuggestion suggestion1 = builder.build();
+            builder.addDebugInfo("This is debug info");
+            PhoneTimeSuggestion rtSuggestion1 = roundTripParcelable(suggestion1);
+            assertEquals(suggestion1.getDebugInfo(), rtSuggestion1.getDebugInfo());
+        }
     }
 }
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 576ac73..5cb7852 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -239,4 +239,17 @@
         verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                 .times(1)).onThermalStatusChanged(status);
     }
+
+    @Test
+    public void testUserspaceRebootNotSupported_throwsUnsupportedOperationException() {
+        // Can't use assumption framework with AndroidTestCase :(
+        if (mPm.isRebootingUserspaceSupported()) {
+            return;
+        }
+        try {
+            mPm.reboot(PowerManager.REBOOT_USERSPACE);
+            fail("UnsupportedOperationException not thrown");
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/util/CloseGuardTest.java b/core/tests/coretests/src/android/util/CloseGuardTest.java
new file mode 100644
index 0000000..d86c7b7
--- /dev/null
+++ b/core/tests/coretests/src/android/util/CloseGuardTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import libcore.dalvik.system.CloseGuardSupport;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+/** Unit tests for {@link android.util.CloseGuard} */
+public class CloseGuardTest {
+
+    @Rule
+    public final TestRule rule = CloseGuardSupport.getRule();
+
+    @Test
+    public void testEnabled_NotOpen() throws Throwable {
+        ResourceOwner owner = new ResourceOwner();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test
+    public void testEnabled_OpenNotClosed() throws Throwable {
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        assertUnreleasedResources(owner, 1);
+    }
+
+    @Test
+    public void testEnabled_OpenThenClosed() throws Throwable {
+        ResourceOwner owner = new ResourceOwner();
+        owner.open();
+        owner.close();
+        assertUnreleasedResources(owner, 0);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testOpen_withNullMethodName_throwsNPE() throws Throwable {
+        CloseGuard closeGuard = new CloseGuard();
+        closeGuard.open(null);
+    }
+
+    private void assertUnreleasedResources(ResourceOwner owner, int expectedCount)
+            throws Throwable {
+        try {
+            CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount);
+        } finally {
+            // Close the resource so that CloseGuard does not generate a warning for real when it
+            // is actually finalized.
+            owner.close();
+        }
+    }
+
+    /**
+     * A test user of {@link CloseGuard}.
+     */
+    private static class ResourceOwner {
+
+        private final CloseGuard mCloseGuard;
+
+        ResourceOwner() {
+            mCloseGuard = new CloseGuard();
+        }
+
+        public void open() {
+            mCloseGuard.open("close");
+        }
+
+        public void close() {
+            mCloseGuard.close();
+        }
+
+        /**
+         * Make finalize public so that it can be tested directly without relying on garbage
+         * collection to trigger it.
+         */
+        @Override
+        public void finalize() throws Throwable {
+            mCloseGuard.warnIfOpen();
+            super.finalize();
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/util/LocalLogTest.java b/core/tests/coretests/src/android/util/LocalLogTest.java
index 6cdcb5e..d4861cd 100644
--- a/core/tests/coretests/src/android/util/LocalLogTest.java
+++ b/core/tests/coretests/src/android/util/LocalLogTest.java
@@ -29,14 +29,24 @@
 @LargeTest
 public class LocalLogTest extends TestCase {
 
-    public void testA() {
+    public void testA_localTimestamps() {
+        boolean localTimestamps = true;
+        doTestA(localTimestamps);
+    }
+
+    public void testA_nonLocalTimestamps() {
+        boolean localTimestamps = false;
+        doTestA(localTimestamps);
+    }
+
+    private void doTestA(boolean localTimestamps) {
         String[] lines = {
-            "foo",
-            "bar",
-            "baz"
+                "foo",
+                "bar",
+                "baz"
         };
         String[] want = lines;
-        testcase(new LocalLog(10), lines, want);
+        testcase(new LocalLog(10, localTimestamps), lines, want);
     }
 
     public void testB() {
diff --git a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
index 80bce26..ec7e83f 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
@@ -238,6 +238,7 @@
         assertThat(conversationActions).isEmpty();
     }
 
+    @Test
     public void createLabeledIntentResult_null() {
         ActionsSuggestionsModel.ActionSuggestion nativeSuggestion =
                 new ActionsSuggestionsModel.ActionSuggestion(
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 9f70538..67783bf 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -94,7 +94,7 @@
     }
 
     @SmallTest
-    private static void testHandle() throws Exception {
+    public void testHandle() throws Exception {
         String value;
         SystemProperties.Handle handle = SystemProperties.find("doesnotexist_2341431");
         assertNull(handle);
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index 3e53a38..cc1ce9b 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -39,10 +39,11 @@
         <permission name="android.permission.MOVE_PACKAGE"/>
         <permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.READ_SEARCH_INDEXABLES"/>
         <permission name="android.permission.REBOOT"/>
-        <permission name="android.permission.SET_TIME"/>
         <permission name="android.permission.STATUS_BAR"/>
+        <permission name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"/>
         <permission name="android.permission.TETHER_PRIVILEGED"/>
         <permission name="android.permission.USE_RESERVED_DISK"/>
         <permission name="android.permission.USER_ACTIVITY"/>
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index e24f26c1..d282744 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -57,4 +57,7 @@
   <hidden-api-whitelisted-app package="com.android.terminal" />
   <hidden-api-whitelisted-app package="com.android.wallpaper" />
   <hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
+  <!-- STOPSHIP: Remove this when fixing all @hide usage for tethering.-->
+  <hidden-api-whitelisted-app package="com.android.networkstack.tethering" />
+  <hidden-api-whitelisted-app package="com.android.networkstack" />
 </config>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 375b35c..0756647 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -139,7 +139,7 @@
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
         <permission name="android.permission.CHANGE_CONFIGURATION"/>
         <permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/>
-        <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+        <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
         <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
         <permission name="android.permission.DUMP"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
@@ -155,12 +155,12 @@
         <permission name="android.permission.REGISTER_CALL_PROVIDER"/>
         <permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
         <permission name="android.permission.SEND_RESPOND_VIA_MESSAGE"/>
-        <permission name="android.permission.SET_TIME"/>
         <permission name="android.permission.SET_TIME_ZONE"/>
         <permission name="android.permission.SHUTDOWN"/>
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
         <permission name="android.permission.STATUS_BAR"/>
         <permission name="android.permission.STOP_APP_SWITCHES"/>
+        <permission name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"/>
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.UPDATE_DEVICE_STATS"/>
         <permission name="android.permission.UPDATE_LOCK"/>
@@ -234,6 +234,13 @@
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.networkstack.tethering">
+        <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.UPDATE_APP_OPS_STATS"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.server.telecom">
         <permission name="android.permission.BIND_CONNECTION_SERVICE"/>
         <permission name="android.permission.BIND_INCALL_SERVICE"/>
@@ -333,6 +340,8 @@
         <permission name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
         <!-- Permission required for Telecom car mode CTS tests. -->
         <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+        <!-- Permission required for Tethering CTS tests. -->
+        <permission name="android.permission.TETHER_PRIVILEGED"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 08f4176..fad7d80 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -16,11 +16,12 @@
 
 package android.security;
 
+import android.annotation.UnsupportedAppUsage;
+
 import com.android.org.bouncycastle.util.io.pem.PemObject;
 import com.android.org.bouncycastle.util.io.pem.PemReader;
 import com.android.org.bouncycastle.util.io.pem.PemWriter;
 
-import android.annotation.UnsupportedAppUsage;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -64,6 +65,9 @@
     /** Key prefix for VPN. */
     public static final String VPN = "VPN_";
 
+    /** Key prefix for platform VPNs. */
+    public static final String PLATFORM_VPN = "PLATFORM_VPN_";
+
     /** Key prefix for WIFI. */
     public static final String WIFI = "WIFI_";
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
index c6515ef..feb6101 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -176,7 +176,7 @@
                 KeyStore keyStore, IBinder operationToken) {
             KeyStoreCryptoOperationStreamer streamer = new KeyStoreCryptoOperationChunkedStreamer(
                     new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                            keyStore, operationToken));
+                            keyStore, operationToken), 0);
             if (isEncrypting()) {
                 return streamer;
             } else {
@@ -191,7 +191,7 @@
         protected final KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
                 KeyStore keyStore, IBinder operationToken) {
             return new KeyStoreCryptoOperationChunkedStreamer(
-                    new AdditionalAuthenticationDataStream(keyStore, operationToken));
+                    new AdditionalAuthenticationDataStream(keyStore, operationToken), 0);
         }
 
         @Override
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index 5bcb34a..ccc3153 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -299,7 +299,7 @@
             KeyStore keyStore, IBinder operationToken) {
         return new KeyStoreCryptoOperationChunkedStreamer(
                 new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                        keyStore, operationToken));
+                        keyStore, operationToken), 0);
     }
 
     /**
diff --git a/keystore/java/android/security/keystore/ArrayUtils.java b/keystore/java/android/security/keystore/ArrayUtils.java
index 26172d2..f519c7c 100644
--- a/keystore/java/android/security/keystore/ArrayUtils.java
+++ b/keystore/java/android/security/keystore/ArrayUtils.java
@@ -55,6 +55,34 @@
         }
     }
 
+    /**
+     * Copies a subset of the source array to the destination array.
+     * Length will be limited to the bounds of source and destination arrays.
+     * The length actually copied is returned, which will be <= length argument.
+     * @param src is the source array
+     * @param srcOffset is the offset in the source array.
+     * @param dst is the destination array.
+     * @param dstOffset is the offset in the destination array.
+     * @param length is the length to be copied from source to destination array.
+     * @return The length actually copied from source array.
+     */
+    public static int copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int length) {
+        if (dst == null || src == null) {
+            return 0;
+        }
+        if (length > dst.length - dstOffset) {
+            length = dst.length - dstOffset;
+        }
+        if (length > src.length - srcOffset) {
+            length = src.length - srcOffset;
+        }
+        if (length <= 0) {
+            return 0;
+        }
+        System.arraycopy(src, srcOffset, dst, dstOffset, length);
+        return length;
+    }
+
     public static byte[] subarray(byte[] arr, int offset, int len) {
         if (len == 0) {
             return EmptyArray.BYTE;
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index 75bea26..2c0f40d 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -24,19 +24,20 @@
 
 import libcore.util.EmptyArray;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.ProviderException;
-
 /**
  * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
  * {@code update} and {@code finish} operations.
  *
- * <p>The helper abstracts away to issues that need to be solved in most code that uses KeyStore's
+ * <p>The helper abstracts away issues that need to be solved in most code that uses KeyStore's
  * update and finish operations. Firstly, KeyStore's update operation can consume only a limited
  * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
  * operation may consume less data than provided, in which case the caller has to buffer the
- * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
+ * remainder for next time. Thirdly, when the input is smaller than a threshold, skipping update
+ * and passing input data directly to final improves performance. This threshold is configurable;
+ * using a threshold <= 1 causes the helper act eagerly, which may be required for some types of
+ * operations (e.g. ciphers).
+ *
+ * <p>The helper exposes {@link #update(byte[], int, int) update} and
  * {@link #doFinal(byte[], int, int, byte[], byte[]) doFinal} operations which can be used to
  * conveniently implement various JCA crypto primitives.
  *
@@ -67,240 +68,122 @@
 
     // Binder buffer is about 1MB, but it's shared between all active transactions of the process.
     // Thus, it's safer to use a much smaller upper bound.
-    private static final int DEFAULT_MAX_CHUNK_SIZE = 64 * 1024;
+    private static final int DEFAULT_CHUNK_SIZE_MAX = 64 * 1024;
+    // The chunk buffer will be sent to update until its size under this threshold.
+    // This threshold should be <= the max input allowed for finish.
+    // Setting this threshold <= 1 will effectivley disable buffering between updates.
+    private static final int DEFAULT_CHUNK_SIZE_THRESHOLD = 2 * 1024;
 
     private final Stream mKeyStoreStream;
-    private final int mMaxChunkSize;
-
-    private byte[] mBuffered = EmptyArray.BYTE;
-    private int mBufferedOffset;
-    private int mBufferedLength;
+    private final int mChunkSizeMax;
+    private final int mChunkSizeThreshold;
+    private final byte[] mChunk;
+    private int mChunkLength = 0;
     private long mConsumedInputSizeBytes;
     private long mProducedOutputSizeBytes;
 
-    public KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
-        this(operation, DEFAULT_MAX_CHUNK_SIZE);
+    KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
+        this(operation, DEFAULT_CHUNK_SIZE_THRESHOLD, DEFAULT_CHUNK_SIZE_MAX);
     }
 
-    public KeyStoreCryptoOperationChunkedStreamer(Stream operation, int maxChunkSize) {
+    KeyStoreCryptoOperationChunkedStreamer(Stream operation, int chunkSizeThreshold) {
+        this(operation, chunkSizeThreshold, DEFAULT_CHUNK_SIZE_MAX);
+    }
+
+    KeyStoreCryptoOperationChunkedStreamer(Stream operation, int chunkSizeThreshold,
+            int chunkSizeMax) {
         mKeyStoreStream = operation;
-        mMaxChunkSize = maxChunkSize;
+        mChunkSizeMax = chunkSizeMax;
+        if (chunkSizeThreshold <= 0) {
+            mChunkSizeThreshold = 1;
+        } else if (chunkSizeThreshold > chunkSizeMax) {
+            mChunkSizeThreshold = chunkSizeMax;
+        } else {
+            mChunkSizeThreshold = chunkSizeThreshold;
+        }
+        mChunk = new byte[mChunkSizeMax];
     }
 
-    @Override
     public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException {
-        if (inputLength == 0) {
+        if (inputLength == 0 || input == null) {
             // No input provided
             return EmptyArray.BYTE;
         }
+        if (inputLength < 0 || inputOffset < 0 || (inputOffset + inputLength) > input.length) {
+            throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+                "Input offset and length out of bounds of input array");
+        }
 
-        ByteArrayOutputStream bufferedOutput = null;
+        byte[] output = EmptyArray.BYTE;
 
-        while (inputLength > 0) {
-            byte[] chunk;
-            int inputBytesInChunk;
-            if ((mBufferedLength + inputLength) > mMaxChunkSize) {
-                // Too much input for one chunk -- extract one max-sized chunk and feed it into the
-                // update operation.
-                inputBytesInChunk = mMaxChunkSize - mBufferedLength;
-                chunk = ArrayUtils.concat(mBuffered, mBufferedOffset, mBufferedLength,
-                        input, inputOffset, inputBytesInChunk);
-            } else {
-                // All of available input fits into one chunk.
-                if ((mBufferedLength == 0) && (inputOffset == 0)
-                        && (inputLength == input.length)) {
-                    // Nothing buffered and all of input array needs to be fed into the update
-                    // operation.
-                    chunk = input;
-                    inputBytesInChunk = input.length;
-                } else {
-                    // Need to combine buffered data with input data into one array.
-                    inputBytesInChunk = inputLength;
-                    chunk = ArrayUtils.concat(mBuffered, mBufferedOffset, mBufferedLength,
-                            input, inputOffset, inputBytesInChunk);
+        while (inputLength > 0 || mChunkLength >= mChunkSizeThreshold) {
+            int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength,
+                    inputLength);
+            inputLength -= inputConsumed;
+            inputOffset += inputConsumed;
+            mChunkLength += inputConsumed;
+            mConsumedInputSizeBytes += inputConsumed;
+
+            if (mChunkLength > mChunkSizeMax) {
+                throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+                    "Chunk size exceeded max chunk size. Max: " + mChunkSizeMax
+                    + " Actual: " + mChunkLength);
+            }
+
+            if (mChunkLength >= mChunkSizeThreshold) {
+                OperationResult opResult = mKeyStoreStream.update(
+                        ArrayUtils.subarray(mChunk, 0, mChunkLength));
+
+                if (opResult == null) {
+                    throw new KeyStoreConnectException();
+                } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+                    throw KeyStore.getKeyStoreException(opResult.resultCode);
                 }
-            }
-            // Update input array references to reflect that some of its bytes are now in mBuffered.
-            inputOffset += inputBytesInChunk;
-            inputLength -= inputBytesInChunk;
-            mConsumedInputSizeBytes += inputBytesInChunk;
-
-            OperationResult opResult = mKeyStoreStream.update(chunk);
-            if (opResult == null) {
-                throw new KeyStoreConnectException();
-            } else if (opResult.resultCode != KeyStore.NO_ERROR) {
-                throw KeyStore.getKeyStoreException(opResult.resultCode);
-            }
-
-            if (opResult.inputConsumed == chunk.length) {
-                // The whole chunk was consumed
-                mBuffered = EmptyArray.BYTE;
-                mBufferedOffset = 0;
-                mBufferedLength = 0;
-            } else if (opResult.inputConsumed <= 0) {
-                // Nothing was consumed. More input needed.
-                if (inputLength > 0) {
-                    // More input is available, but it wasn't included into the previous chunk
-                    // because the chunk reached its maximum permitted size.
-                    // Shouldn't have happened.
+                if (opResult.inputConsumed <= 0) {
+                    throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+                        "Keystore consumed 0 of " + mChunkLength + " bytes provided.");
+                } else if (opResult.inputConsumed > mChunkLength) {
                     throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
-                            "Keystore consumed nothing from max-sized chunk: " + chunk.length
-                                    + " bytes");
+                        "Keystore consumed more input than provided. Provided: "
+                            + mChunkLength + ", consumed: " + opResult.inputConsumed);
                 }
-                mBuffered = chunk;
-                mBufferedOffset = 0;
-                mBufferedLength = chunk.length;
-            } else if (opResult.inputConsumed < chunk.length) {
-                // The chunk was consumed only partially -- buffer the rest of the chunk
-                mBuffered = chunk;
-                mBufferedOffset = opResult.inputConsumed;
-                mBufferedLength = chunk.length - opResult.inputConsumed;
-            } else {
-                throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
-                        "Keystore consumed more input than provided. Provided: " + chunk.length
-                                + ", consumed: " + opResult.inputConsumed);
-            }
+                mChunkLength -= opResult.inputConsumed;
 
-            if ((opResult.output != null) && (opResult.output.length > 0)) {
-                if (inputLength + mBufferedLength > 0) {
-                    // More output might be produced in this loop -- buffer the current output
-                    if (bufferedOutput == null) {
-                        bufferedOutput = new ByteArrayOutputStream();
-                    }
-                    try {
-                        bufferedOutput.write(opResult.output);
-                    } catch (IOException e) {
-                        throw new ProviderException("Failed to buffer output", e);
-                    }
-                } else {
-                    // No more output will be produced in this loop
-                    byte[] result;
-                    if (bufferedOutput == null) {
-                        // No previously buffered output
-                        result = opResult.output;
-                    } else {
-                        // There was some previously buffered output
-                        try {
-                            bufferedOutput.write(opResult.output);
-                        } catch (IOException e) {
-                            throw new ProviderException("Failed to buffer output", e);
-                        }
-                        result = bufferedOutput.toByteArray();
-                    }
-                    mProducedOutputSizeBytes += result.length;
-                    return result;
+                if (mChunkLength > 0) {
+                    // Partialy consumed, shift chunk contents
+                    ArrayUtils.copy(mChunk, opResult.inputConsumed, mChunk, 0, mChunkLength);
+                }
+
+                if ((opResult.output != null) && (opResult.output.length > 0)) {
+                    // Output was produced
+                    mProducedOutputSizeBytes += opResult.output.length;
+                    output = ArrayUtils.concat(output, opResult.output);
                 }
             }
         }
-
-        byte[] result;
-        if (bufferedOutput == null) {
-            // No output produced
-            result = EmptyArray.BYTE;
-        } else {
-            result = bufferedOutput.toByteArray();
-        }
-        mProducedOutputSizeBytes += result.length;
-        return result;
+        return output;
     }
 
-    @Override
     public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
             byte[] signature, byte[] additionalEntropy) throws KeyStoreException {
-        if (inputLength == 0) {
-            // No input provided -- simplify the rest of the code
-            input = EmptyArray.BYTE;
-            inputOffset = 0;
-        }
-
-        // Flush all buffered input and provided input into keystore/keymaster.
         byte[] output = update(input, inputOffset, inputLength);
-        output = ArrayUtils.concat(output, flush());
+        byte[] finalChunk = ArrayUtils.subarray(mChunk, 0, mChunkLength);
+        OperationResult opResult = mKeyStoreStream.finish(finalChunk, signature, additionalEntropy);
 
-        OperationResult opResult = mKeyStoreStream.finish(EmptyArray.BYTE, signature,
-                                                          additionalEntropy);
         if (opResult == null) {
             throw new KeyStoreConnectException();
         } else if (opResult.resultCode != KeyStore.NO_ERROR) {
             throw KeyStore.getKeyStoreException(opResult.resultCode);
         }
-        mProducedOutputSizeBytes += opResult.output.length;
+        // If no error, assume all input consumed
+        mConsumedInputSizeBytes += finalChunk.length;
 
-        return ArrayUtils.concat(output, opResult.output);
-    }
-
-    public byte[] flush() throws KeyStoreException {
-        if (mBufferedLength <= 0) {
-            return EmptyArray.BYTE;
+        if ((opResult.output != null) && (opResult.output.length > 0)) {
+            mProducedOutputSizeBytes += opResult.output.length;
+            output = ArrayUtils.concat(output, opResult.output);
         }
 
-        // Keep invoking the update operation with remaining buffered data until either all of the
-        // buffered data is consumed or until update fails to consume anything.
-        ByteArrayOutputStream bufferedOutput = null;
-        while (mBufferedLength > 0) {
-            byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength);
-            OperationResult opResult = mKeyStoreStream.update(chunk);
-            if (opResult == null) {
-                throw new KeyStoreConnectException();
-            } else if (opResult.resultCode != KeyStore.NO_ERROR) {
-                throw KeyStore.getKeyStoreException(opResult.resultCode);
-            }
-
-            if (opResult.inputConsumed <= 0) {
-                // Nothing was consumed. Break out of the loop to avoid an infinite loop.
-                break;
-            }
-
-            if (opResult.inputConsumed >= chunk.length) {
-                // All of the input was consumed
-                mBuffered = EmptyArray.BYTE;
-                mBufferedOffset = 0;
-                mBufferedLength = 0;
-            } else {
-                // Some of the input was not consumed
-                mBuffered = chunk;
-                mBufferedOffset = opResult.inputConsumed;
-                mBufferedLength = chunk.length - opResult.inputConsumed;
-            }
-
-            if (opResult.inputConsumed > chunk.length) {
-                throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
-                        "Keystore consumed more input than provided. Provided: "
-                                + chunk.length + ", consumed: " + opResult.inputConsumed);
-            }
-
-            if ((opResult.output != null) && (opResult.output.length > 0)) {
-                // Some output was produced by this update operation
-                if (bufferedOutput == null) {
-                    // No output buffered yet.
-                    if (mBufferedLength == 0) {
-                        // No more output will be produced by this flush operation
-                        mProducedOutputSizeBytes += opResult.output.length;
-                        return opResult.output;
-                    } else {
-                        // More output might be produced by this flush operation -- buffer output.
-                        bufferedOutput = new ByteArrayOutputStream();
-                    }
-                }
-                // Buffer the output from this update operation
-                try {
-                    bufferedOutput.write(opResult.output);
-                } catch (IOException e) {
-                    throw new ProviderException("Failed to buffer output", e);
-                }
-            }
-        }
-
-        if (mBufferedLength > 0) {
-            throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
-                    "Keystore failed to consume last "
-                            + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte")
-                            + " of input");
-        }
-
-        byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE;
-        mProducedOutputSizeBytes += result.length;
-        return result;
+        return output;
     }
 
     @Override
diff --git a/libs/androidfw/LocaleDataTables.cpp b/libs/androidfw/LocaleDataTables.cpp
index c276a23..e748bd8 100644
--- a/libs/androidfw/LocaleDataTables.cpp
+++ b/libs/androidfw/LocaleDataTables.cpp
@@ -10,1439 +10,1479 @@
     /* 6  */ {'B', 'a', 's', 's'},
     /* 7  */ {'B', 'e', 'n', 'g'},
     /* 8  */ {'B', 'r', 'a', 'h'},
-    /* 9  */ {'C', 'a', 'n', 's'},
-    /* 10 */ {'C', 'a', 'r', 'i'},
-    /* 11 */ {'C', 'h', 'a', 'm'},
-    /* 12 */ {'C', 'h', 'e', 'r'},
-    /* 13 */ {'C', 'o', 'p', 't'},
-    /* 14 */ {'C', 'p', 'r', 't'},
-    /* 15 */ {'C', 'y', 'r', 'l'},
-    /* 16 */ {'D', 'e', 'v', 'a'},
-    /* 17 */ {'E', 'g', 'y', 'p'},
-    /* 18 */ {'E', 't', 'h', 'i'},
-    /* 19 */ {'G', 'e', 'o', 'r'},
-    /* 20 */ {'G', 'o', 't', 'h'},
-    /* 21 */ {'G', 'r', 'e', 'k'},
-    /* 22 */ {'G', 'u', 'j', 'r'},
-    /* 23 */ {'G', 'u', 'r', 'u'},
-    /* 24 */ {'H', 'a', 'n', 's'},
-    /* 25 */ {'H', 'a', 'n', 't'},
-    /* 26 */ {'H', 'a', 't', 'r'},
-    /* 27 */ {'H', 'e', 'b', 'r'},
-    /* 28 */ {'H', 'l', 'u', 'w'},
-    /* 29 */ {'H', 'm', 'n', 'g'},
-    /* 30 */ {'I', 't', 'a', 'l'},
-    /* 31 */ {'J', 'p', 'a', 'n'},
-    /* 32 */ {'K', 'a', 'l', 'i'},
-    /* 33 */ {'K', 'a', 'n', 'a'},
-    /* 34 */ {'K', 'h', 'a', 'r'},
-    /* 35 */ {'K', 'h', 'm', 'r'},
-    /* 36 */ {'K', 'n', 'd', 'a'},
-    /* 37 */ {'K', 'o', 'r', 'e'},
-    /* 38 */ {'L', 'a', 'n', 'a'},
-    /* 39 */ {'L', 'a', 'o', 'o'},
-    /* 40 */ {'L', 'a', 't', 'n'},
-    /* 41 */ {'L', 'e', 'p', 'c'},
-    /* 42 */ {'L', 'i', 'n', 'a'},
-    /* 43 */ {'L', 'i', 's', 'u'},
-    /* 44 */ {'L', 'y', 'c', 'i'},
-    /* 45 */ {'L', 'y', 'd', 'i'},
-    /* 46 */ {'M', 'a', 'n', 'd'},
-    /* 47 */ {'M', 'a', 'n', 'i'},
-    /* 48 */ {'M', 'e', 'r', 'c'},
-    /* 49 */ {'M', 'l', 'y', 'm'},
-    /* 50 */ {'M', 'o', 'n', 'g'},
-    /* 51 */ {'M', 'r', 'o', 'o'},
-    /* 52 */ {'M', 'y', 'm', 'r'},
-    /* 53 */ {'N', 'a', 'r', 'b'},
-    /* 54 */ {'N', 'k', 'o', 'o'},
-    /* 55 */ {'O', 'g', 'a', 'm'},
-    /* 56 */ {'O', 'r', 'k', 'h'},
-    /* 57 */ {'O', 'r', 'y', 'a'},
-    /* 58 */ {'O', 's', 'g', 'e'},
-    /* 59 */ {'P', 'a', 'u', 'c'},
-    /* 60 */ {'P', 'h', 'l', 'i'},
-    /* 61 */ {'P', 'h', 'n', 'x'},
-    /* 62 */ {'P', 'l', 'r', 'd'},
-    /* 63 */ {'P', 'r', 't', 'i'},
-    /* 64 */ {'R', 'u', 'n', 'r'},
-    /* 65 */ {'S', 'a', 'm', 'r'},
-    /* 66 */ {'S', 'a', 'r', 'b'},
-    /* 67 */ {'S', 'a', 'u', 'r'},
-    /* 68 */ {'S', 'g', 'n', 'w'},
-    /* 69 */ {'S', 'i', 'n', 'h'},
-    /* 70 */ {'S', 'o', 'r', 'a'},
-    /* 71 */ {'S', 'y', 'r', 'c'},
-    /* 72 */ {'T', 'a', 'l', 'e'},
-    /* 73 */ {'T', 'a', 'l', 'u'},
-    /* 74 */ {'T', 'a', 'm', 'l'},
-    /* 75 */ {'T', 'a', 'n', 'g'},
-    /* 76 */ {'T', 'a', 'v', 't'},
-    /* 77 */ {'T', 'e', 'l', 'u'},
-    /* 78 */ {'T', 'f', 'n', 'g'},
-    /* 79 */ {'T', 'h', 'a', 'a'},
-    /* 80 */ {'T', 'h', 'a', 'i'},
-    /* 81 */ {'T', 'i', 'b', 't'},
-    /* 82 */ {'U', 'g', 'a', 'r'},
-    /* 83 */ {'V', 'a', 'i', 'i'},
-    /* 84 */ {'X', 'p', 'e', 'o'},
-    /* 85 */ {'X', 's', 'u', 'x'},
-    /* 86 */ {'Y', 'i', 'i', 'i'},
-    /* 87 */ {'~', '~', '~', 'A'},
-    /* 88 */ {'~', '~', '~', 'B'},
+    /* 9  */ {'C', 'a', 'k', 'm'},
+    /* 10 */ {'C', 'a', 'n', 's'},
+    /* 11 */ {'C', 'a', 'r', 'i'},
+    /* 12 */ {'C', 'h', 'a', 'm'},
+    /* 13 */ {'C', 'h', 'e', 'r'},
+    /* 14 */ {'C', 'o', 'p', 't'},
+    /* 15 */ {'C', 'p', 'r', 't'},
+    /* 16 */ {'C', 'y', 'r', 'l'},
+    /* 17 */ {'D', 'e', 'v', 'a'},
+    /* 18 */ {'E', 'g', 'y', 'p'},
+    /* 19 */ {'E', 't', 'h', 'i'},
+    /* 20 */ {'G', 'e', 'o', 'r'},
+    /* 21 */ {'G', 'o', 'n', 'g'},
+    /* 22 */ {'G', 'o', 'n', 'm'},
+    /* 23 */ {'G', 'o', 't', 'h'},
+    /* 24 */ {'G', 'r', 'e', 'k'},
+    /* 25 */ {'G', 'u', 'j', 'r'},
+    /* 26 */ {'G', 'u', 'r', 'u'},
+    /* 27 */ {'H', 'a', 'n', 's'},
+    /* 28 */ {'H', 'a', 'n', 't'},
+    /* 29 */ {'H', 'a', 't', 'r'},
+    /* 30 */ {'H', 'e', 'b', 'r'},
+    /* 31 */ {'H', 'l', 'u', 'w'},
+    /* 32 */ {'H', 'm', 'n', 'g'},
+    /* 33 */ {'H', 'm', 'n', 'p'},
+    /* 34 */ {'I', 't', 'a', 'l'},
+    /* 35 */ {'J', 'p', 'a', 'n'},
+    /* 36 */ {'K', 'a', 'l', 'i'},
+    /* 37 */ {'K', 'a', 'n', 'a'},
+    /* 38 */ {'K', 'h', 'a', 'r'},
+    /* 39 */ {'K', 'h', 'm', 'r'},
+    /* 40 */ {'K', 'n', 'd', 'a'},
+    /* 41 */ {'K', 'o', 'r', 'e'},
+    /* 42 */ {'L', 'a', 'n', 'a'},
+    /* 43 */ {'L', 'a', 'o', 'o'},
+    /* 44 */ {'L', 'a', 't', 'n'},
+    /* 45 */ {'L', 'e', 'p', 'c'},
+    /* 46 */ {'L', 'i', 'n', 'a'},
+    /* 47 */ {'L', 'i', 's', 'u'},
+    /* 48 */ {'L', 'y', 'c', 'i'},
+    /* 49 */ {'L', 'y', 'd', 'i'},
+    /* 50 */ {'M', 'a', 'n', 'd'},
+    /* 51 */ {'M', 'a', 'n', 'i'},
+    /* 52 */ {'M', 'e', 'r', 'c'},
+    /* 53 */ {'M', 'l', 'y', 'm'},
+    /* 54 */ {'M', 'o', 'n', 'g'},
+    /* 55 */ {'M', 'r', 'o', 'o'},
+    /* 56 */ {'M', 'y', 'm', 'r'},
+    /* 57 */ {'N', 'a', 'r', 'b'},
+    /* 58 */ {'N', 'k', 'o', 'o'},
+    /* 59 */ {'N', 's', 'h', 'u'},
+    /* 60 */ {'O', 'g', 'a', 'm'},
+    /* 61 */ {'O', 'r', 'k', 'h'},
+    /* 62 */ {'O', 'r', 'y', 'a'},
+    /* 63 */ {'O', 's', 'g', 'e'},
+    /* 64 */ {'P', 'a', 'u', 'c'},
+    /* 65 */ {'P', 'h', 'l', 'i'},
+    /* 66 */ {'P', 'h', 'n', 'x'},
+    /* 67 */ {'P', 'l', 'r', 'd'},
+    /* 68 */ {'P', 'r', 't', 'i'},
+    /* 69 */ {'R', 'u', 'n', 'r'},
+    /* 70 */ {'S', 'a', 'm', 'r'},
+    /* 71 */ {'S', 'a', 'r', 'b'},
+    /* 72 */ {'S', 'a', 'u', 'r'},
+    /* 73 */ {'S', 'g', 'n', 'w'},
+    /* 74 */ {'S', 'i', 'n', 'h'},
+    /* 75 */ {'S', 'o', 'g', 'd'},
+    /* 76 */ {'S', 'o', 'r', 'a'},
+    /* 77 */ {'S', 'o', 'y', 'o'},
+    /* 78 */ {'S', 'y', 'r', 'c'},
+    /* 79 */ {'T', 'a', 'l', 'e'},
+    /* 80 */ {'T', 'a', 'l', 'u'},
+    /* 81 */ {'T', 'a', 'm', 'l'},
+    /* 82 */ {'T', 'a', 'n', 'g'},
+    /* 83 */ {'T', 'a', 'v', 't'},
+    /* 84 */ {'T', 'e', 'l', 'u'},
+    /* 85 */ {'T', 'f', 'n', 'g'},
+    /* 86 */ {'T', 'h', 'a', 'a'},
+    /* 87 */ {'T', 'h', 'a', 'i'},
+    /* 88 */ {'T', 'i', 'b', 't'},
+    /* 89 */ {'U', 'g', 'a', 'r'},
+    /* 90 */ {'V', 'a', 'i', 'i'},
+    /* 91 */ {'W', 'c', 'h', 'o'},
+    /* 92 */ {'X', 'p', 'e', 'o'},
+    /* 93 */ {'X', 's', 'u', 'x'},
+    /* 94 */ {'Y', 'i', 'i', 'i'},
+    /* 95 */ {'~', '~', '~', 'A'},
+    /* 96 */ {'~', '~', '~', 'B'},
 };
 
 
 const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
-    {0x61610000u, 40u}, // aa -> Latn
-    {0xA0000000u, 40u}, // aai -> Latn
-    {0xA8000000u, 40u}, // aak -> Latn
-    {0xD0000000u, 40u}, // aau -> Latn
-    {0x61620000u, 15u}, // ab -> Cyrl
-    {0xA0200000u, 40u}, // abi -> Latn
-    {0xC4200000u, 40u}, // abr -> Latn
-    {0xCC200000u, 40u}, // abt -> Latn
-    {0xE0200000u, 40u}, // aby -> Latn
-    {0x8C400000u, 40u}, // acd -> Latn
-    {0x90400000u, 40u}, // ace -> Latn
-    {0x9C400000u, 40u}, // ach -> Latn
-    {0x80600000u, 40u}, // ada -> Latn
-    {0x90600000u, 40u}, // ade -> Latn
-    {0xA4600000u, 40u}, // adj -> Latn
-    {0xE0600000u, 15u}, // ady -> Cyrl
-    {0xE4600000u, 40u}, // adz -> Latn
+    {0x61610000u, 44u}, // aa -> Latn
+    {0xA0000000u, 44u}, // aai -> Latn
+    {0xA8000000u, 44u}, // aak -> Latn
+    {0xD0000000u, 44u}, // aau -> Latn
+    {0x61620000u, 16u}, // ab -> Cyrl
+    {0xA0200000u, 44u}, // abi -> Latn
+    {0xC0200000u, 16u}, // abq -> Cyrl
+    {0xC4200000u, 44u}, // abr -> Latn
+    {0xCC200000u, 44u}, // abt -> Latn
+    {0xE0200000u, 44u}, // aby -> Latn
+    {0x8C400000u, 44u}, // acd -> Latn
+    {0x90400000u, 44u}, // ace -> Latn
+    {0x9C400000u, 44u}, // ach -> Latn
+    {0x80600000u, 44u}, // ada -> Latn
+    {0x90600000u, 44u}, // ade -> Latn
+    {0xA4600000u, 44u}, // adj -> Latn
+    {0xBC600000u, 88u}, // adp -> Tibt
+    {0xE0600000u, 16u}, // ady -> Cyrl
+    {0xE4600000u, 44u}, // adz -> Latn
     {0x61650000u,  4u}, // ae -> Avst
     {0x84800000u,  1u}, // aeb -> Arab
-    {0xE0800000u, 40u}, // aey -> Latn
-    {0x61660000u, 40u}, // af -> Latn
-    {0x88C00000u, 40u}, // agc -> Latn
-    {0x8CC00000u, 40u}, // agd -> Latn
-    {0x98C00000u, 40u}, // agg -> Latn
-    {0xB0C00000u, 40u}, // agm -> Latn
-    {0xB8C00000u, 40u}, // ago -> Latn
-    {0xC0C00000u, 40u}, // agq -> Latn
-    {0x80E00000u, 40u}, // aha -> Latn
-    {0xACE00000u, 40u}, // ahl -> Latn
+    {0xE0800000u, 44u}, // aey -> Latn
+    {0x61660000u, 44u}, // af -> Latn
+    {0x88C00000u, 44u}, // agc -> Latn
+    {0x8CC00000u, 44u}, // agd -> Latn
+    {0x98C00000u, 44u}, // agg -> Latn
+    {0xB0C00000u, 44u}, // agm -> Latn
+    {0xB8C00000u, 44u}, // ago -> Latn
+    {0xC0C00000u, 44u}, // agq -> Latn
+    {0x80E00000u, 44u}, // aha -> Latn
+    {0xACE00000u, 44u}, // ahl -> Latn
     {0xB8E00000u,  0u}, // aho -> Ahom
-    {0x99200000u, 40u}, // ajg -> Latn
-    {0x616B0000u, 40u}, // ak -> Latn
-    {0xA9400000u, 85u}, // akk -> Xsux
-    {0x81600000u, 40u}, // ala -> Latn
-    {0xA1600000u, 40u}, // ali -> Latn
-    {0xB5600000u, 40u}, // aln -> Latn
-    {0xCD600000u, 15u}, // alt -> Cyrl
-    {0x616D0000u, 18u}, // am -> Ethi
-    {0xB1800000u, 40u}, // amm -> Latn
-    {0xB5800000u, 40u}, // amn -> Latn
-    {0xB9800000u, 40u}, // amo -> Latn
-    {0xBD800000u, 40u}, // amp -> Latn
-    {0x89A00000u, 40u}, // anc -> Latn
-    {0xA9A00000u, 40u}, // ank -> Latn
-    {0xB5A00000u, 40u}, // ann -> Latn
-    {0xE1A00000u, 40u}, // any -> Latn
-    {0xA5C00000u, 40u}, // aoj -> Latn
-    {0xB1C00000u, 40u}, // aom -> Latn
-    {0xE5C00000u, 40u}, // aoz -> Latn
+    {0x99200000u, 44u}, // ajg -> Latn
+    {0x616B0000u, 44u}, // ak -> Latn
+    {0xA9400000u, 93u}, // akk -> Xsux
+    {0x81600000u, 44u}, // ala -> Latn
+    {0xA1600000u, 44u}, // ali -> Latn
+    {0xB5600000u, 44u}, // aln -> Latn
+    {0xCD600000u, 16u}, // alt -> Cyrl
+    {0x616D0000u, 19u}, // am -> Ethi
+    {0xB1800000u, 44u}, // amm -> Latn
+    {0xB5800000u, 44u}, // amn -> Latn
+    {0xB9800000u, 44u}, // amo -> Latn
+    {0xBD800000u, 44u}, // amp -> Latn
+    {0x616E0000u, 44u}, // an -> Latn
+    {0x89A00000u, 44u}, // anc -> Latn
+    {0xA9A00000u, 44u}, // ank -> Latn
+    {0xB5A00000u, 44u}, // ann -> Latn
+    {0xE1A00000u, 44u}, // any -> Latn
+    {0xA5C00000u, 44u}, // aoj -> Latn
+    {0xB1C00000u, 44u}, // aom -> Latn
+    {0xE5C00000u, 44u}, // aoz -> Latn
     {0x89E00000u,  1u}, // apc -> Arab
     {0x8DE00000u,  1u}, // apd -> Arab
-    {0x91E00000u, 40u}, // ape -> Latn
-    {0xC5E00000u, 40u}, // apr -> Latn
-    {0xC9E00000u, 40u}, // aps -> Latn
-    {0xE5E00000u, 40u}, // apz -> Latn
+    {0x91E00000u, 44u}, // ape -> Latn
+    {0xC5E00000u, 44u}, // apr -> Latn
+    {0xC9E00000u, 44u}, // aps -> Latn
+    {0xE5E00000u, 44u}, // apz -> Latn
     {0x61720000u,  1u}, // ar -> Arab
-    {0x61725842u, 88u}, // ar-XB -> ~~~B
+    {0x61725842u, 96u}, // ar-XB -> ~~~B
     {0x8A200000u,  2u}, // arc -> Armi
-    {0x9E200000u, 40u}, // arh -> Latn
-    {0xB6200000u, 40u}, // arn -> Latn
-    {0xBA200000u, 40u}, // aro -> Latn
+    {0x9E200000u, 44u}, // arh -> Latn
+    {0xB6200000u, 44u}, // arn -> Latn
+    {0xBA200000u, 44u}, // aro -> Latn
     {0xC2200000u,  1u}, // arq -> Arab
+    {0xCA200000u,  1u}, // ars -> Arab
     {0xE2200000u,  1u}, // ary -> Arab
     {0xE6200000u,  1u}, // arz -> Arab
     {0x61730000u,  7u}, // as -> Beng
-    {0x82400000u, 40u}, // asa -> Latn
-    {0x92400000u, 68u}, // ase -> Sgnw
-    {0x9A400000u, 40u}, // asg -> Latn
-    {0xBA400000u, 40u}, // aso -> Latn
-    {0xCE400000u, 40u}, // ast -> Latn
-    {0x82600000u, 40u}, // ata -> Latn
-    {0x9A600000u, 40u}, // atg -> Latn
-    {0xA6600000u, 40u}, // atj -> Latn
-    {0xE2800000u, 40u}, // auy -> Latn
-    {0x61760000u, 15u}, // av -> Cyrl
+    {0x82400000u, 44u}, // asa -> Latn
+    {0x92400000u, 73u}, // ase -> Sgnw
+    {0x9A400000u, 44u}, // asg -> Latn
+    {0xBA400000u, 44u}, // aso -> Latn
+    {0xCE400000u, 44u}, // ast -> Latn
+    {0x82600000u, 44u}, // ata -> Latn
+    {0x9A600000u, 44u}, // atg -> Latn
+    {0xA6600000u, 44u}, // atj -> Latn
+    {0xE2800000u, 44u}, // auy -> Latn
+    {0x61760000u, 16u}, // av -> Cyrl
     {0xAEA00000u,  1u}, // avl -> Arab
-    {0xB6A00000u, 40u}, // avn -> Latn
-    {0xCEA00000u, 40u}, // avt -> Latn
-    {0xD2A00000u, 40u}, // avu -> Latn
-    {0x82C00000u, 16u}, // awa -> Deva
-    {0x86C00000u, 40u}, // awb -> Latn
-    {0xBAC00000u, 40u}, // awo -> Latn
-    {0xDEC00000u, 40u}, // awx -> Latn
-    {0x61790000u, 40u}, // ay -> Latn
-    {0x87000000u, 40u}, // ayb -> Latn
-    {0x617A0000u, 40u}, // az -> Latn
+    {0xB6A00000u, 44u}, // avn -> Latn
+    {0xCEA00000u, 44u}, // avt -> Latn
+    {0xD2A00000u, 44u}, // avu -> Latn
+    {0x82C00000u, 17u}, // awa -> Deva
+    {0x86C00000u, 44u}, // awb -> Latn
+    {0xBAC00000u, 44u}, // awo -> Latn
+    {0xDEC00000u, 44u}, // awx -> Latn
+    {0x61790000u, 44u}, // ay -> Latn
+    {0x87000000u, 44u}, // ayb -> Latn
+    {0x617A0000u, 44u}, // az -> Latn
     {0x617A4951u,  1u}, // az-IQ -> Arab
     {0x617A4952u,  1u}, // az-IR -> Arab
-    {0x617A5255u, 15u}, // az-RU -> Cyrl
-    {0x62610000u, 15u}, // ba -> Cyrl
+    {0x617A5255u, 16u}, // az-RU -> Cyrl
+    {0x62610000u, 16u}, // ba -> Cyrl
     {0xAC010000u,  1u}, // bal -> Arab
-    {0xB4010000u, 40u}, // ban -> Latn
-    {0xBC010000u, 16u}, // bap -> Deva
-    {0xC4010000u, 40u}, // bar -> Latn
-    {0xC8010000u, 40u}, // bas -> Latn
-    {0xD4010000u, 40u}, // bav -> Latn
+    {0xB4010000u, 44u}, // ban -> Latn
+    {0xBC010000u, 17u}, // bap -> Deva
+    {0xC4010000u, 44u}, // bar -> Latn
+    {0xC8010000u, 44u}, // bas -> Latn
+    {0xD4010000u, 44u}, // bav -> Latn
     {0xDC010000u,  5u}, // bax -> Bamu
-    {0x80210000u, 40u}, // bba -> Latn
-    {0x84210000u, 40u}, // bbb -> Latn
-    {0x88210000u, 40u}, // bbc -> Latn
-    {0x8C210000u, 40u}, // bbd -> Latn
-    {0xA4210000u, 40u}, // bbj -> Latn
-    {0xBC210000u, 40u}, // bbp -> Latn
-    {0xC4210000u, 40u}, // bbr -> Latn
-    {0x94410000u, 40u}, // bcf -> Latn
-    {0x9C410000u, 40u}, // bch -> Latn
-    {0xA0410000u, 40u}, // bci -> Latn
-    {0xB0410000u, 40u}, // bcm -> Latn
-    {0xB4410000u, 40u}, // bcn -> Latn
-    {0xB8410000u, 40u}, // bco -> Latn
-    {0xC0410000u, 18u}, // bcq -> Ethi
-    {0xD0410000u, 40u}, // bcu -> Latn
-    {0x8C610000u, 40u}, // bdd -> Latn
-    {0x62650000u, 15u}, // be -> Cyrl
-    {0x94810000u, 40u}, // bef -> Latn
-    {0x9C810000u, 40u}, // beh -> Latn
+    {0x80210000u, 44u}, // bba -> Latn
+    {0x84210000u, 44u}, // bbb -> Latn
+    {0x88210000u, 44u}, // bbc -> Latn
+    {0x8C210000u, 44u}, // bbd -> Latn
+    {0xA4210000u, 44u}, // bbj -> Latn
+    {0xBC210000u, 44u}, // bbp -> Latn
+    {0xC4210000u, 44u}, // bbr -> Latn
+    {0x94410000u, 44u}, // bcf -> Latn
+    {0x9C410000u, 44u}, // bch -> Latn
+    {0xA0410000u, 44u}, // bci -> Latn
+    {0xB0410000u, 44u}, // bcm -> Latn
+    {0xB4410000u, 44u}, // bcn -> Latn
+    {0xB8410000u, 44u}, // bco -> Latn
+    {0xC0410000u, 19u}, // bcq -> Ethi
+    {0xD0410000u, 44u}, // bcu -> Latn
+    {0x8C610000u, 44u}, // bdd -> Latn
+    {0x62650000u, 16u}, // be -> Cyrl
+    {0x94810000u, 44u}, // bef -> Latn
+    {0x9C810000u, 44u}, // beh -> Latn
     {0xA4810000u,  1u}, // bej -> Arab
-    {0xB0810000u, 40u}, // bem -> Latn
-    {0xCC810000u, 40u}, // bet -> Latn
-    {0xD8810000u, 40u}, // bew -> Latn
-    {0xDC810000u, 40u}, // bex -> Latn
-    {0xE4810000u, 40u}, // bez -> Latn
-    {0x8CA10000u, 40u}, // bfd -> Latn
-    {0xC0A10000u, 74u}, // bfq -> Taml
+    {0xB0810000u, 44u}, // bem -> Latn
+    {0xCC810000u, 44u}, // bet -> Latn
+    {0xD8810000u, 44u}, // bew -> Latn
+    {0xDC810000u, 44u}, // bex -> Latn
+    {0xE4810000u, 44u}, // bez -> Latn
+    {0x8CA10000u, 44u}, // bfd -> Latn
+    {0xC0A10000u, 81u}, // bfq -> Taml
     {0xCCA10000u,  1u}, // bft -> Arab
-    {0xE0A10000u, 16u}, // bfy -> Deva
-    {0x62670000u, 15u}, // bg -> Cyrl
-    {0x88C10000u, 16u}, // bgc -> Deva
+    {0xE0A10000u, 17u}, // bfy -> Deva
+    {0x62670000u, 16u}, // bg -> Cyrl
+    {0x88C10000u, 17u}, // bgc -> Deva
     {0xB4C10000u,  1u}, // bgn -> Arab
-    {0xDCC10000u, 21u}, // bgx -> Grek
-    {0x84E10000u, 16u}, // bhb -> Deva
-    {0x98E10000u, 40u}, // bhg -> Latn
-    {0xA0E10000u, 16u}, // bhi -> Deva
-    {0xA8E10000u, 40u}, // bhk -> Latn
-    {0xACE10000u, 40u}, // bhl -> Latn
-    {0xB8E10000u, 16u}, // bho -> Deva
-    {0xE0E10000u, 40u}, // bhy -> Latn
-    {0x62690000u, 40u}, // bi -> Latn
-    {0x85010000u, 40u}, // bib -> Latn
-    {0x99010000u, 40u}, // big -> Latn
-    {0xA9010000u, 40u}, // bik -> Latn
-    {0xB1010000u, 40u}, // bim -> Latn
-    {0xB5010000u, 40u}, // bin -> Latn
-    {0xB9010000u, 40u}, // bio -> Latn
-    {0xC1010000u, 40u}, // biq -> Latn
-    {0x9D210000u, 40u}, // bjh -> Latn
-    {0xA1210000u, 18u}, // bji -> Ethi
-    {0xA5210000u, 16u}, // bjj -> Deva
-    {0xB5210000u, 40u}, // bjn -> Latn
-    {0xB9210000u, 40u}, // bjo -> Latn
-    {0xC5210000u, 40u}, // bjr -> Latn
-    {0xE5210000u, 40u}, // bjz -> Latn
-    {0x89410000u, 40u}, // bkc -> Latn
-    {0xB1410000u, 40u}, // bkm -> Latn
-    {0xC1410000u, 40u}, // bkq -> Latn
-    {0xD1410000u, 40u}, // bku -> Latn
-    {0xD5410000u, 40u}, // bkv -> Latn
-    {0xCD610000u, 76u}, // blt -> Tavt
-    {0x626D0000u, 40u}, // bm -> Latn
-    {0x9D810000u, 40u}, // bmh -> Latn
-    {0xA9810000u, 40u}, // bmk -> Latn
-    {0xC1810000u, 40u}, // bmq -> Latn
-    {0xD1810000u, 40u}, // bmu -> Latn
+    {0xDCC10000u, 24u}, // bgx -> Grek
+    {0x84E10000u, 17u}, // bhb -> Deva
+    {0x98E10000u, 44u}, // bhg -> Latn
+    {0xA0E10000u, 17u}, // bhi -> Deva
+    {0xACE10000u, 44u}, // bhl -> Latn
+    {0xB8E10000u, 17u}, // bho -> Deva
+    {0xE0E10000u, 44u}, // bhy -> Latn
+    {0x62690000u, 44u}, // bi -> Latn
+    {0x85010000u, 44u}, // bib -> Latn
+    {0x99010000u, 44u}, // big -> Latn
+    {0xA9010000u, 44u}, // bik -> Latn
+    {0xB1010000u, 44u}, // bim -> Latn
+    {0xB5010000u, 44u}, // bin -> Latn
+    {0xB9010000u, 44u}, // bio -> Latn
+    {0xC1010000u, 44u}, // biq -> Latn
+    {0x9D210000u, 44u}, // bjh -> Latn
+    {0xA1210000u, 19u}, // bji -> Ethi
+    {0xA5210000u, 17u}, // bjj -> Deva
+    {0xB5210000u, 44u}, // bjn -> Latn
+    {0xB9210000u, 44u}, // bjo -> Latn
+    {0xC5210000u, 44u}, // bjr -> Latn
+    {0xCD210000u, 44u}, // bjt -> Latn
+    {0xE5210000u, 44u}, // bjz -> Latn
+    {0x89410000u, 44u}, // bkc -> Latn
+    {0xB1410000u, 44u}, // bkm -> Latn
+    {0xC1410000u, 44u}, // bkq -> Latn
+    {0xD1410000u, 44u}, // bku -> Latn
+    {0xD5410000u, 44u}, // bkv -> Latn
+    {0xCD610000u, 83u}, // blt -> Tavt
+    {0x626D0000u, 44u}, // bm -> Latn
+    {0x9D810000u, 44u}, // bmh -> Latn
+    {0xA9810000u, 44u}, // bmk -> Latn
+    {0xC1810000u, 44u}, // bmq -> Latn
+    {0xD1810000u, 44u}, // bmu -> Latn
     {0x626E0000u,  7u}, // bn -> Beng
-    {0x99A10000u, 40u}, // bng -> Latn
-    {0xB1A10000u, 40u}, // bnm -> Latn
-    {0xBDA10000u, 40u}, // bnp -> Latn
-    {0x626F0000u, 81u}, // bo -> Tibt
-    {0xA5C10000u, 40u}, // boj -> Latn
-    {0xB1C10000u, 40u}, // bom -> Latn
-    {0xB5C10000u, 40u}, // bon -> Latn
+    {0x99A10000u, 44u}, // bng -> Latn
+    {0xB1A10000u, 44u}, // bnm -> Latn
+    {0xBDA10000u, 44u}, // bnp -> Latn
+    {0x626F0000u, 88u}, // bo -> Tibt
+    {0xA5C10000u, 44u}, // boj -> Latn
+    {0xB1C10000u, 44u}, // bom -> Latn
+    {0xB5C10000u, 44u}, // bon -> Latn
     {0xE1E10000u,  7u}, // bpy -> Beng
-    {0x8A010000u, 40u}, // bqc -> Latn
+    {0x8A010000u, 44u}, // bqc -> Latn
     {0xA2010000u,  1u}, // bqi -> Arab
-    {0xBE010000u, 40u}, // bqp -> Latn
-    {0xD6010000u, 40u}, // bqv -> Latn
-    {0x62720000u, 40u}, // br -> Latn
-    {0x82210000u, 16u}, // bra -> Deva
+    {0xBE010000u, 44u}, // bqp -> Latn
+    {0xD6010000u, 44u}, // bqv -> Latn
+    {0x62720000u, 44u}, // br -> Latn
+    {0x82210000u, 17u}, // bra -> Deva
     {0x9E210000u,  1u}, // brh -> Arab
-    {0xDE210000u, 16u}, // brx -> Deva
-    {0xE6210000u, 40u}, // brz -> Latn
-    {0x62730000u, 40u}, // bs -> Latn
-    {0xA6410000u, 40u}, // bsj -> Latn
+    {0xDE210000u, 17u}, // brx -> Deva
+    {0xE6210000u, 44u}, // brz -> Latn
+    {0x62730000u, 44u}, // bs -> Latn
+    {0xA6410000u, 44u}, // bsj -> Latn
     {0xC2410000u,  6u}, // bsq -> Bass
-    {0xCA410000u, 40u}, // bss -> Latn
-    {0xCE410000u, 18u}, // bst -> Ethi
-    {0xBA610000u, 40u}, // bto -> Latn
-    {0xCE610000u, 40u}, // btt -> Latn
-    {0xD6610000u, 16u}, // btv -> Deva
-    {0x82810000u, 15u}, // bua -> Cyrl
-    {0x8A810000u, 40u}, // buc -> Latn
-    {0x8E810000u, 40u}, // bud -> Latn
-    {0x9A810000u, 40u}, // bug -> Latn
-    {0xAA810000u, 40u}, // buk -> Latn
-    {0xB2810000u, 40u}, // bum -> Latn
-    {0xBA810000u, 40u}, // buo -> Latn
-    {0xCA810000u, 40u}, // bus -> Latn
-    {0xD2810000u, 40u}, // buu -> Latn
-    {0x86A10000u, 40u}, // bvb -> Latn
-    {0x8EC10000u, 40u}, // bwd -> Latn
-    {0xC6C10000u, 40u}, // bwr -> Latn
-    {0x9EE10000u, 40u}, // bxh -> Latn
-    {0x93010000u, 40u}, // bye -> Latn
-    {0xB7010000u, 18u}, // byn -> Ethi
-    {0xC7010000u, 40u}, // byr -> Latn
-    {0xCB010000u, 40u}, // bys -> Latn
-    {0xD7010000u, 40u}, // byv -> Latn
-    {0xDF010000u, 40u}, // byx -> Latn
-    {0x83210000u, 40u}, // bza -> Latn
-    {0x93210000u, 40u}, // bze -> Latn
-    {0x97210000u, 40u}, // bzf -> Latn
-    {0x9F210000u, 40u}, // bzh -> Latn
-    {0xDB210000u, 40u}, // bzw -> Latn
-    {0x63610000u, 40u}, // ca -> Latn
-    {0xB4020000u, 40u}, // can -> Latn
-    {0xA4220000u, 40u}, // cbj -> Latn
-    {0x9C420000u, 40u}, // cch -> Latn
-    {0xBC420000u,  7u}, // ccp -> Beng
-    {0x63650000u, 15u}, // ce -> Cyrl
-    {0x84820000u, 40u}, // ceb -> Latn
-    {0x80A20000u, 40u}, // cfa -> Latn
-    {0x98C20000u, 40u}, // cgg -> Latn
-    {0x63680000u, 40u}, // ch -> Latn
-    {0xA8E20000u, 40u}, // chk -> Latn
-    {0xB0E20000u, 15u}, // chm -> Cyrl
-    {0xB8E20000u, 40u}, // cho -> Latn
-    {0xBCE20000u, 40u}, // chp -> Latn
-    {0xC4E20000u, 12u}, // chr -> Cher
+    {0xCA410000u, 44u}, // bss -> Latn
+    {0xCE410000u, 19u}, // bst -> Ethi
+    {0xBA610000u, 44u}, // bto -> Latn
+    {0xCE610000u, 44u}, // btt -> Latn
+    {0xD6610000u, 17u}, // btv -> Deva
+    {0x82810000u, 16u}, // bua -> Cyrl
+    {0x8A810000u, 44u}, // buc -> Latn
+    {0x8E810000u, 44u}, // bud -> Latn
+    {0x9A810000u, 44u}, // bug -> Latn
+    {0xAA810000u, 44u}, // buk -> Latn
+    {0xB2810000u, 44u}, // bum -> Latn
+    {0xBA810000u, 44u}, // buo -> Latn
+    {0xCA810000u, 44u}, // bus -> Latn
+    {0xD2810000u, 44u}, // buu -> Latn
+    {0x86A10000u, 44u}, // bvb -> Latn
+    {0x8EC10000u, 44u}, // bwd -> Latn
+    {0xC6C10000u, 44u}, // bwr -> Latn
+    {0x9EE10000u, 44u}, // bxh -> Latn
+    {0x93010000u, 44u}, // bye -> Latn
+    {0xB7010000u, 19u}, // byn -> Ethi
+    {0xC7010000u, 44u}, // byr -> Latn
+    {0xCB010000u, 44u}, // bys -> Latn
+    {0xD7010000u, 44u}, // byv -> Latn
+    {0xDF010000u, 44u}, // byx -> Latn
+    {0x83210000u, 44u}, // bza -> Latn
+    {0x93210000u, 44u}, // bze -> Latn
+    {0x97210000u, 44u}, // bzf -> Latn
+    {0x9F210000u, 44u}, // bzh -> Latn
+    {0xDB210000u, 44u}, // bzw -> Latn
+    {0x63610000u, 44u}, // ca -> Latn
+    {0xB4020000u, 44u}, // can -> Latn
+    {0xA4220000u, 44u}, // cbj -> Latn
+    {0x9C420000u, 44u}, // cch -> Latn
+    {0xBC420000u,  9u}, // ccp -> Cakm
+    {0x63650000u, 16u}, // ce -> Cyrl
+    {0x84820000u, 44u}, // ceb -> Latn
+    {0x80A20000u, 44u}, // cfa -> Latn
+    {0x98C20000u, 44u}, // cgg -> Latn
+    {0x63680000u, 44u}, // ch -> Latn
+    {0xA8E20000u, 44u}, // chk -> Latn
+    {0xB0E20000u, 16u}, // chm -> Cyrl
+    {0xB8E20000u, 44u}, // cho -> Latn
+    {0xBCE20000u, 44u}, // chp -> Latn
+    {0xC4E20000u, 13u}, // chr -> Cher
+    {0x89020000u, 44u}, // cic -> Latn
     {0x81220000u,  1u}, // cja -> Arab
-    {0xB1220000u, 11u}, // cjm -> Cham
-    {0xD5220000u, 40u}, // cjv -> Latn
+    {0xB1220000u, 12u}, // cjm -> Cham
+    {0xD5220000u, 44u}, // cjv -> Latn
     {0x85420000u,  1u}, // ckb -> Arab
-    {0xAD420000u, 40u}, // ckl -> Latn
-    {0xB9420000u, 40u}, // cko -> Latn
-    {0xE1420000u, 40u}, // cky -> Latn
-    {0x81620000u, 40u}, // cla -> Latn
-    {0x91820000u, 40u}, // cme -> Latn
-    {0x636F0000u, 40u}, // co -> Latn
-    {0xBDC20000u, 13u}, // cop -> Copt
-    {0xC9E20000u, 40u}, // cps -> Latn
-    {0x63720000u,  9u}, // cr -> Cans
-    {0xA6220000u,  9u}, // crj -> Cans
-    {0xAA220000u,  9u}, // crk -> Cans
-    {0xAE220000u,  9u}, // crl -> Cans
-    {0xB2220000u,  9u}, // crm -> Cans
-    {0xCA220000u, 40u}, // crs -> Latn
-    {0x63730000u, 40u}, // cs -> Latn
-    {0x86420000u, 40u}, // csb -> Latn
-    {0xDA420000u,  9u}, // csw -> Cans
-    {0x8E620000u, 59u}, // ctd -> Pauc
-    {0x63750000u, 15u}, // cu -> Cyrl
-    {0x63760000u, 15u}, // cv -> Cyrl
-    {0x63790000u, 40u}, // cy -> Latn
-    {0x64610000u, 40u}, // da -> Latn
-    {0x8C030000u, 40u}, // dad -> Latn
-    {0x94030000u, 40u}, // daf -> Latn
-    {0x98030000u, 40u}, // dag -> Latn
-    {0x9C030000u, 40u}, // dah -> Latn
-    {0xA8030000u, 40u}, // dak -> Latn
-    {0xC4030000u, 15u}, // dar -> Cyrl
-    {0xD4030000u, 40u}, // dav -> Latn
-    {0x8C230000u, 40u}, // dbd -> Latn
-    {0xC0230000u, 40u}, // dbq -> Latn
+    {0xAD420000u, 44u}, // ckl -> Latn
+    {0xB9420000u, 44u}, // cko -> Latn
+    {0xE1420000u, 44u}, // cky -> Latn
+    {0x81620000u, 44u}, // cla -> Latn
+    {0x91820000u, 44u}, // cme -> Latn
+    {0x99820000u, 77u}, // cmg -> Soyo
+    {0x636F0000u, 44u}, // co -> Latn
+    {0xBDC20000u, 14u}, // cop -> Copt
+    {0xC9E20000u, 44u}, // cps -> Latn
+    {0x63720000u, 10u}, // cr -> Cans
+    {0x9E220000u, 16u}, // crh -> Cyrl
+    {0xA6220000u, 10u}, // crj -> Cans
+    {0xAA220000u, 10u}, // crk -> Cans
+    {0xAE220000u, 10u}, // crl -> Cans
+    {0xB2220000u, 10u}, // crm -> Cans
+    {0xCA220000u, 44u}, // crs -> Latn
+    {0x63730000u, 44u}, // cs -> Latn
+    {0x86420000u, 44u}, // csb -> Latn
+    {0xDA420000u, 10u}, // csw -> Cans
+    {0x8E620000u, 64u}, // ctd -> Pauc
+    {0x63750000u, 16u}, // cu -> Cyrl
+    {0x63760000u, 16u}, // cv -> Cyrl
+    {0x63790000u, 44u}, // cy -> Latn
+    {0x64610000u, 44u}, // da -> Latn
+    {0x8C030000u, 44u}, // dad -> Latn
+    {0x94030000u, 44u}, // daf -> Latn
+    {0x98030000u, 44u}, // dag -> Latn
+    {0x9C030000u, 44u}, // dah -> Latn
+    {0xA8030000u, 44u}, // dak -> Latn
+    {0xC4030000u, 16u}, // dar -> Cyrl
+    {0xD4030000u, 44u}, // dav -> Latn
+    {0x8C230000u, 44u}, // dbd -> Latn
+    {0xC0230000u, 44u}, // dbq -> Latn
     {0x88430000u,  1u}, // dcc -> Arab
-    {0xB4630000u, 40u}, // ddn -> Latn
-    {0x64650000u, 40u}, // de -> Latn
-    {0x8C830000u, 40u}, // ded -> Latn
-    {0xB4830000u, 40u}, // den -> Latn
-    {0x80C30000u, 40u}, // dga -> Latn
-    {0x9CC30000u, 40u}, // dgh -> Latn
-    {0xA0C30000u, 40u}, // dgi -> Latn
+    {0xB4630000u, 44u}, // ddn -> Latn
+    {0x64650000u, 44u}, // de -> Latn
+    {0x8C830000u, 44u}, // ded -> Latn
+    {0xB4830000u, 44u}, // den -> Latn
+    {0x80C30000u, 44u}, // dga -> Latn
+    {0x9CC30000u, 44u}, // dgh -> Latn
+    {0xA0C30000u, 44u}, // dgi -> Latn
     {0xACC30000u,  1u}, // dgl -> Arab
-    {0xC4C30000u, 40u}, // dgr -> Latn
-    {0xE4C30000u, 40u}, // dgz -> Latn
-    {0x81030000u, 40u}, // dia -> Latn
-    {0x91230000u, 40u}, // dje -> Latn
-    {0xA5A30000u, 40u}, // dnj -> Latn
-    {0x85C30000u, 40u}, // dob -> Latn
+    {0xC4C30000u, 44u}, // dgr -> Latn
+    {0xE4C30000u, 44u}, // dgz -> Latn
+    {0x81030000u, 44u}, // dia -> Latn
+    {0x91230000u, 44u}, // dje -> Latn
+    {0xA5A30000u, 44u}, // dnj -> Latn
+    {0x85C30000u, 44u}, // dob -> Latn
     {0xA1C30000u,  1u}, // doi -> Arab
-    {0xBDC30000u, 40u}, // dop -> Latn
-    {0xD9C30000u, 40u}, // dow -> Latn
-    {0xA2230000u, 40u}, // dri -> Latn
-    {0xCA230000u, 18u}, // drs -> Ethi
-    {0x86430000u, 40u}, // dsb -> Latn
-    {0xB2630000u, 40u}, // dtm -> Latn
-    {0xBE630000u, 40u}, // dtp -> Latn
-    {0xCA630000u, 40u}, // dts -> Latn
-    {0xE2630000u, 16u}, // dty -> Deva
-    {0x82830000u, 40u}, // dua -> Latn
-    {0x8A830000u, 40u}, // duc -> Latn
-    {0x8E830000u, 40u}, // dud -> Latn
-    {0x9A830000u, 40u}, // dug -> Latn
-    {0x64760000u, 79u}, // dv -> Thaa
-    {0x82A30000u, 40u}, // dva -> Latn
-    {0xDAC30000u, 40u}, // dww -> Latn
-    {0xBB030000u, 40u}, // dyo -> Latn
-    {0xD3030000u, 40u}, // dyu -> Latn
-    {0x647A0000u, 81u}, // dz -> Tibt
-    {0x9B230000u, 40u}, // dzg -> Latn
-    {0xD0240000u, 40u}, // ebu -> Latn
-    {0x65650000u, 40u}, // ee -> Latn
-    {0xA0A40000u, 40u}, // efi -> Latn
-    {0xACC40000u, 40u}, // egl -> Latn
-    {0xE0C40000u, 17u}, // egy -> Egyp
-    {0xE1440000u, 32u}, // eky -> Kali
-    {0x656C0000u, 21u}, // el -> Grek
-    {0x81840000u, 40u}, // ema -> Latn
-    {0xA1840000u, 40u}, // emi -> Latn
-    {0x656E0000u, 40u}, // en -> Latn
-    {0x656E5841u, 87u}, // en-XA -> ~~~A
-    {0xB5A40000u, 40u}, // enn -> Latn
-    {0xC1A40000u, 40u}, // enq -> Latn
-    {0x656F0000u, 40u}, // eo -> Latn
-    {0xA2240000u, 40u}, // eri -> Latn
-    {0x65730000u, 40u}, // es -> Latn
-    {0xD2440000u, 40u}, // esu -> Latn
-    {0x65740000u, 40u}, // et -> Latn
-    {0xC6640000u, 40u}, // etr -> Latn
-    {0xCE640000u, 30u}, // ett -> Ital
-    {0xD2640000u, 40u}, // etu -> Latn
-    {0xDE640000u, 40u}, // etx -> Latn
-    {0x65750000u, 40u}, // eu -> Latn
-    {0xBAC40000u, 40u}, // ewo -> Latn
-    {0xCEE40000u, 40u}, // ext -> Latn
+    {0xBDC30000u, 44u}, // dop -> Latn
+    {0xD9C30000u, 44u}, // dow -> Latn
+    {0x9E230000u, 54u}, // drh -> Mong
+    {0xA2230000u, 44u}, // dri -> Latn
+    {0xCA230000u, 19u}, // drs -> Ethi
+    {0x86430000u, 44u}, // dsb -> Latn
+    {0xB2630000u, 44u}, // dtm -> Latn
+    {0xBE630000u, 44u}, // dtp -> Latn
+    {0xCA630000u, 44u}, // dts -> Latn
+    {0xE2630000u, 17u}, // dty -> Deva
+    {0x82830000u, 44u}, // dua -> Latn
+    {0x8A830000u, 44u}, // duc -> Latn
+    {0x8E830000u, 44u}, // dud -> Latn
+    {0x9A830000u, 44u}, // dug -> Latn
+    {0x64760000u, 86u}, // dv -> Thaa
+    {0x82A30000u, 44u}, // dva -> Latn
+    {0xDAC30000u, 44u}, // dww -> Latn
+    {0xBB030000u, 44u}, // dyo -> Latn
+    {0xD3030000u, 44u}, // dyu -> Latn
+    {0x647A0000u, 88u}, // dz -> Tibt
+    {0x9B230000u, 44u}, // dzg -> Latn
+    {0xD0240000u, 44u}, // ebu -> Latn
+    {0x65650000u, 44u}, // ee -> Latn
+    {0xA0A40000u, 44u}, // efi -> Latn
+    {0xACC40000u, 44u}, // egl -> Latn
+    {0xE0C40000u, 18u}, // egy -> Egyp
+    {0x81440000u, 44u}, // eka -> Latn
+    {0xE1440000u, 36u}, // eky -> Kali
+    {0x656C0000u, 24u}, // el -> Grek
+    {0x81840000u, 44u}, // ema -> Latn
+    {0xA1840000u, 44u}, // emi -> Latn
+    {0x656E0000u, 44u}, // en -> Latn
+    {0x656E5841u, 95u}, // en-XA -> ~~~A
+    {0xB5A40000u, 44u}, // enn -> Latn
+    {0xC1A40000u, 44u}, // enq -> Latn
+    {0x656F0000u, 44u}, // eo -> Latn
+    {0xA2240000u, 44u}, // eri -> Latn
+    {0x65730000u, 44u}, // es -> Latn
+    {0x9A440000u, 22u}, // esg -> Gonm
+    {0xD2440000u, 44u}, // esu -> Latn
+    {0x65740000u, 44u}, // et -> Latn
+    {0xC6640000u, 44u}, // etr -> Latn
+    {0xCE640000u, 34u}, // ett -> Ital
+    {0xD2640000u, 44u}, // etu -> Latn
+    {0xDE640000u, 44u}, // etx -> Latn
+    {0x65750000u, 44u}, // eu -> Latn
+    {0xBAC40000u, 44u}, // ewo -> Latn
+    {0xCEE40000u, 44u}, // ext -> Latn
     {0x66610000u,  1u}, // fa -> Arab
-    {0x80050000u, 40u}, // faa -> Latn
-    {0x84050000u, 40u}, // fab -> Latn
-    {0x98050000u, 40u}, // fag -> Latn
-    {0xA0050000u, 40u}, // fai -> Latn
-    {0xB4050000u, 40u}, // fan -> Latn
-    {0x66660000u, 40u}, // ff -> Latn
-    {0xA0A50000u, 40u}, // ffi -> Latn
-    {0xB0A50000u, 40u}, // ffm -> Latn
-    {0x66690000u, 40u}, // fi -> Latn
+    {0x80050000u, 44u}, // faa -> Latn
+    {0x84050000u, 44u}, // fab -> Latn
+    {0x98050000u, 44u}, // fag -> Latn
+    {0xA0050000u, 44u}, // fai -> Latn
+    {0xB4050000u, 44u}, // fan -> Latn
+    {0x66660000u, 44u}, // ff -> Latn
+    {0xA0A50000u, 44u}, // ffi -> Latn
+    {0xB0A50000u, 44u}, // ffm -> Latn
+    {0x66690000u, 44u}, // fi -> Latn
     {0x81050000u,  1u}, // fia -> Arab
-    {0xAD050000u, 40u}, // fil -> Latn
-    {0xCD050000u, 40u}, // fit -> Latn
-    {0x666A0000u, 40u}, // fj -> Latn
-    {0xC5650000u, 40u}, // flr -> Latn
-    {0xBD850000u, 40u}, // fmp -> Latn
-    {0x666F0000u, 40u}, // fo -> Latn
-    {0x8DC50000u, 40u}, // fod -> Latn
-    {0xB5C50000u, 40u}, // fon -> Latn
-    {0xC5C50000u, 40u}, // for -> Latn
-    {0x91E50000u, 40u}, // fpe -> Latn
-    {0xCA050000u, 40u}, // fqs -> Latn
-    {0x66720000u, 40u}, // fr -> Latn
-    {0x8A250000u, 40u}, // frc -> Latn
-    {0xBE250000u, 40u}, // frp -> Latn
-    {0xC6250000u, 40u}, // frr -> Latn
-    {0xCA250000u, 40u}, // frs -> Latn
+    {0xAD050000u, 44u}, // fil -> Latn
+    {0xCD050000u, 44u}, // fit -> Latn
+    {0x666A0000u, 44u}, // fj -> Latn
+    {0xC5650000u, 44u}, // flr -> Latn
+    {0xBD850000u, 44u}, // fmp -> Latn
+    {0x666F0000u, 44u}, // fo -> Latn
+    {0x8DC50000u, 44u}, // fod -> Latn
+    {0xB5C50000u, 44u}, // fon -> Latn
+    {0xC5C50000u, 44u}, // for -> Latn
+    {0x91E50000u, 44u}, // fpe -> Latn
+    {0xCA050000u, 44u}, // fqs -> Latn
+    {0x66720000u, 44u}, // fr -> Latn
+    {0x8A250000u, 44u}, // frc -> Latn
+    {0xBE250000u, 44u}, // frp -> Latn
+    {0xC6250000u, 44u}, // frr -> Latn
+    {0xCA250000u, 44u}, // frs -> Latn
     {0x86850000u,  1u}, // fub -> Arab
-    {0x8E850000u, 40u}, // fud -> Latn
-    {0x92850000u, 40u}, // fue -> Latn
-    {0x96850000u, 40u}, // fuf -> Latn
-    {0x9E850000u, 40u}, // fuh -> Latn
-    {0xC2850000u, 40u}, // fuq -> Latn
-    {0xC6850000u, 40u}, // fur -> Latn
-    {0xD6850000u, 40u}, // fuv -> Latn
-    {0xE2850000u, 40u}, // fuy -> Latn
-    {0xC6A50000u, 40u}, // fvr -> Latn
-    {0x66790000u, 40u}, // fy -> Latn
-    {0x67610000u, 40u}, // ga -> Latn
-    {0x80060000u, 40u}, // gaa -> Latn
-    {0x94060000u, 40u}, // gaf -> Latn
-    {0x98060000u, 40u}, // gag -> Latn
-    {0x9C060000u, 40u}, // gah -> Latn
-    {0xA4060000u, 40u}, // gaj -> Latn
-    {0xB0060000u, 40u}, // gam -> Latn
-    {0xB4060000u, 24u}, // gan -> Hans
-    {0xD8060000u, 40u}, // gaw -> Latn
-    {0xE0060000u, 40u}, // gay -> Latn
-    {0x94260000u, 40u}, // gbf -> Latn
-    {0xB0260000u, 16u}, // gbm -> Deva
-    {0xE0260000u, 40u}, // gby -> Latn
+    {0x8E850000u, 44u}, // fud -> Latn
+    {0x92850000u, 44u}, // fue -> Latn
+    {0x96850000u, 44u}, // fuf -> Latn
+    {0x9E850000u, 44u}, // fuh -> Latn
+    {0xC2850000u, 44u}, // fuq -> Latn
+    {0xC6850000u, 44u}, // fur -> Latn
+    {0xD6850000u, 44u}, // fuv -> Latn
+    {0xE2850000u, 44u}, // fuy -> Latn
+    {0xC6A50000u, 44u}, // fvr -> Latn
+    {0x66790000u, 44u}, // fy -> Latn
+    {0x67610000u, 44u}, // ga -> Latn
+    {0x80060000u, 44u}, // gaa -> Latn
+    {0x94060000u, 44u}, // gaf -> Latn
+    {0x98060000u, 44u}, // gag -> Latn
+    {0x9C060000u, 44u}, // gah -> Latn
+    {0xA4060000u, 44u}, // gaj -> Latn
+    {0xB0060000u, 44u}, // gam -> Latn
+    {0xB4060000u, 27u}, // gan -> Hans
+    {0xD8060000u, 44u}, // gaw -> Latn
+    {0xE0060000u, 44u}, // gay -> Latn
+    {0x80260000u, 44u}, // gba -> Latn
+    {0x94260000u, 44u}, // gbf -> Latn
+    {0xB0260000u, 17u}, // gbm -> Deva
+    {0xE0260000u, 44u}, // gby -> Latn
     {0xE4260000u,  1u}, // gbz -> Arab
-    {0xC4460000u, 40u}, // gcr -> Latn
-    {0x67640000u, 40u}, // gd -> Latn
-    {0x90660000u, 40u}, // gde -> Latn
-    {0xB4660000u, 40u}, // gdn -> Latn
-    {0xC4660000u, 40u}, // gdr -> Latn
-    {0x84860000u, 40u}, // geb -> Latn
-    {0xA4860000u, 40u}, // gej -> Latn
-    {0xAC860000u, 40u}, // gel -> Latn
-    {0xE4860000u, 18u}, // gez -> Ethi
-    {0xA8A60000u, 40u}, // gfk -> Latn
-    {0xB4C60000u, 16u}, // ggn -> Deva
-    {0xC8E60000u, 40u}, // ghs -> Latn
-    {0xAD060000u, 40u}, // gil -> Latn
-    {0xB1060000u, 40u}, // gim -> Latn
+    {0xC4460000u, 44u}, // gcr -> Latn
+    {0x67640000u, 44u}, // gd -> Latn
+    {0x90660000u, 44u}, // gde -> Latn
+    {0xB4660000u, 44u}, // gdn -> Latn
+    {0xC4660000u, 44u}, // gdr -> Latn
+    {0x84860000u, 44u}, // geb -> Latn
+    {0xA4860000u, 44u}, // gej -> Latn
+    {0xAC860000u, 44u}, // gel -> Latn
+    {0xE4860000u, 19u}, // gez -> Ethi
+    {0xA8A60000u, 44u}, // gfk -> Latn
+    {0xB4C60000u, 17u}, // ggn -> Deva
+    {0xC8E60000u, 44u}, // ghs -> Latn
+    {0xAD060000u, 44u}, // gil -> Latn
+    {0xB1060000u, 44u}, // gim -> Latn
     {0xA9260000u,  1u}, // gjk -> Arab
-    {0xB5260000u, 40u}, // gjn -> Latn
+    {0xB5260000u, 44u}, // gjn -> Latn
     {0xD1260000u,  1u}, // gju -> Arab
-    {0xB5460000u, 40u}, // gkn -> Latn
-    {0xBD460000u, 40u}, // gkp -> Latn
-    {0x676C0000u, 40u}, // gl -> Latn
+    {0xB5460000u, 44u}, // gkn -> Latn
+    {0xBD460000u, 44u}, // gkp -> Latn
+    {0x676C0000u, 44u}, // gl -> Latn
     {0xA9660000u,  1u}, // glk -> Arab
-    {0xB1860000u, 40u}, // gmm -> Latn
-    {0xD5860000u, 18u}, // gmv -> Ethi
-    {0x676E0000u, 40u}, // gn -> Latn
-    {0x8DA60000u, 40u}, // gnd -> Latn
-    {0x99A60000u, 40u}, // gng -> Latn
-    {0x8DC60000u, 40u}, // god -> Latn
-    {0x95C60000u, 18u}, // gof -> Ethi
-    {0xA1C60000u, 40u}, // goi -> Latn
-    {0xB1C60000u, 16u}, // gom -> Deva
-    {0xB5C60000u, 77u}, // gon -> Telu
-    {0xC5C60000u, 40u}, // gor -> Latn
-    {0xC9C60000u, 40u}, // gos -> Latn
-    {0xCDC60000u, 20u}, // got -> Goth
-    {0x8A260000u, 14u}, // grc -> Cprt
+    {0xB1860000u, 44u}, // gmm -> Latn
+    {0xD5860000u, 19u}, // gmv -> Ethi
+    {0x676E0000u, 44u}, // gn -> Latn
+    {0x8DA60000u, 44u}, // gnd -> Latn
+    {0x99A60000u, 44u}, // gng -> Latn
+    {0x8DC60000u, 44u}, // god -> Latn
+    {0x95C60000u, 19u}, // gof -> Ethi
+    {0xA1C60000u, 44u}, // goi -> Latn
+    {0xB1C60000u, 17u}, // gom -> Deva
+    {0xB5C60000u, 84u}, // gon -> Telu
+    {0xC5C60000u, 44u}, // gor -> Latn
+    {0xC9C60000u, 44u}, // gos -> Latn
+    {0xCDC60000u, 23u}, // got -> Goth
+    {0x86260000u, 44u}, // grb -> Latn
+    {0x8A260000u, 15u}, // grc -> Cprt
     {0xCE260000u,  7u}, // grt -> Beng
-    {0xDA260000u, 40u}, // grw -> Latn
-    {0xDA460000u, 40u}, // gsw -> Latn
-    {0x67750000u, 22u}, // gu -> Gujr
-    {0x86860000u, 40u}, // gub -> Latn
-    {0x8A860000u, 40u}, // guc -> Latn
-    {0x8E860000u, 40u}, // gud -> Latn
-    {0xC6860000u, 40u}, // gur -> Latn
-    {0xDA860000u, 40u}, // guw -> Latn
-    {0xDE860000u, 40u}, // gux -> Latn
-    {0xE6860000u, 40u}, // guz -> Latn
-    {0x67760000u, 40u}, // gv -> Latn
-    {0x96A60000u, 40u}, // gvf -> Latn
-    {0xC6A60000u, 16u}, // gvr -> Deva
-    {0xCAA60000u, 40u}, // gvs -> Latn
+    {0xDA260000u, 44u}, // grw -> Latn
+    {0xDA460000u, 44u}, // gsw -> Latn
+    {0x67750000u, 25u}, // gu -> Gujr
+    {0x86860000u, 44u}, // gub -> Latn
+    {0x8A860000u, 44u}, // guc -> Latn
+    {0x8E860000u, 44u}, // gud -> Latn
+    {0xC6860000u, 44u}, // gur -> Latn
+    {0xDA860000u, 44u}, // guw -> Latn
+    {0xDE860000u, 44u}, // gux -> Latn
+    {0xE6860000u, 44u}, // guz -> Latn
+    {0x67760000u, 44u}, // gv -> Latn
+    {0x96A60000u, 44u}, // gvf -> Latn
+    {0xC6A60000u, 17u}, // gvr -> Deva
+    {0xCAA60000u, 44u}, // gvs -> Latn
     {0x8AC60000u,  1u}, // gwc -> Arab
-    {0xA2C60000u, 40u}, // gwi -> Latn
+    {0xA2C60000u, 44u}, // gwi -> Latn
     {0xCEC60000u,  1u}, // gwt -> Arab
-    {0xA3060000u, 40u}, // gyi -> Latn
-    {0x68610000u, 40u}, // ha -> Latn
+    {0xA3060000u, 44u}, // gyi -> Latn
+    {0x68610000u, 44u}, // ha -> Latn
     {0x6861434Du,  1u}, // ha-CM -> Arab
     {0x68615344u,  1u}, // ha-SD -> Arab
-    {0x98070000u, 40u}, // hag -> Latn
-    {0xA8070000u, 24u}, // hak -> Hans
-    {0xB0070000u, 40u}, // ham -> Latn
-    {0xD8070000u, 40u}, // haw -> Latn
+    {0x98070000u, 44u}, // hag -> Latn
+    {0xA8070000u, 27u}, // hak -> Hans
+    {0xB0070000u, 44u}, // ham -> Latn
+    {0xD8070000u, 44u}, // haw -> Latn
     {0xE4070000u,  1u}, // haz -> Arab
-    {0x84270000u, 40u}, // hbb -> Latn
-    {0xE0670000u, 18u}, // hdy -> Ethi
-    {0x68650000u, 27u}, // he -> Hebr
-    {0xE0E70000u, 40u}, // hhy -> Latn
-    {0x68690000u, 16u}, // hi -> Deva
-    {0x81070000u, 40u}, // hia -> Latn
-    {0x95070000u, 40u}, // hif -> Latn
-    {0x99070000u, 40u}, // hig -> Latn
-    {0x9D070000u, 40u}, // hih -> Latn
-    {0xAD070000u, 40u}, // hil -> Latn
-    {0x81670000u, 40u}, // hla -> Latn
-    {0xD1670000u, 28u}, // hlu -> Hluw
-    {0x8D870000u, 62u}, // hmd -> Plrd
-    {0xCD870000u, 40u}, // hmt -> Latn
+    {0x84270000u, 44u}, // hbb -> Latn
+    {0xE0670000u, 19u}, // hdy -> Ethi
+    {0x68650000u, 30u}, // he -> Hebr
+    {0xE0E70000u, 44u}, // hhy -> Latn
+    {0x68690000u, 17u}, // hi -> Deva
+    {0x81070000u, 44u}, // hia -> Latn
+    {0x95070000u, 44u}, // hif -> Latn
+    {0x99070000u, 44u}, // hig -> Latn
+    {0x9D070000u, 44u}, // hih -> Latn
+    {0xAD070000u, 44u}, // hil -> Latn
+    {0x81670000u, 44u}, // hla -> Latn
+    {0xD1670000u, 31u}, // hlu -> Hluw
+    {0x8D870000u, 67u}, // hmd -> Plrd
+    {0xCD870000u, 44u}, // hmt -> Latn
     {0x8DA70000u,  1u}, // hnd -> Arab
-    {0x91A70000u, 16u}, // hne -> Deva
-    {0xA5A70000u, 29u}, // hnj -> Hmng
-    {0xB5A70000u, 40u}, // hnn -> Latn
+    {0x91A70000u, 17u}, // hne -> Deva
+    {0xA5A70000u, 32u}, // hnj -> Hmng
+    {0xB5A70000u, 44u}, // hnn -> Latn
     {0xB9A70000u,  1u}, // hno -> Arab
-    {0x686F0000u, 40u}, // ho -> Latn
-    {0x89C70000u, 16u}, // hoc -> Deva
-    {0xA5C70000u, 16u}, // hoj -> Deva
-    {0xCDC70000u, 40u}, // hot -> Latn
-    {0x68720000u, 40u}, // hr -> Latn
-    {0x86470000u, 40u}, // hsb -> Latn
-    {0xB6470000u, 24u}, // hsn -> Hans
-    {0x68740000u, 40u}, // ht -> Latn
-    {0x68750000u, 40u}, // hu -> Latn
-    {0xA2870000u, 40u}, // hui -> Latn
+    {0x686F0000u, 44u}, // ho -> Latn
+    {0x89C70000u, 17u}, // hoc -> Deva
+    {0xA5C70000u, 17u}, // hoj -> Deva
+    {0xCDC70000u, 44u}, // hot -> Latn
+    {0x68720000u, 44u}, // hr -> Latn
+    {0x86470000u, 44u}, // hsb -> Latn
+    {0xB6470000u, 27u}, // hsn -> Hans
+    {0x68740000u, 44u}, // ht -> Latn
+    {0x68750000u, 44u}, // hu -> Latn
+    {0xA2870000u, 44u}, // hui -> Latn
     {0x68790000u,  3u}, // hy -> Armn
-    {0x687A0000u, 40u}, // hz -> Latn
-    {0x69610000u, 40u}, // ia -> Latn
-    {0xB4080000u, 40u}, // ian -> Latn
-    {0xC4080000u, 40u}, // iar -> Latn
-    {0x80280000u, 40u}, // iba -> Latn
-    {0x84280000u, 40u}, // ibb -> Latn
-    {0xE0280000u, 40u}, // iby -> Latn
-    {0x80480000u, 40u}, // ica -> Latn
-    {0x9C480000u, 40u}, // ich -> Latn
-    {0x69640000u, 40u}, // id -> Latn
-    {0x8C680000u, 40u}, // idd -> Latn
-    {0xA0680000u, 40u}, // idi -> Latn
-    {0xD0680000u, 40u}, // idu -> Latn
-    {0x69670000u, 40u}, // ig -> Latn
-    {0x84C80000u, 40u}, // igb -> Latn
-    {0x90C80000u, 40u}, // ige -> Latn
-    {0x69690000u, 86u}, // ii -> Yiii
-    {0xA5280000u, 40u}, // ijj -> Latn
-    {0x696B0000u, 40u}, // ik -> Latn
-    {0xA9480000u, 40u}, // ikk -> Latn
-    {0xCD480000u, 40u}, // ikt -> Latn
-    {0xD9480000u, 40u}, // ikw -> Latn
-    {0xDD480000u, 40u}, // ikx -> Latn
-    {0xB9680000u, 40u}, // ilo -> Latn
-    {0xB9880000u, 40u}, // imo -> Latn
-    {0x696E0000u, 40u}, // in -> Latn
-    {0x9DA80000u, 15u}, // inh -> Cyrl
-    {0xD1C80000u, 40u}, // iou -> Latn
-    {0xA2280000u, 40u}, // iri -> Latn
-    {0x69730000u, 40u}, // is -> Latn
-    {0x69740000u, 40u}, // it -> Latn
-    {0x69750000u,  9u}, // iu -> Cans
-    {0x69770000u, 27u}, // iw -> Hebr
-    {0xB2C80000u, 40u}, // iwm -> Latn
-    {0xCAC80000u, 40u}, // iws -> Latn
-    {0x9F280000u, 40u}, // izh -> Latn
-    {0xA3280000u, 40u}, // izi -> Latn
-    {0x6A610000u, 31u}, // ja -> Jpan
-    {0x84090000u, 40u}, // jab -> Latn
-    {0xB0090000u, 40u}, // jam -> Latn
-    {0xD0290000u, 40u}, // jbu -> Latn
-    {0xB4890000u, 40u}, // jen -> Latn
-    {0xA8C90000u, 40u}, // jgk -> Latn
-    {0xB8C90000u, 40u}, // jgo -> Latn
-    {0x6A690000u, 27u}, // ji -> Hebr
-    {0x85090000u, 40u}, // jib -> Latn
-    {0x89890000u, 40u}, // jmc -> Latn
-    {0xAD890000u, 16u}, // jml -> Deva
-    {0x82290000u, 40u}, // jra -> Latn
-    {0xCE890000u, 40u}, // jut -> Latn
-    {0x6A760000u, 40u}, // jv -> Latn
-    {0x6A770000u, 40u}, // jw -> Latn
-    {0x6B610000u, 19u}, // ka -> Geor
-    {0x800A0000u, 15u}, // kaa -> Cyrl
-    {0x840A0000u, 40u}, // kab -> Latn
-    {0x880A0000u, 40u}, // kac -> Latn
-    {0x8C0A0000u, 40u}, // kad -> Latn
-    {0xA00A0000u, 40u}, // kai -> Latn
-    {0xA40A0000u, 40u}, // kaj -> Latn
-    {0xB00A0000u, 40u}, // kam -> Latn
-    {0xB80A0000u, 40u}, // kao -> Latn
-    {0x8C2A0000u, 15u}, // kbd -> Cyrl
-    {0xB02A0000u, 40u}, // kbm -> Latn
-    {0xBC2A0000u, 40u}, // kbp -> Latn
-    {0xC02A0000u, 40u}, // kbq -> Latn
-    {0xDC2A0000u, 40u}, // kbx -> Latn
+    {0x687A0000u, 44u}, // hz -> Latn
+    {0x69610000u, 44u}, // ia -> Latn
+    {0xB4080000u, 44u}, // ian -> Latn
+    {0xC4080000u, 44u}, // iar -> Latn
+    {0x80280000u, 44u}, // iba -> Latn
+    {0x84280000u, 44u}, // ibb -> Latn
+    {0xE0280000u, 44u}, // iby -> Latn
+    {0x80480000u, 44u}, // ica -> Latn
+    {0x9C480000u, 44u}, // ich -> Latn
+    {0x69640000u, 44u}, // id -> Latn
+    {0x8C680000u, 44u}, // idd -> Latn
+    {0xA0680000u, 44u}, // idi -> Latn
+    {0xD0680000u, 44u}, // idu -> Latn
+    {0x90A80000u, 44u}, // ife -> Latn
+    {0x69670000u, 44u}, // ig -> Latn
+    {0x84C80000u, 44u}, // igb -> Latn
+    {0x90C80000u, 44u}, // ige -> Latn
+    {0x69690000u, 94u}, // ii -> Yiii
+    {0xA5280000u, 44u}, // ijj -> Latn
+    {0x696B0000u, 44u}, // ik -> Latn
+    {0xA9480000u, 44u}, // ikk -> Latn
+    {0xCD480000u, 44u}, // ikt -> Latn
+    {0xD9480000u, 44u}, // ikw -> Latn
+    {0xDD480000u, 44u}, // ikx -> Latn
+    {0xB9680000u, 44u}, // ilo -> Latn
+    {0xB9880000u, 44u}, // imo -> Latn
+    {0x696E0000u, 44u}, // in -> Latn
+    {0x9DA80000u, 16u}, // inh -> Cyrl
+    {0x696F0000u, 44u}, // io -> Latn
+    {0xD1C80000u, 44u}, // iou -> Latn
+    {0xA2280000u, 44u}, // iri -> Latn
+    {0x69730000u, 44u}, // is -> Latn
+    {0x69740000u, 44u}, // it -> Latn
+    {0x69750000u, 10u}, // iu -> Cans
+    {0x69770000u, 30u}, // iw -> Hebr
+    {0xB2C80000u, 44u}, // iwm -> Latn
+    {0xCAC80000u, 44u}, // iws -> Latn
+    {0x9F280000u, 44u}, // izh -> Latn
+    {0xA3280000u, 44u}, // izi -> Latn
+    {0x6A610000u, 35u}, // ja -> Jpan
+    {0x84090000u, 44u}, // jab -> Latn
+    {0xB0090000u, 44u}, // jam -> Latn
+    {0xB8290000u, 44u}, // jbo -> Latn
+    {0xD0290000u, 44u}, // jbu -> Latn
+    {0xB4890000u, 44u}, // jen -> Latn
+    {0xA8C90000u, 44u}, // jgk -> Latn
+    {0xB8C90000u, 44u}, // jgo -> Latn
+    {0x6A690000u, 30u}, // ji -> Hebr
+    {0x85090000u, 44u}, // jib -> Latn
+    {0x89890000u, 44u}, // jmc -> Latn
+    {0xAD890000u, 17u}, // jml -> Deva
+    {0x82290000u, 44u}, // jra -> Latn
+    {0xCE890000u, 44u}, // jut -> Latn
+    {0x6A760000u, 44u}, // jv -> Latn
+    {0x6A770000u, 44u}, // jw -> Latn
+    {0x6B610000u, 20u}, // ka -> Geor
+    {0x800A0000u, 16u}, // kaa -> Cyrl
+    {0x840A0000u, 44u}, // kab -> Latn
+    {0x880A0000u, 44u}, // kac -> Latn
+    {0x8C0A0000u, 44u}, // kad -> Latn
+    {0xA00A0000u, 44u}, // kai -> Latn
+    {0xA40A0000u, 44u}, // kaj -> Latn
+    {0xB00A0000u, 44u}, // kam -> Latn
+    {0xB80A0000u, 44u}, // kao -> Latn
+    {0x8C2A0000u, 16u}, // kbd -> Cyrl
+    {0xB02A0000u, 44u}, // kbm -> Latn
+    {0xBC2A0000u, 44u}, // kbp -> Latn
+    {0xC02A0000u, 44u}, // kbq -> Latn
+    {0xDC2A0000u, 44u}, // kbx -> Latn
     {0xE02A0000u,  1u}, // kby -> Arab
-    {0x984A0000u, 40u}, // kcg -> Latn
-    {0xA84A0000u, 40u}, // kck -> Latn
-    {0xAC4A0000u, 40u}, // kcl -> Latn
-    {0xCC4A0000u, 40u}, // kct -> Latn
-    {0x906A0000u, 40u}, // kde -> Latn
+    {0x984A0000u, 44u}, // kcg -> Latn
+    {0xA84A0000u, 44u}, // kck -> Latn
+    {0xAC4A0000u, 44u}, // kcl -> Latn
+    {0xCC4A0000u, 44u}, // kct -> Latn
+    {0x906A0000u, 44u}, // kde -> Latn
     {0x9C6A0000u,  1u}, // kdh -> Arab
-    {0xAC6A0000u, 40u}, // kdl -> Latn
-    {0xCC6A0000u, 80u}, // kdt -> Thai
-    {0x808A0000u, 40u}, // kea -> Latn
-    {0xB48A0000u, 40u}, // ken -> Latn
-    {0xE48A0000u, 40u}, // kez -> Latn
-    {0xB8AA0000u, 40u}, // kfo -> Latn
-    {0xC4AA0000u, 16u}, // kfr -> Deva
-    {0xE0AA0000u, 16u}, // kfy -> Deva
-    {0x6B670000u, 40u}, // kg -> Latn
-    {0x90CA0000u, 40u}, // kge -> Latn
-    {0x94CA0000u, 40u}, // kgf -> Latn
-    {0xBCCA0000u, 40u}, // kgp -> Latn
-    {0x80EA0000u, 40u}, // kha -> Latn
-    {0x84EA0000u, 73u}, // khb -> Talu
-    {0xB4EA0000u, 16u}, // khn -> Deva
-    {0xC0EA0000u, 40u}, // khq -> Latn
-    {0xC8EA0000u, 40u}, // khs -> Latn
-    {0xCCEA0000u, 52u}, // kht -> Mymr
+    {0xAC6A0000u, 44u}, // kdl -> Latn
+    {0xCC6A0000u, 87u}, // kdt -> Thai
+    {0x808A0000u, 44u}, // kea -> Latn
+    {0xB48A0000u, 44u}, // ken -> Latn
+    {0xE48A0000u, 44u}, // kez -> Latn
+    {0xB8AA0000u, 44u}, // kfo -> Latn
+    {0xC4AA0000u, 17u}, // kfr -> Deva
+    {0xE0AA0000u, 17u}, // kfy -> Deva
+    {0x6B670000u, 44u}, // kg -> Latn
+    {0x90CA0000u, 44u}, // kge -> Latn
+    {0x94CA0000u, 44u}, // kgf -> Latn
+    {0xBCCA0000u, 44u}, // kgp -> Latn
+    {0x80EA0000u, 44u}, // kha -> Latn
+    {0x84EA0000u, 80u}, // khb -> Talu
+    {0xB4EA0000u, 17u}, // khn -> Deva
+    {0xC0EA0000u, 44u}, // khq -> Latn
+    {0xC8EA0000u, 44u}, // khs -> Latn
+    {0xCCEA0000u, 56u}, // kht -> Mymr
     {0xD8EA0000u,  1u}, // khw -> Arab
-    {0xE4EA0000u, 40u}, // khz -> Latn
-    {0x6B690000u, 40u}, // ki -> Latn
-    {0xA50A0000u, 40u}, // kij -> Latn
-    {0xD10A0000u, 40u}, // kiu -> Latn
-    {0xD90A0000u, 40u}, // kiw -> Latn
-    {0x6B6A0000u, 40u}, // kj -> Latn
-    {0x8D2A0000u, 40u}, // kjd -> Latn
-    {0x992A0000u, 39u}, // kjg -> Laoo
-    {0xC92A0000u, 40u}, // kjs -> Latn
-    {0xE12A0000u, 40u}, // kjy -> Latn
-    {0x6B6B0000u, 15u}, // kk -> Cyrl
+    {0xE4EA0000u, 44u}, // khz -> Latn
+    {0x6B690000u, 44u}, // ki -> Latn
+    {0xA50A0000u, 44u}, // kij -> Latn
+    {0xD10A0000u, 44u}, // kiu -> Latn
+    {0xD90A0000u, 44u}, // kiw -> Latn
+    {0x6B6A0000u, 44u}, // kj -> Latn
+    {0x8D2A0000u, 44u}, // kjd -> Latn
+    {0x992A0000u, 43u}, // kjg -> Laoo
+    {0xC92A0000u, 44u}, // kjs -> Latn
+    {0xE12A0000u, 44u}, // kjy -> Latn
+    {0x6B6B0000u, 16u}, // kk -> Cyrl
     {0x6B6B4146u,  1u}, // kk-AF -> Arab
     {0x6B6B434Eu,  1u}, // kk-CN -> Arab
     {0x6B6B4952u,  1u}, // kk-IR -> Arab
     {0x6B6B4D4Eu,  1u}, // kk-MN -> Arab
-    {0x894A0000u, 40u}, // kkc -> Latn
-    {0xA54A0000u, 40u}, // kkj -> Latn
-    {0x6B6C0000u, 40u}, // kl -> Latn
-    {0xB56A0000u, 40u}, // kln -> Latn
-    {0xC16A0000u, 40u}, // klq -> Latn
-    {0xCD6A0000u, 40u}, // klt -> Latn
-    {0xDD6A0000u, 40u}, // klx -> Latn
-    {0x6B6D0000u, 35u}, // km -> Khmr
-    {0x858A0000u, 40u}, // kmb -> Latn
-    {0x9D8A0000u, 40u}, // kmh -> Latn
-    {0xB98A0000u, 40u}, // kmo -> Latn
-    {0xC98A0000u, 40u}, // kms -> Latn
-    {0xD18A0000u, 40u}, // kmu -> Latn
-    {0xD98A0000u, 40u}, // kmw -> Latn
-    {0x6B6E0000u, 36u}, // kn -> Knda
-    {0xBDAA0000u, 40u}, // knp -> Latn
-    {0x6B6F0000u, 37u}, // ko -> Kore
-    {0xA1CA0000u, 15u}, // koi -> Cyrl
-    {0xA9CA0000u, 16u}, // kok -> Deva
-    {0xADCA0000u, 40u}, // kol -> Latn
-    {0xC9CA0000u, 40u}, // kos -> Latn
-    {0xE5CA0000u, 40u}, // koz -> Latn
-    {0x91EA0000u, 40u}, // kpe -> Latn
-    {0x95EA0000u, 40u}, // kpf -> Latn
-    {0xB9EA0000u, 40u}, // kpo -> Latn
-    {0xC5EA0000u, 40u}, // kpr -> Latn
-    {0xDDEA0000u, 40u}, // kpx -> Latn
-    {0x860A0000u, 40u}, // kqb -> Latn
-    {0x960A0000u, 40u}, // kqf -> Latn
-    {0xCA0A0000u, 40u}, // kqs -> Latn
-    {0xE20A0000u, 18u}, // kqy -> Ethi
-    {0x8A2A0000u, 15u}, // krc -> Cyrl
-    {0xA22A0000u, 40u}, // kri -> Latn
-    {0xA62A0000u, 40u}, // krj -> Latn
-    {0xAE2A0000u, 40u}, // krl -> Latn
-    {0xCA2A0000u, 40u}, // krs -> Latn
-    {0xD22A0000u, 16u}, // kru -> Deva
+    {0x894A0000u, 44u}, // kkc -> Latn
+    {0xA54A0000u, 44u}, // kkj -> Latn
+    {0x6B6C0000u, 44u}, // kl -> Latn
+    {0xB56A0000u, 44u}, // kln -> Latn
+    {0xC16A0000u, 44u}, // klq -> Latn
+    {0xCD6A0000u, 44u}, // klt -> Latn
+    {0xDD6A0000u, 44u}, // klx -> Latn
+    {0x6B6D0000u, 39u}, // km -> Khmr
+    {0x858A0000u, 44u}, // kmb -> Latn
+    {0x9D8A0000u, 44u}, // kmh -> Latn
+    {0xB98A0000u, 44u}, // kmo -> Latn
+    {0xC98A0000u, 44u}, // kms -> Latn
+    {0xD18A0000u, 44u}, // kmu -> Latn
+    {0xD98A0000u, 44u}, // kmw -> Latn
+    {0x6B6E0000u, 40u}, // kn -> Knda
+    {0x95AA0000u, 44u}, // knf -> Latn
+    {0xBDAA0000u, 44u}, // knp -> Latn
+    {0x6B6F0000u, 41u}, // ko -> Kore
+    {0xA1CA0000u, 16u}, // koi -> Cyrl
+    {0xA9CA0000u, 17u}, // kok -> Deva
+    {0xADCA0000u, 44u}, // kol -> Latn
+    {0xC9CA0000u, 44u}, // kos -> Latn
+    {0xE5CA0000u, 44u}, // koz -> Latn
+    {0x91EA0000u, 44u}, // kpe -> Latn
+    {0x95EA0000u, 44u}, // kpf -> Latn
+    {0xB9EA0000u, 44u}, // kpo -> Latn
+    {0xC5EA0000u, 44u}, // kpr -> Latn
+    {0xDDEA0000u, 44u}, // kpx -> Latn
+    {0x860A0000u, 44u}, // kqb -> Latn
+    {0x960A0000u, 44u}, // kqf -> Latn
+    {0xCA0A0000u, 44u}, // kqs -> Latn
+    {0xE20A0000u, 19u}, // kqy -> Ethi
+    {0x6B720000u, 44u}, // kr -> Latn
+    {0x8A2A0000u, 16u}, // krc -> Cyrl
+    {0xA22A0000u, 44u}, // kri -> Latn
+    {0xA62A0000u, 44u}, // krj -> Latn
+    {0xAE2A0000u, 44u}, // krl -> Latn
+    {0xCA2A0000u, 44u}, // krs -> Latn
+    {0xD22A0000u, 17u}, // kru -> Deva
     {0x6B730000u,  1u}, // ks -> Arab
-    {0x864A0000u, 40u}, // ksb -> Latn
-    {0x8E4A0000u, 40u}, // ksd -> Latn
-    {0x964A0000u, 40u}, // ksf -> Latn
-    {0x9E4A0000u, 40u}, // ksh -> Latn
-    {0xA64A0000u, 40u}, // ksj -> Latn
-    {0xC64A0000u, 40u}, // ksr -> Latn
-    {0x866A0000u, 18u}, // ktb -> Ethi
-    {0xB26A0000u, 40u}, // ktm -> Latn
-    {0xBA6A0000u, 40u}, // kto -> Latn
-    {0x6B750000u, 40u}, // ku -> Latn
+    {0x864A0000u, 44u}, // ksb -> Latn
+    {0x8E4A0000u, 44u}, // ksd -> Latn
+    {0x964A0000u, 44u}, // ksf -> Latn
+    {0x9E4A0000u, 44u}, // ksh -> Latn
+    {0xA64A0000u, 44u}, // ksj -> Latn
+    {0xC64A0000u, 44u}, // ksr -> Latn
+    {0x866A0000u, 19u}, // ktb -> Ethi
+    {0xB26A0000u, 44u}, // ktm -> Latn
+    {0xBA6A0000u, 44u}, // kto -> Latn
+    {0xC66A0000u, 44u}, // ktr -> Latn
+    {0x6B750000u, 44u}, // ku -> Latn
     {0x6B754952u,  1u}, // ku-IR -> Arab
     {0x6B754C42u,  1u}, // ku-LB -> Arab
-    {0x868A0000u, 40u}, // kub -> Latn
-    {0x8E8A0000u, 40u}, // kud -> Latn
-    {0x928A0000u, 40u}, // kue -> Latn
-    {0xA68A0000u, 40u}, // kuj -> Latn
-    {0xB28A0000u, 15u}, // kum -> Cyrl
-    {0xB68A0000u, 40u}, // kun -> Latn
-    {0xBE8A0000u, 40u}, // kup -> Latn
-    {0xCA8A0000u, 40u}, // kus -> Latn
-    {0x6B760000u, 15u}, // kv -> Cyrl
-    {0x9AAA0000u, 40u}, // kvg -> Latn
-    {0xC6AA0000u, 40u}, // kvr -> Latn
+    {0x868A0000u, 44u}, // kub -> Latn
+    {0x8E8A0000u, 44u}, // kud -> Latn
+    {0x928A0000u, 44u}, // kue -> Latn
+    {0xA68A0000u, 44u}, // kuj -> Latn
+    {0xB28A0000u, 16u}, // kum -> Cyrl
+    {0xB68A0000u, 44u}, // kun -> Latn
+    {0xBE8A0000u, 44u}, // kup -> Latn
+    {0xCA8A0000u, 44u}, // kus -> Latn
+    {0x6B760000u, 16u}, // kv -> Cyrl
+    {0x9AAA0000u, 44u}, // kvg -> Latn
+    {0xC6AA0000u, 44u}, // kvr -> Latn
     {0xDEAA0000u,  1u}, // kvx -> Arab
-    {0x6B770000u, 40u}, // kw -> Latn
-    {0xA6CA0000u, 40u}, // kwj -> Latn
-    {0xBACA0000u, 40u}, // kwo -> Latn
-    {0x82EA0000u, 40u}, // kxa -> Latn
-    {0x8AEA0000u, 18u}, // kxc -> Ethi
-    {0xB2EA0000u, 80u}, // kxm -> Thai
+    {0x6B770000u, 44u}, // kw -> Latn
+    {0xA6CA0000u, 44u}, // kwj -> Latn
+    {0xBACA0000u, 44u}, // kwo -> Latn
+    {0xC2CA0000u, 44u}, // kwq -> Latn
+    {0x82EA0000u, 44u}, // kxa -> Latn
+    {0x8AEA0000u, 19u}, // kxc -> Ethi
+    {0x92EA0000u, 44u}, // kxe -> Latn
+    {0xB2EA0000u, 87u}, // kxm -> Thai
     {0xBEEA0000u,  1u}, // kxp -> Arab
-    {0xDAEA0000u, 40u}, // kxw -> Latn
-    {0xE6EA0000u, 40u}, // kxz -> Latn
-    {0x6B790000u, 15u}, // ky -> Cyrl
+    {0xDAEA0000u, 44u}, // kxw -> Latn
+    {0xE6EA0000u, 44u}, // kxz -> Latn
+    {0x6B790000u, 16u}, // ky -> Cyrl
     {0x6B79434Eu,  1u}, // ky-CN -> Arab
-    {0x6B795452u, 40u}, // ky-TR -> Latn
-    {0x930A0000u, 40u}, // kye -> Latn
-    {0xDF0A0000u, 40u}, // kyx -> Latn
-    {0xC72A0000u, 40u}, // kzr -> Latn
-    {0x6C610000u, 40u}, // la -> Latn
-    {0x840B0000u, 42u}, // lab -> Lina
-    {0x8C0B0000u, 27u}, // lad -> Hebr
-    {0x980B0000u, 40u}, // lag -> Latn
+    {0x6B795452u, 44u}, // ky-TR -> Latn
+    {0x930A0000u, 44u}, // kye -> Latn
+    {0xDF0A0000u, 44u}, // kyx -> Latn
+    {0xA72A0000u, 44u}, // kzj -> Latn
+    {0xC72A0000u, 44u}, // kzr -> Latn
+    {0xCF2A0000u, 44u}, // kzt -> Latn
+    {0x6C610000u, 44u}, // la -> Latn
+    {0x840B0000u, 46u}, // lab -> Lina
+    {0x8C0B0000u, 30u}, // lad -> Hebr
+    {0x980B0000u, 44u}, // lag -> Latn
     {0x9C0B0000u,  1u}, // lah -> Arab
-    {0xA40B0000u, 40u}, // laj -> Latn
-    {0xC80B0000u, 40u}, // las -> Latn
-    {0x6C620000u, 40u}, // lb -> Latn
-    {0x902B0000u, 15u}, // lbe -> Cyrl
-    {0xD02B0000u, 40u}, // lbu -> Latn
-    {0xD82B0000u, 40u}, // lbw -> Latn
-    {0xB04B0000u, 40u}, // lcm -> Latn
-    {0xBC4B0000u, 80u}, // lcp -> Thai
-    {0x846B0000u, 40u}, // ldb -> Latn
-    {0x8C8B0000u, 40u}, // led -> Latn
-    {0x908B0000u, 40u}, // lee -> Latn
-    {0xB08B0000u, 40u}, // lem -> Latn
-    {0xBC8B0000u, 41u}, // lep -> Lepc
-    {0xC08B0000u, 40u}, // leq -> Latn
-    {0xD08B0000u, 40u}, // leu -> Latn
-    {0xE48B0000u, 15u}, // lez -> Cyrl
-    {0x6C670000u, 40u}, // lg -> Latn
-    {0x98CB0000u, 40u}, // lgg -> Latn
-    {0x6C690000u, 40u}, // li -> Latn
-    {0x810B0000u, 40u}, // lia -> Latn
-    {0x8D0B0000u, 40u}, // lid -> Latn
-    {0x950B0000u, 16u}, // lif -> Deva
-    {0x990B0000u, 40u}, // lig -> Latn
-    {0x9D0B0000u, 40u}, // lih -> Latn
-    {0xA50B0000u, 40u}, // lij -> Latn
-    {0xC90B0000u, 43u}, // lis -> Lisu
-    {0xBD2B0000u, 40u}, // ljp -> Latn
+    {0xA40B0000u, 44u}, // laj -> Latn
+    {0xC80B0000u, 44u}, // las -> Latn
+    {0x6C620000u, 44u}, // lb -> Latn
+    {0x902B0000u, 16u}, // lbe -> Cyrl
+    {0xD02B0000u, 44u}, // lbu -> Latn
+    {0xD82B0000u, 44u}, // lbw -> Latn
+    {0xB04B0000u, 44u}, // lcm -> Latn
+    {0xBC4B0000u, 87u}, // lcp -> Thai
+    {0x846B0000u, 44u}, // ldb -> Latn
+    {0x8C8B0000u, 44u}, // led -> Latn
+    {0x908B0000u, 44u}, // lee -> Latn
+    {0xB08B0000u, 44u}, // lem -> Latn
+    {0xBC8B0000u, 45u}, // lep -> Lepc
+    {0xC08B0000u, 44u}, // leq -> Latn
+    {0xD08B0000u, 44u}, // leu -> Latn
+    {0xE48B0000u, 16u}, // lez -> Cyrl
+    {0x6C670000u, 44u}, // lg -> Latn
+    {0x98CB0000u, 44u}, // lgg -> Latn
+    {0x6C690000u, 44u}, // li -> Latn
+    {0x810B0000u, 44u}, // lia -> Latn
+    {0x8D0B0000u, 44u}, // lid -> Latn
+    {0x950B0000u, 17u}, // lif -> Deva
+    {0x990B0000u, 44u}, // lig -> Latn
+    {0x9D0B0000u, 44u}, // lih -> Latn
+    {0xA50B0000u, 44u}, // lij -> Latn
+    {0xC90B0000u, 47u}, // lis -> Lisu
+    {0xBD2B0000u, 44u}, // ljp -> Latn
     {0xA14B0000u,  1u}, // lki -> Arab
-    {0xCD4B0000u, 40u}, // lkt -> Latn
-    {0x916B0000u, 40u}, // lle -> Latn
-    {0xB56B0000u, 40u}, // lln -> Latn
-    {0xB58B0000u, 77u}, // lmn -> Telu
-    {0xB98B0000u, 40u}, // lmo -> Latn
-    {0xBD8B0000u, 40u}, // lmp -> Latn
-    {0x6C6E0000u, 40u}, // ln -> Latn
-    {0xC9AB0000u, 40u}, // lns -> Latn
-    {0xD1AB0000u, 40u}, // lnu -> Latn
-    {0x6C6F0000u, 39u}, // lo -> Laoo
-    {0xA5CB0000u, 40u}, // loj -> Latn
-    {0xA9CB0000u, 40u}, // lok -> Latn
-    {0xADCB0000u, 40u}, // lol -> Latn
-    {0xC5CB0000u, 40u}, // lor -> Latn
-    {0xC9CB0000u, 40u}, // los -> Latn
-    {0xE5CB0000u, 40u}, // loz -> Latn
+    {0xCD4B0000u, 44u}, // lkt -> Latn
+    {0x916B0000u, 44u}, // lle -> Latn
+    {0xB56B0000u, 44u}, // lln -> Latn
+    {0xB58B0000u, 84u}, // lmn -> Telu
+    {0xB98B0000u, 44u}, // lmo -> Latn
+    {0xBD8B0000u, 44u}, // lmp -> Latn
+    {0x6C6E0000u, 44u}, // ln -> Latn
+    {0xC9AB0000u, 44u}, // lns -> Latn
+    {0xD1AB0000u, 44u}, // lnu -> Latn
+    {0x6C6F0000u, 43u}, // lo -> Laoo
+    {0xA5CB0000u, 44u}, // loj -> Latn
+    {0xA9CB0000u, 44u}, // lok -> Latn
+    {0xADCB0000u, 44u}, // lol -> Latn
+    {0xC5CB0000u, 44u}, // lor -> Latn
+    {0xC9CB0000u, 44u}, // los -> Latn
+    {0xE5CB0000u, 44u}, // loz -> Latn
     {0x8A2B0000u,  1u}, // lrc -> Arab
-    {0x6C740000u, 40u}, // lt -> Latn
-    {0x9A6B0000u, 40u}, // ltg -> Latn
-    {0x6C750000u, 40u}, // lu -> Latn
-    {0x828B0000u, 40u}, // lua -> Latn
-    {0xBA8B0000u, 40u}, // luo -> Latn
-    {0xE28B0000u, 40u}, // luy -> Latn
+    {0x6C740000u, 44u}, // lt -> Latn
+    {0x9A6B0000u, 44u}, // ltg -> Latn
+    {0x6C750000u, 44u}, // lu -> Latn
+    {0x828B0000u, 44u}, // lua -> Latn
+    {0xBA8B0000u, 44u}, // luo -> Latn
+    {0xE28B0000u, 44u}, // luy -> Latn
     {0xE68B0000u,  1u}, // luz -> Arab
-    {0x6C760000u, 40u}, // lv -> Latn
-    {0xAECB0000u, 80u}, // lwl -> Thai
-    {0x9F2B0000u, 24u}, // lzh -> Hans
-    {0xE72B0000u, 40u}, // lzz -> Latn
-    {0x8C0C0000u, 40u}, // mad -> Latn
-    {0x940C0000u, 40u}, // maf -> Latn
-    {0x980C0000u, 16u}, // mag -> Deva
-    {0xA00C0000u, 16u}, // mai -> Deva
-    {0xA80C0000u, 40u}, // mak -> Latn
-    {0xB40C0000u, 40u}, // man -> Latn
-    {0xB40C474Eu, 54u}, // man-GN -> Nkoo
-    {0xC80C0000u, 40u}, // mas -> Latn
-    {0xD80C0000u, 40u}, // maw -> Latn
-    {0xE40C0000u, 40u}, // maz -> Latn
-    {0x9C2C0000u, 40u}, // mbh -> Latn
-    {0xB82C0000u, 40u}, // mbo -> Latn
-    {0xC02C0000u, 40u}, // mbq -> Latn
-    {0xD02C0000u, 40u}, // mbu -> Latn
-    {0xD82C0000u, 40u}, // mbw -> Latn
-    {0xA04C0000u, 40u}, // mci -> Latn
-    {0xBC4C0000u, 40u}, // mcp -> Latn
-    {0xC04C0000u, 40u}, // mcq -> Latn
-    {0xC44C0000u, 40u}, // mcr -> Latn
-    {0xD04C0000u, 40u}, // mcu -> Latn
-    {0x806C0000u, 40u}, // mda -> Latn
+    {0x6C760000u, 44u}, // lv -> Latn
+    {0xAECB0000u, 87u}, // lwl -> Thai
+    {0x9F2B0000u, 27u}, // lzh -> Hans
+    {0xE72B0000u, 44u}, // lzz -> Latn
+    {0x8C0C0000u, 44u}, // mad -> Latn
+    {0x940C0000u, 44u}, // maf -> Latn
+    {0x980C0000u, 17u}, // mag -> Deva
+    {0xA00C0000u, 17u}, // mai -> Deva
+    {0xA80C0000u, 44u}, // mak -> Latn
+    {0xB40C0000u, 44u}, // man -> Latn
+    {0xB40C474Eu, 58u}, // man-GN -> Nkoo
+    {0xC80C0000u, 44u}, // mas -> Latn
+    {0xD80C0000u, 44u}, // maw -> Latn
+    {0xE40C0000u, 44u}, // maz -> Latn
+    {0x9C2C0000u, 44u}, // mbh -> Latn
+    {0xB82C0000u, 44u}, // mbo -> Latn
+    {0xC02C0000u, 44u}, // mbq -> Latn
+    {0xD02C0000u, 44u}, // mbu -> Latn
+    {0xD82C0000u, 44u}, // mbw -> Latn
+    {0xA04C0000u, 44u}, // mci -> Latn
+    {0xBC4C0000u, 44u}, // mcp -> Latn
+    {0xC04C0000u, 44u}, // mcq -> Latn
+    {0xC44C0000u, 44u}, // mcr -> Latn
+    {0xD04C0000u, 44u}, // mcu -> Latn
+    {0x806C0000u, 44u}, // mda -> Latn
     {0x906C0000u,  1u}, // mde -> Arab
-    {0x946C0000u, 15u}, // mdf -> Cyrl
-    {0x9C6C0000u, 40u}, // mdh -> Latn
-    {0xA46C0000u, 40u}, // mdj -> Latn
-    {0xC46C0000u, 40u}, // mdr -> Latn
-    {0xDC6C0000u, 18u}, // mdx -> Ethi
-    {0x8C8C0000u, 40u}, // med -> Latn
-    {0x908C0000u, 40u}, // mee -> Latn
-    {0xA88C0000u, 40u}, // mek -> Latn
-    {0xB48C0000u, 40u}, // men -> Latn
-    {0xC48C0000u, 40u}, // mer -> Latn
-    {0xCC8C0000u, 40u}, // met -> Latn
-    {0xD08C0000u, 40u}, // meu -> Latn
+    {0x946C0000u, 16u}, // mdf -> Cyrl
+    {0x9C6C0000u, 44u}, // mdh -> Latn
+    {0xA46C0000u, 44u}, // mdj -> Latn
+    {0xC46C0000u, 44u}, // mdr -> Latn
+    {0xDC6C0000u, 19u}, // mdx -> Ethi
+    {0x8C8C0000u, 44u}, // med -> Latn
+    {0x908C0000u, 44u}, // mee -> Latn
+    {0xA88C0000u, 44u}, // mek -> Latn
+    {0xB48C0000u, 44u}, // men -> Latn
+    {0xC48C0000u, 44u}, // mer -> Latn
+    {0xCC8C0000u, 44u}, // met -> Latn
+    {0xD08C0000u, 44u}, // meu -> Latn
     {0x80AC0000u,  1u}, // mfa -> Arab
-    {0x90AC0000u, 40u}, // mfe -> Latn
-    {0xB4AC0000u, 40u}, // mfn -> Latn
-    {0xB8AC0000u, 40u}, // mfo -> Latn
-    {0xC0AC0000u, 40u}, // mfq -> Latn
-    {0x6D670000u, 40u}, // mg -> Latn
-    {0x9CCC0000u, 40u}, // mgh -> Latn
-    {0xACCC0000u, 40u}, // mgl -> Latn
-    {0xB8CC0000u, 40u}, // mgo -> Latn
-    {0xBCCC0000u, 16u}, // mgp -> Deva
-    {0xE0CC0000u, 40u}, // mgy -> Latn
-    {0x6D680000u, 40u}, // mh -> Latn
-    {0xA0EC0000u, 40u}, // mhi -> Latn
-    {0xACEC0000u, 40u}, // mhl -> Latn
-    {0x6D690000u, 40u}, // mi -> Latn
-    {0x950C0000u, 40u}, // mif -> Latn
-    {0xB50C0000u, 40u}, // min -> Latn
-    {0xC90C0000u, 26u}, // mis -> Hatr
-    {0xD90C0000u, 40u}, // miw -> Latn
-    {0x6D6B0000u, 15u}, // mk -> Cyrl
+    {0x90AC0000u, 44u}, // mfe -> Latn
+    {0xB4AC0000u, 44u}, // mfn -> Latn
+    {0xB8AC0000u, 44u}, // mfo -> Latn
+    {0xC0AC0000u, 44u}, // mfq -> Latn
+    {0x6D670000u, 44u}, // mg -> Latn
+    {0x9CCC0000u, 44u}, // mgh -> Latn
+    {0xACCC0000u, 44u}, // mgl -> Latn
+    {0xB8CC0000u, 44u}, // mgo -> Latn
+    {0xBCCC0000u, 17u}, // mgp -> Deva
+    {0xE0CC0000u, 44u}, // mgy -> Latn
+    {0x6D680000u, 44u}, // mh -> Latn
+    {0xA0EC0000u, 44u}, // mhi -> Latn
+    {0xACEC0000u, 44u}, // mhl -> Latn
+    {0x6D690000u, 44u}, // mi -> Latn
+    {0x950C0000u, 44u}, // mif -> Latn
+    {0xB50C0000u, 44u}, // min -> Latn
+    {0xC90C0000u, 29u}, // mis -> Hatr
+    {0xD90C0000u, 44u}, // miw -> Latn
+    {0x6D6B0000u, 16u}, // mk -> Cyrl
     {0xA14C0000u,  1u}, // mki -> Arab
-    {0xAD4C0000u, 40u}, // mkl -> Latn
-    {0xBD4C0000u, 40u}, // mkp -> Latn
-    {0xD94C0000u, 40u}, // mkw -> Latn
-    {0x6D6C0000u, 49u}, // ml -> Mlym
-    {0x916C0000u, 40u}, // mle -> Latn
-    {0xBD6C0000u, 40u}, // mlp -> Latn
-    {0xC96C0000u, 40u}, // mls -> Latn
-    {0xB98C0000u, 40u}, // mmo -> Latn
-    {0xD18C0000u, 40u}, // mmu -> Latn
-    {0xDD8C0000u, 40u}, // mmx -> Latn
-    {0x6D6E0000u, 15u}, // mn -> Cyrl
-    {0x6D6E434Eu, 50u}, // mn-CN -> Mong
-    {0x81AC0000u, 40u}, // mna -> Latn
-    {0x95AC0000u, 40u}, // mnf -> Latn
+    {0xAD4C0000u, 44u}, // mkl -> Latn
+    {0xBD4C0000u, 44u}, // mkp -> Latn
+    {0xD94C0000u, 44u}, // mkw -> Latn
+    {0x6D6C0000u, 53u}, // ml -> Mlym
+    {0x916C0000u, 44u}, // mle -> Latn
+    {0xBD6C0000u, 44u}, // mlp -> Latn
+    {0xC96C0000u, 44u}, // mls -> Latn
+    {0xB98C0000u, 44u}, // mmo -> Latn
+    {0xD18C0000u, 44u}, // mmu -> Latn
+    {0xDD8C0000u, 44u}, // mmx -> Latn
+    {0x6D6E0000u, 16u}, // mn -> Cyrl
+    {0x6D6E434Eu, 54u}, // mn-CN -> Mong
+    {0x81AC0000u, 44u}, // mna -> Latn
+    {0x95AC0000u, 44u}, // mnf -> Latn
     {0xA1AC0000u,  7u}, // mni -> Beng
-    {0xD9AC0000u, 52u}, // mnw -> Mymr
-    {0x81CC0000u, 40u}, // moa -> Latn
-    {0x91CC0000u, 40u}, // moe -> Latn
-    {0x9DCC0000u, 40u}, // moh -> Latn
-    {0xC9CC0000u, 40u}, // mos -> Latn
-    {0xDDCC0000u, 40u}, // mox -> Latn
-    {0xBDEC0000u, 40u}, // mpp -> Latn
-    {0xC9EC0000u, 40u}, // mps -> Latn
-    {0xCDEC0000u, 40u}, // mpt -> Latn
-    {0xDDEC0000u, 40u}, // mpx -> Latn
-    {0xAE0C0000u, 40u}, // mql -> Latn
-    {0x6D720000u, 16u}, // mr -> Deva
-    {0x8E2C0000u, 16u}, // mrd -> Deva
-    {0xA62C0000u, 15u}, // mrj -> Cyrl
-    {0xBA2C0000u, 51u}, // mro -> Mroo
-    {0x6D730000u, 40u}, // ms -> Latn
+    {0xD9AC0000u, 56u}, // mnw -> Mymr
+    {0x6D6F0000u, 44u}, // mo -> Latn
+    {0x81CC0000u, 44u}, // moa -> Latn
+    {0x91CC0000u, 44u}, // moe -> Latn
+    {0x9DCC0000u, 44u}, // moh -> Latn
+    {0xC9CC0000u, 44u}, // mos -> Latn
+    {0xDDCC0000u, 44u}, // mox -> Latn
+    {0xBDEC0000u, 44u}, // mpp -> Latn
+    {0xC9EC0000u, 44u}, // mps -> Latn
+    {0xCDEC0000u, 44u}, // mpt -> Latn
+    {0xDDEC0000u, 44u}, // mpx -> Latn
+    {0xAE0C0000u, 44u}, // mql -> Latn
+    {0x6D720000u, 17u}, // mr -> Deva
+    {0x8E2C0000u, 17u}, // mrd -> Deva
+    {0xA62C0000u, 16u}, // mrj -> Cyrl
+    {0xBA2C0000u, 55u}, // mro -> Mroo
+    {0x6D730000u, 44u}, // ms -> Latn
     {0x6D734343u,  1u}, // ms-CC -> Arab
     {0x6D734944u,  1u}, // ms-ID -> Arab
-    {0x6D740000u, 40u}, // mt -> Latn
-    {0x8A6C0000u, 40u}, // mtc -> Latn
-    {0x966C0000u, 40u}, // mtf -> Latn
-    {0xA26C0000u, 40u}, // mti -> Latn
-    {0xC66C0000u, 16u}, // mtr -> Deva
-    {0x828C0000u, 40u}, // mua -> Latn
-    {0xC68C0000u, 40u}, // mur -> Latn
-    {0xCA8C0000u, 40u}, // mus -> Latn
-    {0x82AC0000u, 40u}, // mva -> Latn
-    {0xB6AC0000u, 40u}, // mvn -> Latn
+    {0x6D740000u, 44u}, // mt -> Latn
+    {0x8A6C0000u, 44u}, // mtc -> Latn
+    {0x966C0000u, 44u}, // mtf -> Latn
+    {0xA26C0000u, 44u}, // mti -> Latn
+    {0xC66C0000u, 17u}, // mtr -> Deva
+    {0x828C0000u, 44u}, // mua -> Latn
+    {0xC68C0000u, 44u}, // mur -> Latn
+    {0xCA8C0000u, 44u}, // mus -> Latn
+    {0x82AC0000u, 44u}, // mva -> Latn
+    {0xB6AC0000u, 44u}, // mvn -> Latn
     {0xE2AC0000u,  1u}, // mvy -> Arab
-    {0xAACC0000u, 40u}, // mwk -> Latn
-    {0xC6CC0000u, 16u}, // mwr -> Deva
-    {0xD6CC0000u, 40u}, // mwv -> Latn
-    {0x8AEC0000u, 40u}, // mxc -> Latn
-    {0xB2EC0000u, 40u}, // mxm -> Latn
-    {0x6D790000u, 52u}, // my -> Mymr
-    {0xAB0C0000u, 40u}, // myk -> Latn
-    {0xB30C0000u, 18u}, // mym -> Ethi
-    {0xD70C0000u, 15u}, // myv -> Cyrl
-    {0xDB0C0000u, 40u}, // myw -> Latn
-    {0xDF0C0000u, 40u}, // myx -> Latn
-    {0xE70C0000u, 46u}, // myz -> Mand
-    {0xAB2C0000u, 40u}, // mzk -> Latn
-    {0xB32C0000u, 40u}, // mzm -> Latn
+    {0xAACC0000u, 44u}, // mwk -> Latn
+    {0xC6CC0000u, 17u}, // mwr -> Deva
+    {0xD6CC0000u, 44u}, // mwv -> Latn
+    {0xDACC0000u, 33u}, // mww -> Hmnp
+    {0x8AEC0000u, 44u}, // mxc -> Latn
+    {0xB2EC0000u, 44u}, // mxm -> Latn
+    {0x6D790000u, 56u}, // my -> Mymr
+    {0xAB0C0000u, 44u}, // myk -> Latn
+    {0xB30C0000u, 19u}, // mym -> Ethi
+    {0xD70C0000u, 16u}, // myv -> Cyrl
+    {0xDB0C0000u, 44u}, // myw -> Latn
+    {0xDF0C0000u, 44u}, // myx -> Latn
+    {0xE70C0000u, 50u}, // myz -> Mand
+    {0xAB2C0000u, 44u}, // mzk -> Latn
+    {0xB32C0000u, 44u}, // mzm -> Latn
     {0xB72C0000u,  1u}, // mzn -> Arab
-    {0xBF2C0000u, 40u}, // mzp -> Latn
-    {0xDB2C0000u, 40u}, // mzw -> Latn
-    {0xE72C0000u, 40u}, // mzz -> Latn
-    {0x6E610000u, 40u}, // na -> Latn
-    {0x880D0000u, 40u}, // nac -> Latn
-    {0x940D0000u, 40u}, // naf -> Latn
-    {0xA80D0000u, 40u}, // nak -> Latn
-    {0xB40D0000u, 24u}, // nan -> Hans
-    {0xBC0D0000u, 40u}, // nap -> Latn
-    {0xC00D0000u, 40u}, // naq -> Latn
-    {0xC80D0000u, 40u}, // nas -> Latn
-    {0x6E620000u, 40u}, // nb -> Latn
-    {0x804D0000u, 40u}, // nca -> Latn
-    {0x904D0000u, 40u}, // nce -> Latn
-    {0x944D0000u, 40u}, // ncf -> Latn
-    {0x9C4D0000u, 40u}, // nch -> Latn
-    {0xB84D0000u, 40u}, // nco -> Latn
-    {0xD04D0000u, 40u}, // ncu -> Latn
-    {0x6E640000u, 40u}, // nd -> Latn
-    {0x886D0000u, 40u}, // ndc -> Latn
-    {0xC86D0000u, 40u}, // nds -> Latn
-    {0x6E650000u, 16u}, // ne -> Deva
-    {0x848D0000u, 40u}, // neb -> Latn
-    {0xD88D0000u, 16u}, // new -> Deva
-    {0xDC8D0000u, 40u}, // nex -> Latn
-    {0xC4AD0000u, 40u}, // nfr -> Latn
-    {0x6E670000u, 40u}, // ng -> Latn
-    {0x80CD0000u, 40u}, // nga -> Latn
-    {0x84CD0000u, 40u}, // ngb -> Latn
-    {0xACCD0000u, 40u}, // ngl -> Latn
-    {0x84ED0000u, 40u}, // nhb -> Latn
-    {0x90ED0000u, 40u}, // nhe -> Latn
-    {0xD8ED0000u, 40u}, // nhw -> Latn
-    {0x950D0000u, 40u}, // nif -> Latn
-    {0xA10D0000u, 40u}, // nii -> Latn
-    {0xA50D0000u, 40u}, // nij -> Latn
-    {0xB50D0000u, 40u}, // nin -> Latn
-    {0xD10D0000u, 40u}, // niu -> Latn
-    {0xE10D0000u, 40u}, // niy -> Latn
-    {0xE50D0000u, 40u}, // niz -> Latn
-    {0xB92D0000u, 40u}, // njo -> Latn
-    {0x994D0000u, 40u}, // nkg -> Latn
-    {0xB94D0000u, 40u}, // nko -> Latn
-    {0x6E6C0000u, 40u}, // nl -> Latn
-    {0x998D0000u, 40u}, // nmg -> Latn
-    {0xE58D0000u, 40u}, // nmz -> Latn
-    {0x6E6E0000u, 40u}, // nn -> Latn
-    {0x95AD0000u, 40u}, // nnf -> Latn
-    {0x9DAD0000u, 40u}, // nnh -> Latn
-    {0xA9AD0000u, 40u}, // nnk -> Latn
-    {0xB1AD0000u, 40u}, // nnm -> Latn
-    {0x6E6F0000u, 40u}, // no -> Latn
-    {0x8DCD0000u, 38u}, // nod -> Lana
-    {0x91CD0000u, 16u}, // noe -> Deva
-    {0xB5CD0000u, 64u}, // non -> Runr
-    {0xBDCD0000u, 40u}, // nop -> Latn
-    {0xD1CD0000u, 40u}, // nou -> Latn
-    {0xBA0D0000u, 54u}, // nqo -> Nkoo
-    {0x6E720000u, 40u}, // nr -> Latn
-    {0x862D0000u, 40u}, // nrb -> Latn
-    {0xAA4D0000u,  9u}, // nsk -> Cans
-    {0xB64D0000u, 40u}, // nsn -> Latn
-    {0xBA4D0000u, 40u}, // nso -> Latn
-    {0xCA4D0000u, 40u}, // nss -> Latn
-    {0xB26D0000u, 40u}, // ntm -> Latn
-    {0xC66D0000u, 40u}, // ntr -> Latn
-    {0xA28D0000u, 40u}, // nui -> Latn
-    {0xBE8D0000u, 40u}, // nup -> Latn
-    {0xCA8D0000u, 40u}, // nus -> Latn
-    {0xD68D0000u, 40u}, // nuv -> Latn
-    {0xDE8D0000u, 40u}, // nux -> Latn
-    {0x6E760000u, 40u}, // nv -> Latn
-    {0x86CD0000u, 40u}, // nwb -> Latn
-    {0xC2ED0000u, 40u}, // nxq -> Latn
-    {0xC6ED0000u, 40u}, // nxr -> Latn
-    {0x6E790000u, 40u}, // ny -> Latn
-    {0xB30D0000u, 40u}, // nym -> Latn
-    {0xB70D0000u, 40u}, // nyn -> Latn
-    {0xA32D0000u, 40u}, // nzi -> Latn
-    {0x6F630000u, 40u}, // oc -> Latn
-    {0x88CE0000u, 40u}, // ogc -> Latn
-    {0xC54E0000u, 40u}, // okr -> Latn
-    {0xD54E0000u, 40u}, // okv -> Latn
-    {0x6F6D0000u, 40u}, // om -> Latn
-    {0x99AE0000u, 40u}, // ong -> Latn
-    {0xB5AE0000u, 40u}, // onn -> Latn
-    {0xC9AE0000u, 40u}, // ons -> Latn
-    {0xB1EE0000u, 40u}, // opm -> Latn
-    {0x6F720000u, 57u}, // or -> Orya
-    {0xBA2E0000u, 40u}, // oro -> Latn
+    {0xBF2C0000u, 44u}, // mzp -> Latn
+    {0xDB2C0000u, 44u}, // mzw -> Latn
+    {0xE72C0000u, 44u}, // mzz -> Latn
+    {0x6E610000u, 44u}, // na -> Latn
+    {0x880D0000u, 44u}, // nac -> Latn
+    {0x940D0000u, 44u}, // naf -> Latn
+    {0xA80D0000u, 44u}, // nak -> Latn
+    {0xB40D0000u, 27u}, // nan -> Hans
+    {0xBC0D0000u, 44u}, // nap -> Latn
+    {0xC00D0000u, 44u}, // naq -> Latn
+    {0xC80D0000u, 44u}, // nas -> Latn
+    {0x6E620000u, 44u}, // nb -> Latn
+    {0x804D0000u, 44u}, // nca -> Latn
+    {0x904D0000u, 44u}, // nce -> Latn
+    {0x944D0000u, 44u}, // ncf -> Latn
+    {0x9C4D0000u, 44u}, // nch -> Latn
+    {0xB84D0000u, 44u}, // nco -> Latn
+    {0xD04D0000u, 44u}, // ncu -> Latn
+    {0x6E640000u, 44u}, // nd -> Latn
+    {0x886D0000u, 44u}, // ndc -> Latn
+    {0xC86D0000u, 44u}, // nds -> Latn
+    {0x6E650000u, 17u}, // ne -> Deva
+    {0x848D0000u, 44u}, // neb -> Latn
+    {0xD88D0000u, 17u}, // new -> Deva
+    {0xDC8D0000u, 44u}, // nex -> Latn
+    {0xC4AD0000u, 44u}, // nfr -> Latn
+    {0x6E670000u, 44u}, // ng -> Latn
+    {0x80CD0000u, 44u}, // nga -> Latn
+    {0x84CD0000u, 44u}, // ngb -> Latn
+    {0xACCD0000u, 44u}, // ngl -> Latn
+    {0x84ED0000u, 44u}, // nhb -> Latn
+    {0x90ED0000u, 44u}, // nhe -> Latn
+    {0xD8ED0000u, 44u}, // nhw -> Latn
+    {0x950D0000u, 44u}, // nif -> Latn
+    {0xA10D0000u, 44u}, // nii -> Latn
+    {0xA50D0000u, 44u}, // nij -> Latn
+    {0xB50D0000u, 44u}, // nin -> Latn
+    {0xD10D0000u, 44u}, // niu -> Latn
+    {0xE10D0000u, 44u}, // niy -> Latn
+    {0xE50D0000u, 44u}, // niz -> Latn
+    {0xB92D0000u, 44u}, // njo -> Latn
+    {0x994D0000u, 44u}, // nkg -> Latn
+    {0xB94D0000u, 44u}, // nko -> Latn
+    {0x6E6C0000u, 44u}, // nl -> Latn
+    {0x998D0000u, 44u}, // nmg -> Latn
+    {0xE58D0000u, 44u}, // nmz -> Latn
+    {0x6E6E0000u, 44u}, // nn -> Latn
+    {0x95AD0000u, 44u}, // nnf -> Latn
+    {0x9DAD0000u, 44u}, // nnh -> Latn
+    {0xA9AD0000u, 44u}, // nnk -> Latn
+    {0xB1AD0000u, 44u}, // nnm -> Latn
+    {0xBDAD0000u, 91u}, // nnp -> Wcho
+    {0x6E6F0000u, 44u}, // no -> Latn
+    {0x8DCD0000u, 42u}, // nod -> Lana
+    {0x91CD0000u, 17u}, // noe -> Deva
+    {0xB5CD0000u, 69u}, // non -> Runr
+    {0xBDCD0000u, 44u}, // nop -> Latn
+    {0xD1CD0000u, 44u}, // nou -> Latn
+    {0xBA0D0000u, 58u}, // nqo -> Nkoo
+    {0x6E720000u, 44u}, // nr -> Latn
+    {0x862D0000u, 44u}, // nrb -> Latn
+    {0xAA4D0000u, 10u}, // nsk -> Cans
+    {0xB64D0000u, 44u}, // nsn -> Latn
+    {0xBA4D0000u, 44u}, // nso -> Latn
+    {0xCA4D0000u, 44u}, // nss -> Latn
+    {0xB26D0000u, 44u}, // ntm -> Latn
+    {0xC66D0000u, 44u}, // ntr -> Latn
+    {0xA28D0000u, 44u}, // nui -> Latn
+    {0xBE8D0000u, 44u}, // nup -> Latn
+    {0xCA8D0000u, 44u}, // nus -> Latn
+    {0xD68D0000u, 44u}, // nuv -> Latn
+    {0xDE8D0000u, 44u}, // nux -> Latn
+    {0x6E760000u, 44u}, // nv -> Latn
+    {0x86CD0000u, 44u}, // nwb -> Latn
+    {0xC2ED0000u, 44u}, // nxq -> Latn
+    {0xC6ED0000u, 44u}, // nxr -> Latn
+    {0x6E790000u, 44u}, // ny -> Latn
+    {0xB30D0000u, 44u}, // nym -> Latn
+    {0xB70D0000u, 44u}, // nyn -> Latn
+    {0xA32D0000u, 44u}, // nzi -> Latn
+    {0x6F630000u, 44u}, // oc -> Latn
+    {0x88CE0000u, 44u}, // ogc -> Latn
+    {0xC54E0000u, 44u}, // okr -> Latn
+    {0xD54E0000u, 44u}, // okv -> Latn
+    {0x6F6D0000u, 44u}, // om -> Latn
+    {0x99AE0000u, 44u}, // ong -> Latn
+    {0xB5AE0000u, 44u}, // onn -> Latn
+    {0xC9AE0000u, 44u}, // ons -> Latn
+    {0xB1EE0000u, 44u}, // opm -> Latn
+    {0x6F720000u, 62u}, // or -> Orya
+    {0xBA2E0000u, 44u}, // oro -> Latn
     {0xD22E0000u,  1u}, // oru -> Arab
-    {0x6F730000u, 15u}, // os -> Cyrl
-    {0x824E0000u, 58u}, // osa -> Osge
+    {0x6F730000u, 16u}, // os -> Cyrl
+    {0x824E0000u, 63u}, // osa -> Osge
     {0x826E0000u,  1u}, // ota -> Arab
-    {0xAA6E0000u, 56u}, // otk -> Orkh
-    {0xB32E0000u, 40u}, // ozm -> Latn
-    {0x70610000u, 23u}, // pa -> Guru
+    {0xAA6E0000u, 61u}, // otk -> Orkh
+    {0xB32E0000u, 44u}, // ozm -> Latn
+    {0x70610000u, 26u}, // pa -> Guru
     {0x7061504Bu,  1u}, // pa-PK -> Arab
-    {0x980F0000u, 40u}, // pag -> Latn
-    {0xAC0F0000u, 60u}, // pal -> Phli
-    {0xB00F0000u, 40u}, // pam -> Latn
-    {0xBC0F0000u, 40u}, // pap -> Latn
-    {0xD00F0000u, 40u}, // pau -> Latn
-    {0xA02F0000u, 40u}, // pbi -> Latn
-    {0x8C4F0000u, 40u}, // pcd -> Latn
-    {0xB04F0000u, 40u}, // pcm -> Latn
-    {0x886F0000u, 40u}, // pdc -> Latn
-    {0xCC6F0000u, 40u}, // pdt -> Latn
-    {0x8C8F0000u, 40u}, // ped -> Latn
-    {0xB88F0000u, 84u}, // peo -> Xpeo
-    {0xDC8F0000u, 40u}, // pex -> Latn
-    {0xACAF0000u, 40u}, // pfl -> Latn
+    {0x980F0000u, 44u}, // pag -> Latn
+    {0xAC0F0000u, 65u}, // pal -> Phli
+    {0xB00F0000u, 44u}, // pam -> Latn
+    {0xBC0F0000u, 44u}, // pap -> Latn
+    {0xD00F0000u, 44u}, // pau -> Latn
+    {0xA02F0000u, 44u}, // pbi -> Latn
+    {0x8C4F0000u, 44u}, // pcd -> Latn
+    {0xB04F0000u, 44u}, // pcm -> Latn
+    {0x886F0000u, 44u}, // pdc -> Latn
+    {0xCC6F0000u, 44u}, // pdt -> Latn
+    {0x8C8F0000u, 44u}, // ped -> Latn
+    {0xB88F0000u, 92u}, // peo -> Xpeo
+    {0xDC8F0000u, 44u}, // pex -> Latn
+    {0xACAF0000u, 44u}, // pfl -> Latn
     {0xACEF0000u,  1u}, // phl -> Arab
-    {0xB4EF0000u, 61u}, // phn -> Phnx
-    {0xAD0F0000u, 40u}, // pil -> Latn
-    {0xBD0F0000u, 40u}, // pip -> Latn
+    {0xB4EF0000u, 66u}, // phn -> Phnx
+    {0xAD0F0000u, 44u}, // pil -> Latn
+    {0xBD0F0000u, 44u}, // pip -> Latn
     {0x814F0000u,  8u}, // pka -> Brah
-    {0xB94F0000u, 40u}, // pko -> Latn
-    {0x706C0000u, 40u}, // pl -> Latn
-    {0x816F0000u, 40u}, // pla -> Latn
-    {0xC98F0000u, 40u}, // pms -> Latn
-    {0x99AF0000u, 40u}, // png -> Latn
-    {0xB5AF0000u, 40u}, // pnn -> Latn
-    {0xCDAF0000u, 21u}, // pnt -> Grek
-    {0xB5CF0000u, 40u}, // pon -> Latn
-    {0xB9EF0000u, 40u}, // ppo -> Latn
-    {0x822F0000u, 34u}, // pra -> Khar
+    {0xB94F0000u, 44u}, // pko -> Latn
+    {0x706C0000u, 44u}, // pl -> Latn
+    {0x816F0000u, 44u}, // pla -> Latn
+    {0xC98F0000u, 44u}, // pms -> Latn
+    {0x99AF0000u, 44u}, // png -> Latn
+    {0xB5AF0000u, 44u}, // pnn -> Latn
+    {0xCDAF0000u, 24u}, // pnt -> Grek
+    {0xB5CF0000u, 44u}, // pon -> Latn
+    {0x81EF0000u, 17u}, // ppa -> Deva
+    {0xB9EF0000u, 44u}, // ppo -> Latn
+    {0x822F0000u, 38u}, // pra -> Khar
     {0x8E2F0000u,  1u}, // prd -> Arab
-    {0x9A2F0000u, 40u}, // prg -> Latn
+    {0x9A2F0000u, 44u}, // prg -> Latn
     {0x70730000u,  1u}, // ps -> Arab
-    {0xCA4F0000u, 40u}, // pss -> Latn
-    {0x70740000u, 40u}, // pt -> Latn
-    {0xBE6F0000u, 40u}, // ptp -> Latn
-    {0xD28F0000u, 40u}, // puu -> Latn
-    {0x82CF0000u, 40u}, // pwa -> Latn
-    {0x71750000u, 40u}, // qu -> Latn
-    {0x8A900000u, 40u}, // quc -> Latn
-    {0x9A900000u, 40u}, // qug -> Latn
-    {0xA0110000u, 40u}, // rai -> Latn
-    {0xA4110000u, 16u}, // raj -> Deva
-    {0xB8110000u, 40u}, // rao -> Latn
-    {0x94510000u, 40u}, // rcf -> Latn
-    {0xA4910000u, 40u}, // rej -> Latn
-    {0xAC910000u, 40u}, // rel -> Latn
-    {0xC8910000u, 40u}, // res -> Latn
-    {0xB4D10000u, 40u}, // rgn -> Latn
+    {0xCA4F0000u, 44u}, // pss -> Latn
+    {0x70740000u, 44u}, // pt -> Latn
+    {0xBE6F0000u, 44u}, // ptp -> Latn
+    {0xD28F0000u, 44u}, // puu -> Latn
+    {0x82CF0000u, 44u}, // pwa -> Latn
+    {0x71750000u, 44u}, // qu -> Latn
+    {0x8A900000u, 44u}, // quc -> Latn
+    {0x9A900000u, 44u}, // qug -> Latn
+    {0xA0110000u, 44u}, // rai -> Latn
+    {0xA4110000u, 17u}, // raj -> Deva
+    {0xB8110000u, 44u}, // rao -> Latn
+    {0x94510000u, 44u}, // rcf -> Latn
+    {0xA4910000u, 44u}, // rej -> Latn
+    {0xAC910000u, 44u}, // rel -> Latn
+    {0xC8910000u, 44u}, // res -> Latn
+    {0xB4D10000u, 44u}, // rgn -> Latn
     {0x98F10000u,  1u}, // rhg -> Arab
-    {0x81110000u, 40u}, // ria -> Latn
-    {0x95110000u, 78u}, // rif -> Tfng
-    {0x95114E4Cu, 40u}, // rif-NL -> Latn
-    {0xC9310000u, 16u}, // rjs -> Deva
+    {0x81110000u, 44u}, // ria -> Latn
+    {0x95110000u, 85u}, // rif -> Tfng
+    {0x95114E4Cu, 44u}, // rif-NL -> Latn
+    {0xC9310000u, 17u}, // rjs -> Deva
     {0xCD510000u,  7u}, // rkt -> Beng
-    {0x726D0000u, 40u}, // rm -> Latn
-    {0x95910000u, 40u}, // rmf -> Latn
-    {0xB9910000u, 40u}, // rmo -> Latn
+    {0x726D0000u, 44u}, // rm -> Latn
+    {0x95910000u, 44u}, // rmf -> Latn
+    {0xB9910000u, 44u}, // rmo -> Latn
     {0xCD910000u,  1u}, // rmt -> Arab
-    {0xD1910000u, 40u}, // rmu -> Latn
-    {0x726E0000u, 40u}, // rn -> Latn
-    {0x81B10000u, 40u}, // rna -> Latn
-    {0x99B10000u, 40u}, // rng -> Latn
-    {0x726F0000u, 40u}, // ro -> Latn
-    {0x85D10000u, 40u}, // rob -> Latn
-    {0x95D10000u, 40u}, // rof -> Latn
-    {0xB9D10000u, 40u}, // roo -> Latn
-    {0xBA310000u, 40u}, // rro -> Latn
-    {0xB2710000u, 40u}, // rtm -> Latn
-    {0x72750000u, 15u}, // ru -> Cyrl
-    {0x92910000u, 15u}, // rue -> Cyrl
-    {0x9A910000u, 40u}, // rug -> Latn
-    {0x72770000u, 40u}, // rw -> Latn
-    {0xAAD10000u, 40u}, // rwk -> Latn
-    {0xBAD10000u, 40u}, // rwo -> Latn
-    {0xD3110000u, 33u}, // ryu -> Kana
-    {0x73610000u, 16u}, // sa -> Deva
-    {0x94120000u, 40u}, // saf -> Latn
-    {0x9C120000u, 15u}, // sah -> Cyrl
-    {0xC0120000u, 40u}, // saq -> Latn
-    {0xC8120000u, 40u}, // sas -> Latn
-    {0xCC120000u, 40u}, // sat -> Latn
-    {0xE4120000u, 67u}, // saz -> Saur
-    {0x80320000u, 40u}, // sba -> Latn
-    {0x90320000u, 40u}, // sbe -> Latn
-    {0xBC320000u, 40u}, // sbp -> Latn
-    {0x73630000u, 40u}, // sc -> Latn
-    {0xA8520000u, 16u}, // sck -> Deva
+    {0xD1910000u, 44u}, // rmu -> Latn
+    {0x726E0000u, 44u}, // rn -> Latn
+    {0x81B10000u, 44u}, // rna -> Latn
+    {0x99B10000u, 44u}, // rng -> Latn
+    {0x726F0000u, 44u}, // ro -> Latn
+    {0x85D10000u, 44u}, // rob -> Latn
+    {0x95D10000u, 44u}, // rof -> Latn
+    {0xB9D10000u, 44u}, // roo -> Latn
+    {0xBA310000u, 44u}, // rro -> Latn
+    {0xB2710000u, 44u}, // rtm -> Latn
+    {0x72750000u, 16u}, // ru -> Cyrl
+    {0x92910000u, 16u}, // rue -> Cyrl
+    {0x9A910000u, 44u}, // rug -> Latn
+    {0x72770000u, 44u}, // rw -> Latn
+    {0xAAD10000u, 44u}, // rwk -> Latn
+    {0xBAD10000u, 44u}, // rwo -> Latn
+    {0xD3110000u, 37u}, // ryu -> Kana
+    {0x73610000u, 17u}, // sa -> Deva
+    {0x94120000u, 44u}, // saf -> Latn
+    {0x9C120000u, 16u}, // sah -> Cyrl
+    {0xC0120000u, 44u}, // saq -> Latn
+    {0xC8120000u, 44u}, // sas -> Latn
+    {0xCC120000u, 44u}, // sat -> Latn
+    {0xD4120000u, 44u}, // sav -> Latn
+    {0xE4120000u, 72u}, // saz -> Saur
+    {0x80320000u, 44u}, // sba -> Latn
+    {0x90320000u, 44u}, // sbe -> Latn
+    {0xBC320000u, 44u}, // sbp -> Latn
+    {0x73630000u, 44u}, // sc -> Latn
+    {0xA8520000u, 17u}, // sck -> Deva
     {0xAC520000u,  1u}, // scl -> Arab
-    {0xB4520000u, 40u}, // scn -> Latn
-    {0xB8520000u, 40u}, // sco -> Latn
-    {0xC8520000u, 40u}, // scs -> Latn
+    {0xB4520000u, 44u}, // scn -> Latn
+    {0xB8520000u, 44u}, // sco -> Latn
+    {0xC8520000u, 44u}, // scs -> Latn
     {0x73640000u,  1u}, // sd -> Arab
-    {0x88720000u, 40u}, // sdc -> Latn
+    {0x88720000u, 44u}, // sdc -> Latn
     {0x9C720000u,  1u}, // sdh -> Arab
-    {0x73650000u, 40u}, // se -> Latn
-    {0x94920000u, 40u}, // sef -> Latn
-    {0x9C920000u, 40u}, // seh -> Latn
-    {0xA0920000u, 40u}, // sei -> Latn
-    {0xC8920000u, 40u}, // ses -> Latn
-    {0x73670000u, 40u}, // sg -> Latn
-    {0x80D20000u, 55u}, // sga -> Ogam
-    {0xC8D20000u, 40u}, // sgs -> Latn
-    {0xD8D20000u, 18u}, // sgw -> Ethi
-    {0xE4D20000u, 40u}, // sgz -> Latn
-    {0x73680000u, 40u}, // sh -> Latn
-    {0xA0F20000u, 78u}, // shi -> Tfng
-    {0xA8F20000u, 40u}, // shk -> Latn
-    {0xB4F20000u, 52u}, // shn -> Mymr
+    {0x73650000u, 44u}, // se -> Latn
+    {0x94920000u, 44u}, // sef -> Latn
+    {0x9C920000u, 44u}, // seh -> Latn
+    {0xA0920000u, 44u}, // sei -> Latn
+    {0xC8920000u, 44u}, // ses -> Latn
+    {0x73670000u, 44u}, // sg -> Latn
+    {0x80D20000u, 60u}, // sga -> Ogam
+    {0xC8D20000u, 44u}, // sgs -> Latn
+    {0xD8D20000u, 19u}, // sgw -> Ethi
+    {0xE4D20000u, 44u}, // sgz -> Latn
+    {0x73680000u, 44u}, // sh -> Latn
+    {0xA0F20000u, 85u}, // shi -> Tfng
+    {0xA8F20000u, 44u}, // shk -> Latn
+    {0xB4F20000u, 56u}, // shn -> Mymr
     {0xD0F20000u,  1u}, // shu -> Arab
-    {0x73690000u, 69u}, // si -> Sinh
-    {0x8D120000u, 40u}, // sid -> Latn
-    {0x99120000u, 40u}, // sig -> Latn
-    {0xAD120000u, 40u}, // sil -> Latn
-    {0xB1120000u, 40u}, // sim -> Latn
-    {0xC5320000u, 40u}, // sjr -> Latn
-    {0x736B0000u, 40u}, // sk -> Latn
-    {0x89520000u, 40u}, // skc -> Latn
+    {0x73690000u, 74u}, // si -> Sinh
+    {0x8D120000u, 44u}, // sid -> Latn
+    {0x99120000u, 44u}, // sig -> Latn
+    {0xAD120000u, 44u}, // sil -> Latn
+    {0xB1120000u, 44u}, // sim -> Latn
+    {0xC5320000u, 44u}, // sjr -> Latn
+    {0x736B0000u, 44u}, // sk -> Latn
+    {0x89520000u, 44u}, // skc -> Latn
     {0xC5520000u,  1u}, // skr -> Arab
-    {0xC9520000u, 40u}, // sks -> Latn
-    {0x736C0000u, 40u}, // sl -> Latn
-    {0x8D720000u, 40u}, // sld -> Latn
-    {0xA1720000u, 40u}, // sli -> Latn
-    {0xAD720000u, 40u}, // sll -> Latn
-    {0xE1720000u, 40u}, // sly -> Latn
-    {0x736D0000u, 40u}, // sm -> Latn
-    {0x81920000u, 40u}, // sma -> Latn
-    {0xA5920000u, 40u}, // smj -> Latn
-    {0xB5920000u, 40u}, // smn -> Latn
-    {0xBD920000u, 65u}, // smp -> Samr
-    {0xC1920000u, 40u}, // smq -> Latn
-    {0xC9920000u, 40u}, // sms -> Latn
-    {0x736E0000u, 40u}, // sn -> Latn
-    {0x89B20000u, 40u}, // snc -> Latn
-    {0xA9B20000u, 40u}, // snk -> Latn
-    {0xBDB20000u, 40u}, // snp -> Latn
-    {0xDDB20000u, 40u}, // snx -> Latn
-    {0xE1B20000u, 40u}, // sny -> Latn
-    {0x736F0000u, 40u}, // so -> Latn
-    {0xA9D20000u, 40u}, // sok -> Latn
-    {0xC1D20000u, 40u}, // soq -> Latn
-    {0xD1D20000u, 80u}, // sou -> Thai
-    {0xE1D20000u, 40u}, // soy -> Latn
-    {0x8DF20000u, 40u}, // spd -> Latn
-    {0xADF20000u, 40u}, // spl -> Latn
-    {0xC9F20000u, 40u}, // sps -> Latn
-    {0x73710000u, 40u}, // sq -> Latn
-    {0x73720000u, 15u}, // sr -> Cyrl
-    {0x73724D45u, 40u}, // sr-ME -> Latn
-    {0x7372524Fu, 40u}, // sr-RO -> Latn
-    {0x73725255u, 40u}, // sr-RU -> Latn
-    {0x73725452u, 40u}, // sr-TR -> Latn
-    {0x86320000u, 70u}, // srb -> Sora
-    {0xB6320000u, 40u}, // srn -> Latn
-    {0xC6320000u, 40u}, // srr -> Latn
-    {0xDE320000u, 16u}, // srx -> Deva
-    {0x73730000u, 40u}, // ss -> Latn
-    {0x8E520000u, 40u}, // ssd -> Latn
-    {0x9A520000u, 40u}, // ssg -> Latn
-    {0xE2520000u, 40u}, // ssy -> Latn
-    {0x73740000u, 40u}, // st -> Latn
-    {0xAA720000u, 40u}, // stk -> Latn
-    {0xC2720000u, 40u}, // stq -> Latn
-    {0x73750000u, 40u}, // su -> Latn
-    {0x82920000u, 40u}, // sua -> Latn
-    {0x92920000u, 40u}, // sue -> Latn
-    {0xAA920000u, 40u}, // suk -> Latn
-    {0xC6920000u, 40u}, // sur -> Latn
-    {0xCA920000u, 40u}, // sus -> Latn
-    {0x73760000u, 40u}, // sv -> Latn
-    {0x73770000u, 40u}, // sw -> Latn
+    {0xC9520000u, 44u}, // sks -> Latn
+    {0x736C0000u, 44u}, // sl -> Latn
+    {0x8D720000u, 44u}, // sld -> Latn
+    {0xA1720000u, 44u}, // sli -> Latn
+    {0xAD720000u, 44u}, // sll -> Latn
+    {0xE1720000u, 44u}, // sly -> Latn
+    {0x736D0000u, 44u}, // sm -> Latn
+    {0x81920000u, 44u}, // sma -> Latn
+    {0xA5920000u, 44u}, // smj -> Latn
+    {0xB5920000u, 44u}, // smn -> Latn
+    {0xBD920000u, 70u}, // smp -> Samr
+    {0xC1920000u, 44u}, // smq -> Latn
+    {0xC9920000u, 44u}, // sms -> Latn
+    {0x736E0000u, 44u}, // sn -> Latn
+    {0x89B20000u, 44u}, // snc -> Latn
+    {0xA9B20000u, 44u}, // snk -> Latn
+    {0xBDB20000u, 44u}, // snp -> Latn
+    {0xDDB20000u, 44u}, // snx -> Latn
+    {0xE1B20000u, 44u}, // sny -> Latn
+    {0x736F0000u, 44u}, // so -> Latn
+    {0x99D20000u, 75u}, // sog -> Sogd
+    {0xA9D20000u, 44u}, // sok -> Latn
+    {0xC1D20000u, 44u}, // soq -> Latn
+    {0xD1D20000u, 87u}, // sou -> Thai
+    {0xE1D20000u, 44u}, // soy -> Latn
+    {0x8DF20000u, 44u}, // spd -> Latn
+    {0xADF20000u, 44u}, // spl -> Latn
+    {0xC9F20000u, 44u}, // sps -> Latn
+    {0x73710000u, 44u}, // sq -> Latn
+    {0x73720000u, 16u}, // sr -> Cyrl
+    {0x73724D45u, 44u}, // sr-ME -> Latn
+    {0x7372524Fu, 44u}, // sr-RO -> Latn
+    {0x73725255u, 44u}, // sr-RU -> Latn
+    {0x73725452u, 44u}, // sr-TR -> Latn
+    {0x86320000u, 76u}, // srb -> Sora
+    {0xB6320000u, 44u}, // srn -> Latn
+    {0xC6320000u, 44u}, // srr -> Latn
+    {0xDE320000u, 17u}, // srx -> Deva
+    {0x73730000u, 44u}, // ss -> Latn
+    {0x8E520000u, 44u}, // ssd -> Latn
+    {0x9A520000u, 44u}, // ssg -> Latn
+    {0xE2520000u, 44u}, // ssy -> Latn
+    {0x73740000u, 44u}, // st -> Latn
+    {0xAA720000u, 44u}, // stk -> Latn
+    {0xC2720000u, 44u}, // stq -> Latn
+    {0x73750000u, 44u}, // su -> Latn
+    {0x82920000u, 44u}, // sua -> Latn
+    {0x92920000u, 44u}, // sue -> Latn
+    {0xAA920000u, 44u}, // suk -> Latn
+    {0xC6920000u, 44u}, // sur -> Latn
+    {0xCA920000u, 44u}, // sus -> Latn
+    {0x73760000u, 44u}, // sv -> Latn
+    {0x73770000u, 44u}, // sw -> Latn
     {0x86D20000u,  1u}, // swb -> Arab
-    {0x8AD20000u, 40u}, // swc -> Latn
-    {0x9AD20000u, 40u}, // swg -> Latn
-    {0xBED20000u, 40u}, // swp -> Latn
-    {0xD6D20000u, 16u}, // swv -> Deva
-    {0xB6F20000u, 40u}, // sxn -> Latn
-    {0xDAF20000u, 40u}, // sxw -> Latn
+    {0x8AD20000u, 44u}, // swc -> Latn
+    {0x9AD20000u, 44u}, // swg -> Latn
+    {0xBED20000u, 44u}, // swp -> Latn
+    {0xD6D20000u, 17u}, // swv -> Deva
+    {0xB6F20000u, 44u}, // sxn -> Latn
+    {0xDAF20000u, 44u}, // sxw -> Latn
     {0xAF120000u,  7u}, // syl -> Beng
-    {0xC7120000u, 71u}, // syr -> Syrc
-    {0xAF320000u, 40u}, // szl -> Latn
-    {0x74610000u, 74u}, // ta -> Taml
-    {0xA4130000u, 16u}, // taj -> Deva
-    {0xAC130000u, 40u}, // tal -> Latn
-    {0xB4130000u, 40u}, // tan -> Latn
-    {0xC0130000u, 40u}, // taq -> Latn
-    {0x88330000u, 40u}, // tbc -> Latn
-    {0x8C330000u, 40u}, // tbd -> Latn
-    {0x94330000u, 40u}, // tbf -> Latn
-    {0x98330000u, 40u}, // tbg -> Latn
-    {0xB8330000u, 40u}, // tbo -> Latn
-    {0xD8330000u, 40u}, // tbw -> Latn
-    {0xE4330000u, 40u}, // tbz -> Latn
-    {0xA0530000u, 40u}, // tci -> Latn
-    {0xE0530000u, 36u}, // tcy -> Knda
-    {0x8C730000u, 72u}, // tdd -> Tale
-    {0x98730000u, 16u}, // tdg -> Deva
-    {0x9C730000u, 16u}, // tdh -> Deva
-    {0x74650000u, 77u}, // te -> Telu
-    {0x8C930000u, 40u}, // ted -> Latn
-    {0xB0930000u, 40u}, // tem -> Latn
-    {0xB8930000u, 40u}, // teo -> Latn
-    {0xCC930000u, 40u}, // tet -> Latn
-    {0xA0B30000u, 40u}, // tfi -> Latn
-    {0x74670000u, 15u}, // tg -> Cyrl
+    {0xC7120000u, 78u}, // syr -> Syrc
+    {0xAF320000u, 44u}, // szl -> Latn
+    {0x74610000u, 81u}, // ta -> Taml
+    {0xA4130000u, 17u}, // taj -> Deva
+    {0xAC130000u, 44u}, // tal -> Latn
+    {0xB4130000u, 44u}, // tan -> Latn
+    {0xC0130000u, 44u}, // taq -> Latn
+    {0x88330000u, 44u}, // tbc -> Latn
+    {0x8C330000u, 44u}, // tbd -> Latn
+    {0x94330000u, 44u}, // tbf -> Latn
+    {0x98330000u, 44u}, // tbg -> Latn
+    {0xB8330000u, 44u}, // tbo -> Latn
+    {0xD8330000u, 44u}, // tbw -> Latn
+    {0xE4330000u, 44u}, // tbz -> Latn
+    {0xA0530000u, 44u}, // tci -> Latn
+    {0xE0530000u, 40u}, // tcy -> Knda
+    {0x8C730000u, 79u}, // tdd -> Tale
+    {0x98730000u, 17u}, // tdg -> Deva
+    {0x9C730000u, 17u}, // tdh -> Deva
+    {0xD0730000u, 44u}, // tdu -> Latn
+    {0x74650000u, 84u}, // te -> Telu
+    {0x8C930000u, 44u}, // ted -> Latn
+    {0xB0930000u, 44u}, // tem -> Latn
+    {0xB8930000u, 44u}, // teo -> Latn
+    {0xCC930000u, 44u}, // tet -> Latn
+    {0xA0B30000u, 44u}, // tfi -> Latn
+    {0x74670000u, 16u}, // tg -> Cyrl
     {0x7467504Bu,  1u}, // tg-PK -> Arab
-    {0x88D30000u, 40u}, // tgc -> Latn
-    {0xB8D30000u, 40u}, // tgo -> Latn
-    {0xD0D30000u, 40u}, // tgu -> Latn
-    {0x74680000u, 80u}, // th -> Thai
-    {0xACF30000u, 16u}, // thl -> Deva
-    {0xC0F30000u, 16u}, // thq -> Deva
-    {0xC4F30000u, 16u}, // thr -> Deva
-    {0x74690000u, 18u}, // ti -> Ethi
-    {0x95130000u, 40u}, // tif -> Latn
-    {0x99130000u, 18u}, // tig -> Ethi
-    {0xA9130000u, 40u}, // tik -> Latn
-    {0xB1130000u, 40u}, // tim -> Latn
-    {0xB9130000u, 40u}, // tio -> Latn
-    {0xD5130000u, 40u}, // tiv -> Latn
-    {0x746B0000u, 40u}, // tk -> Latn
-    {0xAD530000u, 40u}, // tkl -> Latn
-    {0xC5530000u, 40u}, // tkr -> Latn
-    {0xCD530000u, 16u}, // tkt -> Deva
-    {0x746C0000u, 40u}, // tl -> Latn
-    {0x95730000u, 40u}, // tlf -> Latn
-    {0xDD730000u, 40u}, // tlx -> Latn
-    {0xE1730000u, 40u}, // tly -> Latn
-    {0x9D930000u, 40u}, // tmh -> Latn
-    {0xE1930000u, 40u}, // tmy -> Latn
-    {0x746E0000u, 40u}, // tn -> Latn
-    {0x9DB30000u, 40u}, // tnh -> Latn
-    {0x746F0000u, 40u}, // to -> Latn
-    {0x95D30000u, 40u}, // tof -> Latn
-    {0x99D30000u, 40u}, // tog -> Latn
-    {0xC1D30000u, 40u}, // toq -> Latn
-    {0xA1F30000u, 40u}, // tpi -> Latn
-    {0xB1F30000u, 40u}, // tpm -> Latn
-    {0xE5F30000u, 40u}, // tpz -> Latn
-    {0xBA130000u, 40u}, // tqo -> Latn
-    {0x74720000u, 40u}, // tr -> Latn
-    {0xD2330000u, 40u}, // tru -> Latn
-    {0xD6330000u, 40u}, // trv -> Latn
+    {0x88D30000u, 44u}, // tgc -> Latn
+    {0xB8D30000u, 44u}, // tgo -> Latn
+    {0xD0D30000u, 44u}, // tgu -> Latn
+    {0x74680000u, 87u}, // th -> Thai
+    {0xACF30000u, 17u}, // thl -> Deva
+    {0xC0F30000u, 17u}, // thq -> Deva
+    {0xC4F30000u, 17u}, // thr -> Deva
+    {0x74690000u, 19u}, // ti -> Ethi
+    {0x95130000u, 44u}, // tif -> Latn
+    {0x99130000u, 19u}, // tig -> Ethi
+    {0xA9130000u, 44u}, // tik -> Latn
+    {0xB1130000u, 44u}, // tim -> Latn
+    {0xB9130000u, 44u}, // tio -> Latn
+    {0xD5130000u, 44u}, // tiv -> Latn
+    {0x746B0000u, 44u}, // tk -> Latn
+    {0xAD530000u, 44u}, // tkl -> Latn
+    {0xC5530000u, 44u}, // tkr -> Latn
+    {0xCD530000u, 17u}, // tkt -> Deva
+    {0x746C0000u, 44u}, // tl -> Latn
+    {0x95730000u, 44u}, // tlf -> Latn
+    {0xDD730000u, 44u}, // tlx -> Latn
+    {0xE1730000u, 44u}, // tly -> Latn
+    {0x9D930000u, 44u}, // tmh -> Latn
+    {0xE1930000u, 44u}, // tmy -> Latn
+    {0x746E0000u, 44u}, // tn -> Latn
+    {0x9DB30000u, 44u}, // tnh -> Latn
+    {0x746F0000u, 44u}, // to -> Latn
+    {0x95D30000u, 44u}, // tof -> Latn
+    {0x99D30000u, 44u}, // tog -> Latn
+    {0xC1D30000u, 44u}, // toq -> Latn
+    {0xA1F30000u, 44u}, // tpi -> Latn
+    {0xB1F30000u, 44u}, // tpm -> Latn
+    {0xE5F30000u, 44u}, // tpz -> Latn
+    {0xBA130000u, 44u}, // tqo -> Latn
+    {0x74720000u, 44u}, // tr -> Latn
+    {0xD2330000u, 44u}, // tru -> Latn
+    {0xD6330000u, 44u}, // trv -> Latn
     {0xDA330000u,  1u}, // trw -> Arab
-    {0x74730000u, 40u}, // ts -> Latn
-    {0x8E530000u, 21u}, // tsd -> Grek
-    {0x96530000u, 16u}, // tsf -> Deva
-    {0x9A530000u, 40u}, // tsg -> Latn
-    {0xA6530000u, 81u}, // tsj -> Tibt
-    {0xDA530000u, 40u}, // tsw -> Latn
-    {0x74740000u, 15u}, // tt -> Cyrl
-    {0x8E730000u, 40u}, // ttd -> Latn
-    {0x92730000u, 40u}, // tte -> Latn
-    {0xA6730000u, 40u}, // ttj -> Latn
-    {0xC6730000u, 40u}, // ttr -> Latn
-    {0xCA730000u, 80u}, // tts -> Thai
-    {0xCE730000u, 40u}, // ttt -> Latn
-    {0x9E930000u, 40u}, // tuh -> Latn
-    {0xAE930000u, 40u}, // tul -> Latn
-    {0xB2930000u, 40u}, // tum -> Latn
-    {0xC2930000u, 40u}, // tuq -> Latn
-    {0x8EB30000u, 40u}, // tvd -> Latn
-    {0xAEB30000u, 40u}, // tvl -> Latn
-    {0xD2B30000u, 40u}, // tvu -> Latn
-    {0x9ED30000u, 40u}, // twh -> Latn
-    {0xC2D30000u, 40u}, // twq -> Latn
-    {0x9AF30000u, 75u}, // txg -> Tang
-    {0x74790000u, 40u}, // ty -> Latn
-    {0x83130000u, 40u}, // tya -> Latn
-    {0xD7130000u, 15u}, // tyv -> Cyrl
-    {0xB3330000u, 40u}, // tzm -> Latn
-    {0xD0340000u, 40u}, // ubu -> Latn
-    {0xB0740000u, 15u}, // udm -> Cyrl
+    {0x74730000u, 44u}, // ts -> Latn
+    {0x8E530000u, 24u}, // tsd -> Grek
+    {0x96530000u, 17u}, // tsf -> Deva
+    {0x9A530000u, 44u}, // tsg -> Latn
+    {0xA6530000u, 88u}, // tsj -> Tibt
+    {0xDA530000u, 44u}, // tsw -> Latn
+    {0x74740000u, 16u}, // tt -> Cyrl
+    {0x8E730000u, 44u}, // ttd -> Latn
+    {0x92730000u, 44u}, // tte -> Latn
+    {0xA6730000u, 44u}, // ttj -> Latn
+    {0xC6730000u, 44u}, // ttr -> Latn
+    {0xCA730000u, 87u}, // tts -> Thai
+    {0xCE730000u, 44u}, // ttt -> Latn
+    {0x9E930000u, 44u}, // tuh -> Latn
+    {0xAE930000u, 44u}, // tul -> Latn
+    {0xB2930000u, 44u}, // tum -> Latn
+    {0xC2930000u, 44u}, // tuq -> Latn
+    {0x8EB30000u, 44u}, // tvd -> Latn
+    {0xAEB30000u, 44u}, // tvl -> Latn
+    {0xD2B30000u, 44u}, // tvu -> Latn
+    {0x9ED30000u, 44u}, // twh -> Latn
+    {0xC2D30000u, 44u}, // twq -> Latn
+    {0x9AF30000u, 82u}, // txg -> Tang
+    {0x74790000u, 44u}, // ty -> Latn
+    {0x83130000u, 44u}, // tya -> Latn
+    {0xD7130000u, 16u}, // tyv -> Cyrl
+    {0xB3330000u, 44u}, // tzm -> Latn
+    {0xD0340000u, 44u}, // ubu -> Latn
+    {0xB0740000u, 16u}, // udm -> Cyrl
     {0x75670000u,  1u}, // ug -> Arab
-    {0x75674B5Au, 15u}, // ug-KZ -> Cyrl
-    {0x75674D4Eu, 15u}, // ug-MN -> Cyrl
-    {0x80D40000u, 82u}, // uga -> Ugar
-    {0x756B0000u, 15u}, // uk -> Cyrl
-    {0xA1740000u, 40u}, // uli -> Latn
-    {0x85940000u, 40u}, // umb -> Latn
+    {0x75674B5Au, 16u}, // ug-KZ -> Cyrl
+    {0x75674D4Eu, 16u}, // ug-MN -> Cyrl
+    {0x80D40000u, 89u}, // uga -> Ugar
+    {0x756B0000u, 16u}, // uk -> Cyrl
+    {0xA1740000u, 44u}, // uli -> Latn
+    {0x85940000u, 44u}, // umb -> Latn
     {0xC5B40000u,  7u}, // unr -> Beng
-    {0xC5B44E50u, 16u}, // unr-NP -> Deva
+    {0xC5B44E50u, 17u}, // unr-NP -> Deva
     {0xDDB40000u,  7u}, // unx -> Beng
+    {0xA9D40000u, 44u}, // uok -> Latn
     {0x75720000u,  1u}, // ur -> Arab
-    {0xA2340000u, 40u}, // uri -> Latn
-    {0xCE340000u, 40u}, // urt -> Latn
-    {0xDA340000u, 40u}, // urw -> Latn
-    {0x82540000u, 40u}, // usa -> Latn
-    {0xC6740000u, 40u}, // utr -> Latn
-    {0x9EB40000u, 40u}, // uvh -> Latn
-    {0xAEB40000u, 40u}, // uvl -> Latn
-    {0x757A0000u, 40u}, // uz -> Latn
+    {0xA2340000u, 44u}, // uri -> Latn
+    {0xCE340000u, 44u}, // urt -> Latn
+    {0xDA340000u, 44u}, // urw -> Latn
+    {0x82540000u, 44u}, // usa -> Latn
+    {0xC6740000u, 44u}, // utr -> Latn
+    {0x9EB40000u, 44u}, // uvh -> Latn
+    {0xAEB40000u, 44u}, // uvl -> Latn
+    {0x757A0000u, 44u}, // uz -> Latn
     {0x757A4146u,  1u}, // uz-AF -> Arab
-    {0x757A434Eu, 15u}, // uz-CN -> Cyrl
-    {0x98150000u, 40u}, // vag -> Latn
-    {0xA0150000u, 83u}, // vai -> Vaii
-    {0xB4150000u, 40u}, // van -> Latn
-    {0x76650000u, 40u}, // ve -> Latn
-    {0x88950000u, 40u}, // vec -> Latn
-    {0xBC950000u, 40u}, // vep -> Latn
-    {0x76690000u, 40u}, // vi -> Latn
-    {0x89150000u, 40u}, // vic -> Latn
-    {0xD5150000u, 40u}, // viv -> Latn
-    {0xC9750000u, 40u}, // vls -> Latn
-    {0x95950000u, 40u}, // vmf -> Latn
-    {0xD9950000u, 40u}, // vmw -> Latn
-    {0x766F0000u, 40u}, // vo -> Latn
-    {0xCDD50000u, 40u}, // vot -> Latn
-    {0xBA350000u, 40u}, // vro -> Latn
-    {0xB6950000u, 40u}, // vun -> Latn
-    {0xCE950000u, 40u}, // vut -> Latn
-    {0x77610000u, 40u}, // wa -> Latn
-    {0x90160000u, 40u}, // wae -> Latn
-    {0xA4160000u, 40u}, // waj -> Latn
-    {0xAC160000u, 18u}, // wal -> Ethi
-    {0xB4160000u, 40u}, // wan -> Latn
-    {0xC4160000u, 40u}, // war -> Latn
-    {0xBC360000u, 40u}, // wbp -> Latn
-    {0xC0360000u, 77u}, // wbq -> Telu
-    {0xC4360000u, 16u}, // wbr -> Deva
-    {0xA0560000u, 40u}, // wci -> Latn
-    {0xC4960000u, 40u}, // wer -> Latn
-    {0xA0D60000u, 40u}, // wgi -> Latn
-    {0x98F60000u, 40u}, // whg -> Latn
-    {0x85160000u, 40u}, // wib -> Latn
-    {0xD1160000u, 40u}, // wiu -> Latn
-    {0xD5160000u, 40u}, // wiv -> Latn
-    {0x81360000u, 40u}, // wja -> Latn
-    {0xA1360000u, 40u}, // wji -> Latn
-    {0xC9760000u, 40u}, // wls -> Latn
-    {0xB9960000u, 40u}, // wmo -> Latn
-    {0x89B60000u, 40u}, // wnc -> Latn
+    {0x757A434Eu, 16u}, // uz-CN -> Cyrl
+    {0x98150000u, 44u}, // vag -> Latn
+    {0xA0150000u, 90u}, // vai -> Vaii
+    {0xB4150000u, 44u}, // van -> Latn
+    {0x76650000u, 44u}, // ve -> Latn
+    {0x88950000u, 44u}, // vec -> Latn
+    {0xBC950000u, 44u}, // vep -> Latn
+    {0x76690000u, 44u}, // vi -> Latn
+    {0x89150000u, 44u}, // vic -> Latn
+    {0xD5150000u, 44u}, // viv -> Latn
+    {0xC9750000u, 44u}, // vls -> Latn
+    {0x95950000u, 44u}, // vmf -> Latn
+    {0xD9950000u, 44u}, // vmw -> Latn
+    {0x766F0000u, 44u}, // vo -> Latn
+    {0xCDD50000u, 44u}, // vot -> Latn
+    {0xBA350000u, 44u}, // vro -> Latn
+    {0xB6950000u, 44u}, // vun -> Latn
+    {0xCE950000u, 44u}, // vut -> Latn
+    {0x77610000u, 44u}, // wa -> Latn
+    {0x90160000u, 44u}, // wae -> Latn
+    {0xA4160000u, 44u}, // waj -> Latn
+    {0xAC160000u, 19u}, // wal -> Ethi
+    {0xB4160000u, 44u}, // wan -> Latn
+    {0xC4160000u, 44u}, // war -> Latn
+    {0xBC360000u, 44u}, // wbp -> Latn
+    {0xC0360000u, 84u}, // wbq -> Telu
+    {0xC4360000u, 17u}, // wbr -> Deva
+    {0xA0560000u, 44u}, // wci -> Latn
+    {0xC4960000u, 44u}, // wer -> Latn
+    {0xA0D60000u, 44u}, // wgi -> Latn
+    {0x98F60000u, 44u}, // whg -> Latn
+    {0x85160000u, 44u}, // wib -> Latn
+    {0xD1160000u, 44u}, // wiu -> Latn
+    {0xD5160000u, 44u}, // wiv -> Latn
+    {0x81360000u, 44u}, // wja -> Latn
+    {0xA1360000u, 44u}, // wji -> Latn
+    {0xC9760000u, 44u}, // wls -> Latn
+    {0xB9960000u, 44u}, // wmo -> Latn
+    {0x89B60000u, 44u}, // wnc -> Latn
     {0xA1B60000u,  1u}, // wni -> Arab
-    {0xD1B60000u, 40u}, // wnu -> Latn
-    {0x776F0000u, 40u}, // wo -> Latn
-    {0x85D60000u, 40u}, // wob -> Latn
-    {0xC9D60000u, 40u}, // wos -> Latn
-    {0xCA360000u, 40u}, // wrs -> Latn
-    {0xAA560000u, 40u}, // wsk -> Latn
-    {0xB2760000u, 16u}, // wtm -> Deva
-    {0xD2960000u, 24u}, // wuu -> Hans
-    {0xD6960000u, 40u}, // wuv -> Latn
-    {0x82D60000u, 40u}, // wwa -> Latn
-    {0xD4170000u, 40u}, // xav -> Latn
-    {0xA0370000u, 40u}, // xbi -> Latn
-    {0xC4570000u, 10u}, // xcr -> Cari
-    {0xC8970000u, 40u}, // xes -> Latn
-    {0x78680000u, 40u}, // xh -> Latn
-    {0x81770000u, 40u}, // xla -> Latn
-    {0x89770000u, 44u}, // xlc -> Lyci
-    {0x8D770000u, 45u}, // xld -> Lydi
-    {0x95970000u, 19u}, // xmf -> Geor
-    {0xB5970000u, 47u}, // xmn -> Mani
-    {0xC5970000u, 48u}, // xmr -> Merc
-    {0x81B70000u, 53u}, // xna -> Narb
-    {0xC5B70000u, 16u}, // xnr -> Deva
-    {0x99D70000u, 40u}, // xog -> Latn
-    {0xB5D70000u, 40u}, // xon -> Latn
-    {0xC5F70000u, 63u}, // xpr -> Prti
-    {0x86370000u, 40u}, // xrb -> Latn
-    {0x82570000u, 66u}, // xsa -> Sarb
-    {0xA2570000u, 40u}, // xsi -> Latn
-    {0xB2570000u, 40u}, // xsm -> Latn
-    {0xC6570000u, 16u}, // xsr -> Deva
-    {0x92D70000u, 40u}, // xwe -> Latn
-    {0xB0180000u, 40u}, // yam -> Latn
-    {0xB8180000u, 40u}, // yao -> Latn
-    {0xBC180000u, 40u}, // yap -> Latn
-    {0xC8180000u, 40u}, // yas -> Latn
-    {0xCC180000u, 40u}, // yat -> Latn
-    {0xD4180000u, 40u}, // yav -> Latn
-    {0xE0180000u, 40u}, // yay -> Latn
-    {0xE4180000u, 40u}, // yaz -> Latn
-    {0x80380000u, 40u}, // yba -> Latn
-    {0x84380000u, 40u}, // ybb -> Latn
-    {0xE0380000u, 40u}, // yby -> Latn
-    {0xC4980000u, 40u}, // yer -> Latn
-    {0xC4D80000u, 40u}, // ygr -> Latn
-    {0xD8D80000u, 40u}, // ygw -> Latn
-    {0x79690000u, 27u}, // yi -> Hebr
-    {0xB9580000u, 40u}, // yko -> Latn
-    {0x91780000u, 40u}, // yle -> Latn
-    {0x99780000u, 40u}, // ylg -> Latn
-    {0xAD780000u, 40u}, // yll -> Latn
-    {0xAD980000u, 40u}, // yml -> Latn
-    {0x796F0000u, 40u}, // yo -> Latn
-    {0xB5D80000u, 40u}, // yon -> Latn
-    {0x86380000u, 40u}, // yrb -> Latn
-    {0x92380000u, 40u}, // yre -> Latn
-    {0xAE380000u, 40u}, // yrl -> Latn
-    {0xCA580000u, 40u}, // yss -> Latn
-    {0x82980000u, 40u}, // yua -> Latn
-    {0x92980000u, 25u}, // yue -> Hant
-    {0x9298434Eu, 24u}, // yue-CN -> Hans
-    {0xA6980000u, 40u}, // yuj -> Latn
-    {0xCE980000u, 40u}, // yut -> Latn
-    {0xDA980000u, 40u}, // yuw -> Latn
-    {0x7A610000u, 40u}, // za -> Latn
-    {0x98190000u, 40u}, // zag -> Latn
+    {0xD1B60000u, 44u}, // wnu -> Latn
+    {0x776F0000u, 44u}, // wo -> Latn
+    {0x85D60000u, 44u}, // wob -> Latn
+    {0xC9D60000u, 44u}, // wos -> Latn
+    {0xCA360000u, 44u}, // wrs -> Latn
+    {0x9A560000u, 21u}, // wsg -> Gong
+    {0xAA560000u, 44u}, // wsk -> Latn
+    {0xB2760000u, 17u}, // wtm -> Deva
+    {0xD2960000u, 27u}, // wuu -> Hans
+    {0xD6960000u, 44u}, // wuv -> Latn
+    {0x82D60000u, 44u}, // wwa -> Latn
+    {0xD4170000u, 44u}, // xav -> Latn
+    {0xA0370000u, 44u}, // xbi -> Latn
+    {0xC4570000u, 11u}, // xcr -> Cari
+    {0xC8970000u, 44u}, // xes -> Latn
+    {0x78680000u, 44u}, // xh -> Latn
+    {0x81770000u, 44u}, // xla -> Latn
+    {0x89770000u, 48u}, // xlc -> Lyci
+    {0x8D770000u, 49u}, // xld -> Lydi
+    {0x95970000u, 20u}, // xmf -> Geor
+    {0xB5970000u, 51u}, // xmn -> Mani
+    {0xC5970000u, 52u}, // xmr -> Merc
+    {0x81B70000u, 57u}, // xna -> Narb
+    {0xC5B70000u, 17u}, // xnr -> Deva
+    {0x99D70000u, 44u}, // xog -> Latn
+    {0xB5D70000u, 44u}, // xon -> Latn
+    {0xC5F70000u, 68u}, // xpr -> Prti
+    {0x86370000u, 44u}, // xrb -> Latn
+    {0x82570000u, 71u}, // xsa -> Sarb
+    {0xA2570000u, 44u}, // xsi -> Latn
+    {0xB2570000u, 44u}, // xsm -> Latn
+    {0xC6570000u, 17u}, // xsr -> Deva
+    {0x92D70000u, 44u}, // xwe -> Latn
+    {0xB0180000u, 44u}, // yam -> Latn
+    {0xB8180000u, 44u}, // yao -> Latn
+    {0xBC180000u, 44u}, // yap -> Latn
+    {0xC8180000u, 44u}, // yas -> Latn
+    {0xCC180000u, 44u}, // yat -> Latn
+    {0xD4180000u, 44u}, // yav -> Latn
+    {0xE0180000u, 44u}, // yay -> Latn
+    {0xE4180000u, 44u}, // yaz -> Latn
+    {0x80380000u, 44u}, // yba -> Latn
+    {0x84380000u, 44u}, // ybb -> Latn
+    {0xE0380000u, 44u}, // yby -> Latn
+    {0xC4980000u, 44u}, // yer -> Latn
+    {0xC4D80000u, 44u}, // ygr -> Latn
+    {0xD8D80000u, 44u}, // ygw -> Latn
+    {0x79690000u, 30u}, // yi -> Hebr
+    {0xB9580000u, 44u}, // yko -> Latn
+    {0x91780000u, 44u}, // yle -> Latn
+    {0x99780000u, 44u}, // ylg -> Latn
+    {0xAD780000u, 44u}, // yll -> Latn
+    {0xAD980000u, 44u}, // yml -> Latn
+    {0x796F0000u, 44u}, // yo -> Latn
+    {0xB5D80000u, 44u}, // yon -> Latn
+    {0x86380000u, 44u}, // yrb -> Latn
+    {0x92380000u, 44u}, // yre -> Latn
+    {0xAE380000u, 44u}, // yrl -> Latn
+    {0xCA580000u, 44u}, // yss -> Latn
+    {0x82980000u, 44u}, // yua -> Latn
+    {0x92980000u, 28u}, // yue -> Hant
+    {0x9298434Eu, 27u}, // yue-CN -> Hans
+    {0xA6980000u, 44u}, // yuj -> Latn
+    {0xCE980000u, 44u}, // yut -> Latn
+    {0xDA980000u, 44u}, // yuw -> Latn
+    {0x7A610000u, 44u}, // za -> Latn
+    {0x98190000u, 44u}, // zag -> Latn
     {0xA4790000u,  1u}, // zdj -> Arab
-    {0x80990000u, 40u}, // zea -> Latn
-    {0x9CD90000u, 78u}, // zgh -> Tfng
-    {0x7A680000u, 24u}, // zh -> Hans
-    {0x7A684155u, 25u}, // zh-AU -> Hant
-    {0x7A68424Eu, 25u}, // zh-BN -> Hant
-    {0x7A684742u, 25u}, // zh-GB -> Hant
-    {0x7A684746u, 25u}, // zh-GF -> Hant
-    {0x7A68484Bu, 25u}, // zh-HK -> Hant
-    {0x7A684944u, 25u}, // zh-ID -> Hant
-    {0x7A684D4Fu, 25u}, // zh-MO -> Hant
-    {0x7A684D59u, 25u}, // zh-MY -> Hant
-    {0x7A685041u, 25u}, // zh-PA -> Hant
-    {0x7A685046u, 25u}, // zh-PF -> Hant
-    {0x7A685048u, 25u}, // zh-PH -> Hant
-    {0x7A685352u, 25u}, // zh-SR -> Hant
-    {0x7A685448u, 25u}, // zh-TH -> Hant
-    {0x7A685457u, 25u}, // zh-TW -> Hant
-    {0x7A685553u, 25u}, // zh-US -> Hant
-    {0x7A68564Eu, 25u}, // zh-VN -> Hant
-    {0x81190000u, 40u}, // zia -> Latn
-    {0xB1790000u, 40u}, // zlm -> Latn
-    {0xA1990000u, 40u}, // zmi -> Latn
-    {0x91B90000u, 40u}, // zne -> Latn
-    {0x7A750000u, 40u}, // zu -> Latn
-    {0x83390000u, 40u}, // zza -> Latn
+    {0x80990000u, 44u}, // zea -> Latn
+    {0x9CD90000u, 85u}, // zgh -> Tfng
+    {0x7A680000u, 27u}, // zh -> Hans
+    {0x7A684155u, 28u}, // zh-AU -> Hant
+    {0x7A68424Eu, 28u}, // zh-BN -> Hant
+    {0x7A684742u, 28u}, // zh-GB -> Hant
+    {0x7A684746u, 28u}, // zh-GF -> Hant
+    {0x7A68484Bu, 28u}, // zh-HK -> Hant
+    {0x7A684944u, 28u}, // zh-ID -> Hant
+    {0x7A684D4Fu, 28u}, // zh-MO -> Hant
+    {0x7A684D59u, 28u}, // zh-MY -> Hant
+    {0x7A685041u, 28u}, // zh-PA -> Hant
+    {0x7A685046u, 28u}, // zh-PF -> Hant
+    {0x7A685048u, 28u}, // zh-PH -> Hant
+    {0x7A685352u, 28u}, // zh-SR -> Hant
+    {0x7A685448u, 28u}, // zh-TH -> Hant
+    {0x7A685457u, 28u}, // zh-TW -> Hant
+    {0x7A685553u, 28u}, // zh-US -> Hant
+    {0x7A68564Eu, 28u}, // zh-VN -> Hant
+    {0xDCF90000u, 59u}, // zhx -> Nshu
+    {0x81190000u, 44u}, // zia -> Latn
+    {0xB1790000u, 44u}, // zlm -> Latn
+    {0xA1990000u, 44u}, // zmi -> Latn
+    {0x91B90000u, 44u}, // zne -> Latn
+    {0x7A750000u, 44u}, // zu -> Latn
+    {0x83390000u, 44u}, // zza -> Latn
 });
 
 std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
@@ -1452,6 +1492,7 @@
     0x904049444C61746ELLU, // ace_Latn_ID
     0x9C4055474C61746ELLU, // ach_Latn_UG
     0x806047484C61746ELLU, // ada_Latn_GH
+    0xBC60425454696274LLU, // adp_Tibt_BT
     0xE06052554379726CLLU, // ady_Cyrl_RU
     0x6165495241767374LLU, // ae_Avst_IR
     0x8480544E41726162LLU, // aeb_Arab_TN
@@ -1464,6 +1505,7 @@
     0xCD6052554379726CLLU, // alt_Cyrl_RU
     0x616D455445746869LLU, // am_Ethi_ET
     0xB9804E474C61746ELLU, // amo_Latn_NG
+    0x616E45534C61746ELLU, // an_Latn_ES
     0xE5C049444C61746ELLU, // aoz_Latn_ID
     0x8DE0544741726162LLU, // apd_Arab_TG
     0x6172454741726162LLU, // ar_Arab_EG
@@ -1473,6 +1515,7 @@
     0xB620434C4C61746ELLU, // arn_Latn_CL
     0xBA20424F4C61746ELLU, // aro_Latn_BO
     0xC220445A41726162LLU, // arq_Arab_DZ
+    0xCA20534141726162LLU, // ars_Arab_SA
     0xE2204D4141726162LLU, // ary_Arab_MA
     0xE620454741726162LLU, // arz_Arab_EG
     0x6173494E42656E67LLU, // as_Beng_IN
@@ -1510,13 +1553,13 @@
     0xDCC154524772656BLLU, // bgx_Grek_TR
     0x84E1494E44657661LLU, // bhb_Deva_IN
     0xA0E1494E44657661LLU, // bhi_Deva_IN
-    0xA8E150484C61746ELLU, // bhk_Latn_PH
     0xB8E1494E44657661LLU, // bho_Deva_IN
     0x626956554C61746ELLU, // bi_Latn_VU
     0xA90150484C61746ELLU, // bik_Latn_PH
     0xB5014E474C61746ELLU, // bin_Latn_NG
     0xA521494E44657661LLU, // bjj_Deva_IN
     0xB52149444C61746ELLU, // bjn_Latn_ID
+    0xCD21534E4C61746ELLU, // bjt_Latn_SN
     0xB141434D4C61746ELLU, // bkm_Latn_CM
     0xD14150484C61746ELLU, // bku_Latn_PH
     0xCD61564E54617674LLU, // blt_Tavt_VN
@@ -1546,7 +1589,6 @@
     0x93214D4C4C61746ELLU, // bze_Latn_ML
     0x636145534C61746ELLU, // ca_Latn_ES
     0x9C424E474C61746ELLU, // cch_Latn_NG
-    0xBC42494E42656E67LLU, // ccp_Beng_IN
     0xBC42424443616B6DLLU, // ccp_Cakm_BD
     0x636552554379726CLLU, // ce_Cyrl_RU
     0x848250484C61746ELLU, // ceb_Latn_PH
@@ -1557,13 +1599,16 @@
     0xB8E255534C61746ELLU, // cho_Latn_US
     0xBCE243414C61746ELLU, // chp_Latn_CA
     0xC4E2555343686572LLU, // chr_Cher_US
+    0x890255534C61746ELLU, // cic_Latn_US
     0x81224B4841726162LLU, // cja_Arab_KH
     0xB122564E4368616DLLU, // cjm_Cham_VN
     0x8542495141726162LLU, // ckb_Arab_IQ
+    0x99824D4E536F796FLLU, // cmg_Soyo_MN
     0x636F46524C61746ELLU, // co_Latn_FR
     0xBDC24547436F7074LLU, // cop_Copt_EG
     0xC9E250484C61746ELLU, // cps_Latn_PH
     0x6372434143616E73LLU, // cr_Cans_CA
+    0x9E2255414379726CLLU, // crh_Cyrl_UA
     0xA622434143616E73LLU, // crj_Cans_CA
     0xAA22434143616E73LLU, // crk_Cans_CA
     0xAE22434143616E73LLU, // crl_Cans_CA
@@ -1588,6 +1633,7 @@
     0x91234E454C61746ELLU, // dje_Latn_NE
     0xA5A343494C61746ELLU, // dnj_Latn_CI
     0xA1C3494E41726162LLU, // doi_Arab_IN
+    0x9E23434E4D6F6E67LLU, // drh_Mong_CN
     0x864344454C61746ELLU, // dsb_Latn_DE
     0xB2634D4C4C61746ELLU, // dtm_Latn_ML
     0xBE634D594C61746ELLU, // dtp_Latn_MY
@@ -1610,6 +1656,7 @@
     0x657345534C61746ELLU, // es_Latn_ES
     0x65734D584C61746ELLU, // es_Latn_MX
     0x657355534C61746ELLU, // es_Latn_US
+    0x9A44494E476F6E6DLLU, // esg_Gonm_IN
     0xD24455534C61746ELLU, // esu_Latn_US
     0x657445454C61746ELLU, // et_Latn_EE
     0xCE6449544974616CLLU, // ett_Ital_IT
@@ -1700,10 +1747,10 @@
     0x687548554C61746ELLU, // hu_Latn_HU
     0x6879414D41726D6ELLU, // hy_Armn_AM
     0x687A4E414C61746ELLU, // hz_Latn_NA
-    0x696146524C61746ELLU, // ia_Latn_FR
     0x80284D594C61746ELLU, // iba_Latn_MY
     0x84284E474C61746ELLU, // ibb_Latn_NG
     0x696449444C61746ELLU, // id_Latn_ID
+    0x90A854474C61746ELLU, // ife_Latn_TG
     0x69674E474C61746ELLU, // ig_Latn_NG
     0x6969434E59696969LLU, // ii_Yiii_CN
     0x696B55534C61746ELLU, // ik_Latn_US
@@ -1764,6 +1811,7 @@
     0x6B6D4B484B686D72LLU, // km_Khmr_KH
     0x858A414F4C61746ELLU, // kmb_Latn_AO
     0x6B6E494E4B6E6461LLU, // kn_Knda_IN
+    0x95AA47574C61746ELLU, // knf_Latn_GW
     0x6B6F4B524B6F7265LLU, // ko_Kore_KR
     0xA1CA52554379726CLLU, // koi_Cyrl_RU
     0xA9CA494E44657661LLU, // kok_Deva_IN
@@ -1778,6 +1826,7 @@
     0x864A545A4C61746ELLU, // ksb_Latn_TZ
     0x964A434D4C61746ELLU, // ksf_Latn_CM
     0x9E4A44454C61746ELLU, // ksh_Latn_DE
+    0xC66A4D594C61746ELLU, // ktr_Latn_MY
     0x6B75495141726162LLU, // ku_Arab_IQ
     0x6B7554524C61746ELLU, // ku_Latn_TR
     0xB28A52554379726CLLU, // kum_Cyrl_RU
@@ -1790,6 +1839,8 @@
     0x6B79434E41726162LLU, // ky_Arab_CN
     0x6B794B474379726CLLU, // ky_Cyrl_KG
     0x6B7954524C61746ELLU, // ky_Latn_TR
+    0xA72A4D594C61746ELLU, // kzj_Latn_MY
+    0xCF2A4D594C61746ELLU, // kzt_Latn_MY
     0x6C6156414C61746ELLU, // la_Latn_VA
     0x840B47524C696E61LLU, // lab_Lina_GR
     0x8C0B494C48656272LLU, // lad_Hebr_IL
@@ -1854,6 +1905,7 @@
     0x6D694E5A4C61746ELLU, // mi_Latn_NZ
     0xB50C49444C61746ELLU, // min_Latn_ID
     0xC90C495148617472LLU, // mis_Hatr_IQ
+    0xC90C4E474D656466LLU, // mis_Medf_NG
     0x6D6B4D4B4379726CLLU, // mk_Cyrl_MK
     0x6D6C494E4D6C796DLLU, // ml_Mlym_IN
     0xC96C53444C61746ELLU, // mls_Latn_SD
@@ -1861,6 +1913,7 @@
     0x6D6E434E4D6F6E67LLU, // mn_Mong_CN
     0xA1AC494E42656E67LLU, // mni_Beng_IN
     0xD9AC4D4D4D796D72LLU, // mnw_Mymr_MM
+    0x6D6F524F4C61746ELLU, // mo_Latn_RO
     0x91CC43414C61746ELLU, // moe_Latn_CA
     0x9DCC43414C61746ELLU, // moh_Latn_CA
     0xC9CC42464C61746ELLU, // mos_Latn_BF
@@ -1877,6 +1930,7 @@
     0xAACC4D4C4C61746ELLU, // mwk_Latn_ML
     0xC6CC494E44657661LLU, // mwr_Deva_IN
     0xD6CC49444C61746ELLU, // mwv_Latn_ID
+    0xDACC5553486D6E70LLU, // mww_Hmnp_US
     0x8AEC5A574C61746ELLU, // mxc_Latn_ZW
     0x6D794D4D4D796D72LLU, // my_Mymr_MM
     0xD70C52554379726CLLU, // myv_Cyrl_RU
@@ -1905,6 +1959,7 @@
     0x998D434D4C61746ELLU, // nmg_Latn_CM
     0x6E6E4E4F4C61746ELLU, // nn_Latn_NO
     0x9DAD434D4C61746ELLU, // nnh_Latn_CM
+    0xBDAD494E5763686FLLU, // nnp_Wcho_IN
     0x6E6F4E4F4C61746ELLU, // no_Latn_NO
     0x8DCD54484C616E61LLU, // nod_Lana_TH
     0x91CD494E44657661LLU, // noe_Deva_IN
@@ -1947,6 +2002,7 @@
     0xC98F49544C61746ELLU, // pms_Latn_IT
     0xCDAF47524772656BLLU, // pnt_Grek_GR
     0xB5CF464D4C61746ELLU, // pon_Latn_FM
+    0x81EF494E44657661LLU, // ppa_Deva_IN
     0x822F504B4B686172LLU, // pra_Khar_PK
     0x8E2F495241726162LLU, // prd_Arab_IR
     0x7073414641726162LLU, // ps_Arab_AF
@@ -1959,6 +2015,7 @@
     0x945152454C61746ELLU, // rcf_Latn_RE
     0xA49149444C61746ELLU, // rej_Latn_ID
     0xB4D149544C61746ELLU, // rgn_Latn_IT
+    0x98F14D4D41726162LLU, // rhg_Arab_MM
     0x8111494E4C61746ELLU, // ria_Latn_IN
     0x95114D4154666E67LLU, // rif_Tfng_MA
     0xC9314E5044657661LLU, // rjs_Deva_NP
@@ -1986,6 +2043,7 @@
     0xC0124B454C61746ELLU, // saq_Latn_KE
     0xC81249444C61746ELLU, // sas_Latn_ID
     0xCC12494E4C61746ELLU, // sat_Latn_IN
+    0xD412534E4C61746ELLU, // sav_Latn_SN
     0xE412494E53617572LLU, // saz_Saur_IN
     0xBC32545A4C61746ELLU, // sbp_Latn_TZ
     0x736349544C61746ELLU, // sc_Latn_IT
@@ -2025,6 +2083,7 @@
     0x736E5A574C61746ELLU, // sn_Latn_ZW
     0xA9B24D4C4C61746ELLU, // snk_Latn_ML
     0x736F534F4C61746ELLU, // so_Latn_SO
+    0x99D2555A536F6764LLU, // sog_Sogd_UZ
     0xD1D2544854686169LLU, // sou_Thai_TH
     0x7371414C4C61746ELLU, // sq_Latn_AL
     0x737252534379726CLLU, // sr_Cyrl_RS
@@ -2057,6 +2116,7 @@
     0x8C73434E54616C65LLU, // tdd_Tale_CN
     0x98734E5044657661LLU, // tdg_Deva_NP
     0x9C734E5044657661LLU, // tdh_Deva_NP
+    0xD0734D594C61746ELLU, // tdu_Latn_MY
     0x7465494E54656C75LLU, // te_Telu_IN
     0xB093534C4C61746ELLU, // tem_Latn_SL
     0xB89355474C61746ELLU, // teo_Latn_UG
@@ -2135,6 +2195,7 @@
     0xC97657464C61746ELLU, // wls_Latn_WF
     0xA1B64B4D41726162LLU, // wni_Arab_KM
     0x776F534E4C61746ELLU, // wo_Latn_SN
+    0x9A56494E476F6E67LLU, // wsg_Gong_IN
     0xB276494E44657661LLU, // wtm_Deva_IN
     0xD296434E48616E73LLU, // wuu_Hans_CN
     0xD41742524C61746ELLU, // xav_Latn_BR
@@ -2169,6 +2230,7 @@
     0x7A68545748616E62LLU, // zh_Hanb_TW
     0x7A68434E48616E73LLU, // zh_Hans_CN
     0x7A68545748616E74LLU, // zh_Hant_TW
+    0xDCF9434E4E736875LLU, // zhx_Nshu_CN
     0xB17954474C61746ELLU, // zlm_Latn_TG
     0xA1994D594C61746ELLU, // zmi_Latn_MY
     0x7A755A414C61746ELLU, // zu_Latn_ZA
@@ -2194,7 +2256,7 @@
     {0x656E4154u, 0x656E80A1u}, // en-AT -> en-150
     {0x656E4155u, 0x656E8400u}, // en-AU -> en-001
     {0x656E4242u, 0x656E8400u}, // en-BB -> en-001
-    {0x656E4245u, 0x656E8400u}, // en-BE -> en-001
+    {0x656E4245u, 0x656E80A1u}, // en-BE -> en-150
     {0x656E424Du, 0x656E8400u}, // en-BM -> en-001
     {0x656E4253u, 0x656E8400u}, // en-BS -> en-001
     {0x656E4257u, 0x656E8400u}, // en-BW -> en-001
@@ -2285,6 +2347,7 @@
     {0x65734152u, 0x6573A424u}, // es-AR -> es-419
     {0x6573424Fu, 0x6573A424u}, // es-BO -> es-419
     {0x65734252u, 0x6573A424u}, // es-BR -> es-419
+    {0x6573425Au, 0x6573A424u}, // es-BZ -> es-419
     {0x6573434Cu, 0x6573A424u}, // es-CL -> es-419
     {0x6573434Fu, 0x6573A424u}, // es-CO -> es-419
     {0x65734352u, 0x6573A424u}, // es-CR -> es-419
@@ -2315,6 +2378,10 @@
     {0x7074544Cu, 0x70745054u}, // pt-TL -> pt-PT
 });
 
+const std::unordered_map<uint32_t, uint32_t> ___B_PARENTS({
+    {0x61725842u, 0x61729420u}, // ar-XB -> ar-015
+});
+
 const struct {
     const char script[4];
     const std::unordered_map<uint32_t, uint32_t>* map;
@@ -2322,6 +2389,7 @@
     {{'A', 'r', 'a', 'b'}, &ARAB_PARENTS},
     {{'H', 'a', 'n', 't'}, &HANT_PARENTS},
     {{'L', 'a', 't', 'n'}, &LATN_PARENTS},
+    {{'~', '~', '~', 'B'}, &___B_PARENTS},
 };
 
 const size_t MAX_PARENT_DEPTH = 3;
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index 87b1467..8cffd6a 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -3,3 +3,4 @@
 rtmitchell@google.com
 
 per-file CursorWindow.cpp=omakoto@google.com
+per-file LocaleDataTables.cpp=vichang@google.com,tobiast@google.com,nikitai@google.com
diff --git a/media/Android.bp b/media/Android.bp
index a768b81..d7cd054 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -66,7 +66,7 @@
     "--hide MissingPermission --hide BroadcastBehavior " +
     "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
     "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
-    "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi "
+    "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) "
 
 droidstubs {
     name: "updatable-media-stubs",
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index f0787e9..e55585a 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -281,6 +281,8 @@
      * metadata (object audio) over HDMI (e.g. Dolby Atmos content).
      **/
     public static final int ENCODING_DOLBY_MAT = 19;
+    /** Audio data format: OPUS compressed. */
+    public static final int ENCODING_OPUS = 20;
 
     /** @hide */
     public static String toLogFriendlyEncoding(int enc) {
@@ -323,6 +325,8 @@
                 return "ENCODING_E_AC3_JOC";
             case ENCODING_DOLBY_MAT:
                 return "ENCODING_DOLBY_MAT";
+            case ENCODING_OPUS:
+                return "ENCODING_OPUS";
             default :
                 return "invalid encoding " + enc;
         }
@@ -548,6 +552,7 @@
             case ENCODING_AC4:
             case ENCODING_E_AC3_JOC:
             case ENCODING_DOLBY_MAT:
+            case ENCODING_OPUS:
                 return true;
             default:
                 return false;
@@ -576,6 +581,7 @@
             case ENCODING_AC4:
             case ENCODING_E_AC3_JOC:
             case ENCODING_DOLBY_MAT:
+            case ENCODING_OPUS:
                 return true;
             default:
                 return false;
@@ -607,6 +613,7 @@
             case ENCODING_AC4:
             case ENCODING_E_AC3_JOC:
             case ENCODING_DOLBY_MAT:
+            case ENCODING_OPUS:
                 return false;
             case ENCODING_INVALID:
             default:
@@ -638,6 +645,7 @@
             case ENCODING_AC4:
             case ENCODING_E_AC3_JOC:
             case ENCODING_DOLBY_MAT:
+            case ENCODING_OPUS:
                 return false;
             case ENCODING_INVALID:
             default:
@@ -917,6 +925,7 @@
                 case ENCODING_AC4:
                 case ENCODING_E_AC3_JOC:
                 case ENCODING_DOLBY_MAT:
+                case ENCODING_OPUS:
                     mEncoding = encoding;
                     break;
                 case ENCODING_INVALID:
@@ -1136,7 +1145,8 @@
         ENCODING_AAC_XHE,
         ENCODING_AC4,
         ENCODING_E_AC3_JOC,
-        ENCODING_DOLBY_MAT }
+        ENCODING_DOLBY_MAT,
+        ENCODING_OPUS }
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface Encoding {}
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index ab80b3a..515e9d0 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -400,6 +400,7 @@
      * configurations
      * @return true if active
      */
+    @SystemApi
     public boolean isActive() {
         switch (mPlayerState) {
             case PLAYER_STATE_STARTED:
@@ -420,18 +421,7 @@
      * @param pw
      */
     public void dump(PrintWriter pw) {
-        pw.println("  " + toLogFriendlyString(this));
-    }
-
-    /**
-     * @hide
-     */
-    public static String toLogFriendlyString(AudioPlaybackConfiguration apc) {
-        return new String("ID:" + apc.mPlayerIId
-                + " -- type:" + toLogFriendlyPlayerType(apc.mPlayerType)
-                + " -- u/pid:" + apc.mClientUid +"/" + apc.mClientPid
-                + " -- state:" + toLogFriendlyPlayerState(apc.mPlayerState)
-                + " -- attr:" + apc.mPlayerAttr);
+        pw.println("  " + this);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<AudioPlaybackConfiguration> CREATOR
@@ -498,6 +488,15 @@
                 && (mClientPid == that.mClientPid));
     }
 
+    @Override
+    public String toString() {
+        return "AudioPlaybackConfiguration piid:" + mPlayerIId
+                + " type:" + toLogFriendlyPlayerType(mPlayerType)
+                + " u/pid:" + mClientUid + "/" + mClientPid
+                + " state:" + toLogFriendlyPlayerState(mPlayerState)
+                + " attr:" + mPlayerAttr;
+    }
+
     //=====================================================================
     // Inner class for corresponding IPlayer and its death monitoring
     static final class IPlayerShell implements IBinder.DeathRecipient {
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 900572d..1033e56 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -25,12 +25,15 @@
 import android.content.pm.PackageManager;
 import android.media.audiofx.AudioEffect;
 import android.media.audiopolicy.AudioMix;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 /* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET
  * TO UPDATE THE CORRESPONDING NATIVE GLUE AND AudioManager.java.
@@ -541,51 +544,75 @@
 
     public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
 
-    public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
-                                              DEVICE_OUT_SPEAKER |
-                                              DEVICE_OUT_WIRED_HEADSET |
-                                              DEVICE_OUT_WIRED_HEADPHONE |
-                                              DEVICE_OUT_BLUETOOTH_SCO |
-                                              DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                              DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
-                                              DEVICE_OUT_BLUETOOTH_A2DP |
-                                              DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                              DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
-                                              DEVICE_OUT_HDMI |
-                                              DEVICE_OUT_ANLG_DOCK_HEADSET |
-                                              DEVICE_OUT_DGTL_DOCK_HEADSET |
-                                              DEVICE_OUT_USB_ACCESSORY |
-                                              DEVICE_OUT_USB_DEVICE |
-                                              DEVICE_OUT_REMOTE_SUBMIX |
-                                              DEVICE_OUT_TELEPHONY_TX |
-                                              DEVICE_OUT_LINE |
-                                              DEVICE_OUT_HDMI_ARC |
-                                              DEVICE_OUT_SPDIF |
-                                              DEVICE_OUT_FM |
-                                              DEVICE_OUT_AUX_LINE |
-                                              DEVICE_OUT_SPEAKER_SAFE |
-                                              DEVICE_OUT_IP |
-                                              DEVICE_OUT_BUS |
-                                              DEVICE_OUT_PROXY |
-                                              DEVICE_OUT_USB_HEADSET |
-                                              DEVICE_OUT_HEARING_AID |
-                                              DEVICE_OUT_DEFAULT);
-    public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
-                                                   DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                                   DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
-    public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO |
-                                                  DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                                  DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+    // Deprecated in R because multiple device types are no longer accessed as a bit mask.
+    // Removing this will get lint warning about changing hidden apis.
     @UnsupportedAppUsage
     public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
                                                   DEVICE_OUT_USB_DEVICE |
                                                   DEVICE_OUT_USB_HEADSET);
-    public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_AUX_LINE |
-                                                                DEVICE_OUT_HDMI_ARC |
-                                                                DEVICE_OUT_SPDIF);
-    public static final int DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER =
-            (DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO |
-             DEVICE_OUT_SPEAKER);
+
+    public static final Set<Integer> DEVICE_OUT_ALL_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_A2DP_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_SCO_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_USB_SET;
+    public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET;
+    public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET;
+    static {
+        DEVICE_OUT_ALL_SET = new HashSet<>();
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_EARPIECE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPEAKER);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_WIRED_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_WIRED_HEADPHONE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HDMI);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ANLG_DOCK_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DGTL_DOCK_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_ACCESSORY);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_DEVICE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_REMOTE_SUBMIX);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_TELEPHONY_TX);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_LINE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HDMI_ARC);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPDIF);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_FM);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_AUX_LINE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_SPEAKER_SAFE);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_IP);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BUS);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_PROXY);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_HEADSET);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HEARING_AID);
+        DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
+
+        DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
+        DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP);
+        DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES);
+        DEVICE_OUT_ALL_A2DP_SET.add(DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+
+        DEVICE_OUT_ALL_SCO_SET = new HashSet<>();
+        DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO);
+        DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
+        DEVICE_OUT_ALL_SCO_SET.add(DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+
+        DEVICE_OUT_ALL_USB_SET = new HashSet<>();
+        DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_ACCESSORY);
+        DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_DEVICE);
+        DEVICE_OUT_ALL_USB_SET.add(DEVICE_OUT_USB_HEADSET);
+
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET = new HashSet<>();
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_AUX_LINE);
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_HDMI_ARC);
+        DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET.add(DEVICE_OUT_SPDIF);
+
+        DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET = new HashSet<>();
+        DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.addAll(DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET);
+        DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.add(DEVICE_OUT_SPEAKER);
+    }
 
     // input devices
     @UnsupportedAppUsage
@@ -633,37 +660,47 @@
     @UnsupportedAppUsage
     public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
 
-    public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
-                                             DEVICE_IN_AMBIENT |
-                                             DEVICE_IN_BUILTIN_MIC |
-                                             DEVICE_IN_BLUETOOTH_SCO_HEADSET |
-                                             DEVICE_IN_WIRED_HEADSET |
-                                             DEVICE_IN_HDMI |
-                                             DEVICE_IN_TELEPHONY_RX |
-                                             DEVICE_IN_BACK_MIC |
-                                             DEVICE_IN_REMOTE_SUBMIX |
-                                             DEVICE_IN_ANLG_DOCK_HEADSET |
-                                             DEVICE_IN_DGTL_DOCK_HEADSET |
-                                             DEVICE_IN_USB_ACCESSORY |
-                                             DEVICE_IN_USB_DEVICE |
-                                             DEVICE_IN_FM_TUNER |
-                                             DEVICE_IN_TV_TUNER |
-                                             DEVICE_IN_LINE |
-                                             DEVICE_IN_SPDIF |
-                                             DEVICE_IN_BLUETOOTH_A2DP |
-                                             DEVICE_IN_LOOPBACK |
-                                             DEVICE_IN_IP |
-                                             DEVICE_IN_BUS |
-                                             DEVICE_IN_PROXY |
-                                             DEVICE_IN_USB_HEADSET |
-                                             DEVICE_IN_BLUETOOTH_BLE |
-                                             DEVICE_IN_HDMI_ARC |
-                                             DEVICE_IN_ECHO_REFERENCE |
-                                             DEVICE_IN_DEFAULT);
-    public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-    public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
-                                                 DEVICE_IN_USB_DEVICE |
-                                                 DEVICE_IN_USB_HEADSET);
+    public static final Set<Integer> DEVICE_IN_ALL_SET;
+    public static final Set<Integer> DEVICE_IN_ALL_SCO_SET;
+    public static final Set<Integer> DEVICE_IN_ALL_USB_SET;
+    static {
+        DEVICE_IN_ALL_SET = new HashSet<>();
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_AMBIENT);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BUILTIN_MIC);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_WIRED_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_TELEPHONY_RX);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BACK_MIC);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_REMOTE_SUBMIX);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_ANLG_DOCK_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_DGTL_DOCK_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_ACCESSORY);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_DEVICE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_FM_TUNER);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_TV_TUNER);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_LINE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_SPDIF);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_A2DP);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_LOOPBACK);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_IP);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BUS);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_PROXY);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_USB_HEADSET);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_BLE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI_ARC);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_ECHO_REFERENCE);
+        DEVICE_IN_ALL_SET.add(DEVICE_IN_DEFAULT);
+
+        DEVICE_IN_ALL_SCO_SET = new HashSet<>();
+        DEVICE_IN_ALL_SCO_SET.add(DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+
+        DEVICE_IN_ALL_USB_SET = new HashSet<>();
+        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY);
+        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE);
+        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);
+    }
 
     // device states, must match AudioSystem::device_connection_state
     @UnsupportedAppUsage
@@ -1203,7 +1240,8 @@
      * </ul>
      */
     public static int getPlatformType(Context context) {
-        if (context.getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
+        if (((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
+                .isVoiceCapable()) {
             return PLATFORM_VOICE;
         } else if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
             return PLATFORM_TELEVISION;
@@ -1222,6 +1260,40 @@
         return getPlatformType(context) == PLATFORM_TELEVISION || forceSingleVolume;
     }
 
+    /**
+     * Return a set of audio device types from a bit mask audio device type, which may
+     * represent multiple audio device types.
+     * FIXME: Remove this when getting ride of bit mask usage of audio device types.
+     */
+    public static Set<Integer> generateAudioDeviceTypesSet(int types) {
+        Set<Integer> deviceTypes = new HashSet<>();
+        Set<Integer> allDeviceTypes =
+                (types & DEVICE_BIT_IN) == 0 ? DEVICE_OUT_ALL_SET : DEVICE_IN_ALL_SET;
+        for (int deviceType : allDeviceTypes) {
+            if ((types & deviceType) == deviceType) {
+                deviceTypes.add(deviceType);
+            }
+        }
+        return deviceTypes;
+    }
+
+    /**
+     * Return the intersection of two audio device types collections.
+     */
+    public static Set<Integer> intersectionAudioDeviceTypes(
+            @NonNull Set<Integer> a, @NonNull Set<Integer> b) {
+        Set<Integer> intersection = new HashSet<>(a);
+        intersection.retainAll(b);
+        return intersection;
+    }
+
+    /**
+     * Return true if the audio device types collection only contains the given device type.
+     */
+    public static boolean isSingleAudioDeviceType(@NonNull Set<Integer> types, int type) {
+        return types.size() == 1 && types.contains(type);
+    }
+
     public static final int DEFAULT_MUTE_STREAMS_AFFECTED =
             (1 << STREAM_MUSIC) |
             (1 << STREAM_RING) |
diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java
index 471fa2c..aafbd44 100644
--- a/media/java/android/media/MediaScannerConnection.java
+++ b/media/java/android/media/MediaScannerConnection.java
@@ -220,7 +220,7 @@
 
     /**
      * Convenience for constructing a {@link MediaScannerConnection}, calling
-     * {@link #connect} on it, and calling {@link #scanFile} with the given
+     * {@link #connect} on it, and calling {@link #scanFile(String, String)} with the given
      * <var>path</var> and <var>mimeType</var> when the connection is
      * established.
      * @param context The caller's Context, required for establishing a connection to
diff --git a/media/java/android/media/session/ICallback.aidl b/media/java/android/media/session/ICallback.aidl
deleted file mode 100644
index 322bffa..0000000
--- a/media/java/android/media/session/ICallback.aidl
+++ /dev/null
@@ -1,35 +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.media.session;
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.media.session.MediaSession;
-import android.view.KeyEvent;
-
-/**
- * @hide
- */
-oneway interface ICallback {
-    void onMediaKeyEventDispatchedToMediaSession(in KeyEvent event,
-            in MediaSession.Token sessionToken);
-    void onMediaKeyEventDispatchedToMediaButtonReceiver(in KeyEvent event,
-            in ComponentName mediaButtonReceiver);
-
-    void onAddressedPlayerChangedToMediaSession(in MediaSession.Token sessionToken);
-    void onAddressedPlayerChangedToMediaButtonReceiver(in ComponentName mediaButtonReceiver);
-}
-
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/media/java/android/media/session/IOnMediaKeyEventDispatchedListener.aidl
similarity index 63%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to media/java/android/media/session/IOnMediaKeyEventDispatchedListener.aidl
index d502088..90d9134 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/media/java/android/media/session/IOnMediaKeyEventDispatchedListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package android.net;
+package android.media.session;
 
-import android.net.Network;
+import android.media.session.MediaSession;
+import android.view.KeyEvent;
 
 /**
- * Callback class for receiving tethering changed events
  * @hide
  */
-oneway interface ITetheringEventCallback
-{
-    void onUpstreamChanged(in Network network);
+oneway interface IOnMediaKeyEventDispatchedListener {
+    void onMediaKeyEventDispatched(in KeyEvent event, in String packageName,
+            in MediaSession.Token sessionToken);
 }
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/media/java/android/media/session/IOnMediaKeyEventSessionChangedListener.aidl
similarity index 65%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to media/java/android/media/session/IOnMediaKeyEventSessionChangedListener.aidl
index d502088..9566e75 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/media/java/android/media/session/IOnMediaKeyEventSessionChangedListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package android.net;
+package android.media.session;
 
-import android.net.Network;
+import android.media.session.MediaSession;
 
 /**
- * Callback class for receiving tethering changed events
  * @hide
  */
-oneway interface ITetheringEventCallback
-{
-    void onUpstreamChanged(in Network network);
+oneway interface IOnMediaKeyEventSessionChangedListener {
+    void onMediaKeyEventSessionChanged(in String packageName,
+            in MediaSession.Token mediaKeyEventSessionToken);
 }
+
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index a67a37e..c8502a5 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -20,7 +20,8 @@
 import android.media.IRemoteVolumeController;
 import android.media.Session2Token;
 import android.media.session.IActiveSessionsListener;
-import android.media.session.ICallback;
+import android.media.session.IOnMediaKeyEventDispatchedListener;
+import android.media.session.IOnMediaKeyEventSessionChangedListener;
 import android.media.session.IOnMediaKeyListener;
 import android.media.session.IOnVolumeKeyLongPressListener;
 import android.media.session.ISession;
@@ -62,7 +63,12 @@
     // For PhoneWindowManager to precheck media keys
     boolean isGlobalPriorityActive();
 
-    void setCallback(in ICallback callback);
+    void addOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
+    void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
+    void addOnMediaKeyEventSessionChangedListener(
+            in IOnMediaKeyEventSessionChangedListener listener);
+    void removeOnMediaKeyEventSessionChangedListener(
+            in IOnMediaKeyEventSessionChangedListener listener);
     void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
     void setOnMediaKeyListener(in IOnMediaKeyListener listener);
 
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 9685c4b..a89dc5f 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -16,6 +16,7 @@
 
 package android.media.session;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -46,8 +47,11 @@
 import com.android.internal.annotations.GuardedBy;
 
 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;
 
 /**
  * Provides support for interacting with {@link MediaSession media sessions}
@@ -72,19 +76,32 @@
      * @hide
      */
     public static final int RESULT_MEDIA_KEY_HANDLED = 1;
+    private final ISessionManager mService;
+    private final OnMediaKeyEventDispatchedListenerStub mOnMediaKeyEventDispatchedListenerStub =
+            new OnMediaKeyEventDispatchedListenerStub();
+    private final OnMediaKeyEventSessionChangedListenerStub
+            mOnMediaKeyEventSessionChangedListenerStub =
+            new OnMediaKeyEventSessionChangedListenerStub();
 
     private final Object mLock = new Object();
     @GuardedBy("mLock")
-    private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners
-            = new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
+    private final ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper> mListeners =
+            new ArrayMap<OnActiveSessionsChangedListener, SessionsChangedWrapper>();
     @GuardedBy("mLock")
     private final ArrayMap<OnSession2TokensChangedListener, Session2TokensChangedWrapper>
             mSession2TokensListeners = new ArrayMap<>();
-    private final ISessionManager mService;
+    @GuardedBy("mLock")
+    private final Map<OnMediaKeyEventDispatchedListener, Executor>
+            mOnMediaKeyEventDispatchedListeners = new HashMap<>();
+    @GuardedBy("mLock")
+    private final Map<OnMediaKeyEventSessionChangedListener, Executor>
+            mMediaKeyEventSessionChangedCallbacks = new HashMap<>();
+    @GuardedBy("mLock")
+    private String mCurMediaKeyEventSessionPackage;
+    @GuardedBy("mLock")
+    private MediaSession.Token mCurMediaKeyEventSession;
 
     private Context mContext;
-
-    private CallbackImpl mCallback;
     private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
     private OnMediaKeyListenerImpl mOnMediaKeyListener;
 
@@ -742,31 +759,118 @@
     }
 
     /**
-     * Set a {@link Callback}.
+     * Add a {@link OnMediaKeyEventDispatchedListener}.
      *
-     * <p>System can only have a single callback, and the callback can only be set by
-     * Bluetooth service process.
-     *
-     * @param callback A {@link Callback}. {@code null} to reset.
-     * @param handler The handler on which the callback should be invoked, or {@code null}
-     *            if the callback should be invoked on the calling thread's looper.
+     * @param executor The executor on which the callback should be invoked
+     * @param listener A {@link OnMediaKeyEventDispatchedListener}.
      * @hide
      */
-    public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
+    @SystemApi
+    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+    public void addOnMediaKeyEventDispatchedListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnMediaKeyEventDispatchedListener listener) {
+        if (executor == null) {
+            throw new NullPointerException("executor shouldn't be null");
+        }
+        if (listener == null) {
+            throw new NullPointerException("listener shouldn't be null");
+        }
         synchronized (mLock) {
             try {
-                if (callback == null) {
-                    mCallback = null;
-                    mService.setCallback(null);
-                } else {
-                    if (handler == null) {
-                        handler = new Handler();
-                    }
-                    mCallback = new CallbackImpl(callback, handler);
-                    mService.setCallback(mCallback);
+                mOnMediaKeyEventDispatchedListeners.put(listener, executor);
+                if (mOnMediaKeyEventDispatchedListeners.size() == 1) {
+                    mService.addOnMediaKeyEventDispatchedListener(
+                            mOnMediaKeyEventDispatchedListenerStub);
                 }
             } catch (RemoteException e) {
-                Log.e(TAG, "Failed to set media key callback", e);
+                Log.e(TAG, "Failed to set media key listener", e);
+            }
+        }
+    }
+
+    /**
+     * Remove a {@link OnMediaKeyEventDispatchedListener}.
+     *
+     * @param listener A {@link OnMediaKeyEventDispatchedListener}.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+    public void removeOnMediaKeyEventDispatchedListener(
+            @NonNull OnMediaKeyEventDispatchedListener listener) {
+        if (listener == null) {
+            throw new NullPointerException("listener shouldn't be null");
+        }
+        synchronized (mLock) {
+            try {
+                mOnMediaKeyEventDispatchedListeners.remove(listener);
+                if (mOnMediaKeyEventDispatchedListeners.size() == 0) {
+                    mService.removeOnMediaKeyEventDispatchedListener(
+                            mOnMediaKeyEventDispatchedListenerStub);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to set media key event dispatched listener", e);
+            }
+        }
+    }
+
+    /**
+     * Add a {@link OnMediaKeyEventDispatchedListener}.
+     *
+     * @param executor The executor on which the callback should be invoked
+     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+    public void addOnMediaKeyEventSessionChangedListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnMediaKeyEventSessionChangedListener listener) {
+        if (executor == null) {
+            throw new NullPointerException("executor shouldn't be null");
+        }
+        if (listener == null) {
+            throw new NullPointerException("listener shouldn't be null");
+        }
+        synchronized (mLock) {
+            try {
+                mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
+                executor.execute(
+                        () -> listener.onMediaKeyEventSessionChanged(
+                                mCurMediaKeyEventSessionPackage, mCurMediaKeyEventSession));
+                if (mMediaKeyEventSessionChangedCallbacks.size() == 1) {
+                    mService.addOnMediaKeyEventSessionChangedListener(
+                            mOnMediaKeyEventSessionChangedListenerStub);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to set media key listener", e);
+            }
+        }
+    }
+
+    /**
+     * Remove a {@link OnMediaKeyEventSessionChangedListener}.
+     *
+     * @param listener A {@link OnMediaKeyEventSessionChangedListener}.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+    public void removeOnMediaKeyEventSessionChangedListener(
+            @NonNull OnMediaKeyEventSessionChangedListener listener) {
+        if (listener == null) {
+            throw new NullPointerException("listener shouldn't be null");
+        }
+        synchronized (mLock) {
+            try {
+                mMediaKeyEventSessionChangedCallbacks.remove(listener);
+                if (mMediaKeyEventSessionChangedCallbacks.size() == 0) {
+                    mService.removeOnMediaKeyEventSessionChangedListener(
+                            mOnMediaKeyEventSessionChangedListenerStub);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to set media key listener", e);
             }
         }
     }
@@ -828,53 +932,46 @@
     }
 
     /**
-     * Callbacks for the media session service.
-     *
-     * <p>Called when a media key event is dispatched or the addressed player is changed.
-     * The addressed player is either the media session or the media button receiver that will
-     * receive media key events.
+     * Listener to receive when the media session service
      * @hide
      */
-    public static abstract class Callback {
+    @SystemApi
+    public interface OnMediaKeyEventDispatchedListener {
         /**
-         * Called when a media key event is dispatched to the media session
-         * through the media session service.
+         * Called when a media key event is dispatched through the media session service. The
+         * session token can be {@link null} if the framework has sent the media key event to the
+         * media button receiver to revive the media app's playback.
+         *
+         * the session is dead when , but the framework sent
          *
          * @param event Dispatched media key event.
-         * @param sessionToken The media session's token.
+         * @param packageName Package
+         * @param sessionToken The media session's token. Can be {@code null}.
          */
-        public abstract void onMediaKeyEventDispatched(KeyEvent event,
-                MediaSession.Token sessionToken);
+        default void onMediaKeyEventDispatched(@NonNull KeyEvent event, @NonNull String packageName,
+                @NonNull MediaSession.Token sessionToken) { }
+    }
 
+    /**
+     * Listener to receive changes in the media key event session, which would receive the media key
+     * event unless specified.
+     * @hide
+     */
+    @SystemApi
+    public interface OnMediaKeyEventSessionChangedListener {
         /**
-         * Called when a media key event is dispatched to the media button receiver
-         * through the media session service.
-         * <p>MediaSessionService may broadcast key events to the media button receiver
-         * when reviving playback after the media session is released.
+         * Called when the media key session is changed to the given media session. The key event
+         * session is the media session which would receive key event by default, unless the caller
+         * has specified the target.
+         * <p>
+         * The session token can be {@link null} if the media button session is unset. In that case,
+         * framework would dispatch to the last sessions's media button receiver.
          *
-         * @param event Dispatched media key event.
-         * @param mediaButtonReceiver The media button receiver.
+         * @param packageName The package name who would receive the media key event. Can be empty.
+         * @param sessionToken The media session's token. Can be {@code null.}
          */
-        public abstract void onMediaKeyEventDispatched(KeyEvent event,
-                ComponentName mediaButtonReceiver);
-
-        /**
-         * Called when the addressed player is changed to a media session.
-         * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
-         * {@link #setCallback} if the addressed player exists.
-         *
-         * @param sessionToken The media session's token.
-         */
-        public abstract void onAddressedPlayerChanged(MediaSession.Token sessionToken);
-
-        /**
-         * Called when the addressed player is changed to the media button receiver.
-         * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
-         * {@link #setCallback} if the addressed player exists.
-         *
-         * @param mediaButtonReceiver The media button receiver.
-         */
-        public abstract void onAddressedPlayerChanged(ComponentName mediaButtonReceiver);
+        default void onMediaKeyEventSessionChanged(@NonNull String packageName,
+                @Nullable MediaSession.Token sessionToken) { }
     }
 
     /**
@@ -1076,56 +1173,37 @@
         }
     }
 
-    private static final class CallbackImpl extends ICallback.Stub {
-        private final Callback mCallback;
-        private final Handler mHandler;
-
-        public CallbackImpl(@NonNull Callback callback, @NonNull Handler handler) {
-            mCallback = callback;
-            mHandler = handler;
-        }
+    private final class OnMediaKeyEventDispatchedListenerStub
+            extends IOnMediaKeyEventDispatchedListener.Stub {
 
         @Override
-        public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
+        public void onMediaKeyEventDispatched(KeyEvent event, String packageName,
                 MediaSession.Token sessionToken) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onMediaKeyEventDispatched(event, sessionToken);
+            synchronized (mLock) {
+                for (Map.Entry<OnMediaKeyEventDispatchedListener, Executor> e
+                        : mOnMediaKeyEventDispatchedListeners.entrySet()) {
+                    e.getValue().execute(
+                            () -> e.getKey().onMediaKeyEventDispatched(event, packageName,
+                                    sessionToken));
                 }
-            });
+            }
         }
+    }
 
+    private final class OnMediaKeyEventSessionChangedListenerStub
+            extends IOnMediaKeyEventSessionChangedListener.Stub {
         @Override
-        public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
-                ComponentName mediaButtonReceiver) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onMediaKeyEventDispatched(event, mediaButtonReceiver);
+        public void onMediaKeyEventSessionChanged(String packageName,
+                MediaSession.Token sessionToken) {
+            synchronized (mLock) {
+                mCurMediaKeyEventSessionPackage = packageName;
+                mCurMediaKeyEventSession = sessionToken;
+                for (Map.Entry<OnMediaKeyEventSessionChangedListener, Executor> e
+                        : mMediaKeyEventSessionChangedCallbacks.entrySet()) {
+                    e.getValue().execute(() -> e.getKey().onMediaKeyEventSessionChanged(packageName,
+                            sessionToken));
                 }
-            });
-        }
-
-        @Override
-        public void onAddressedPlayerChangedToMediaSession(MediaSession.Token sessionToken) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onAddressedPlayerChanged(sessionToken);
-                }
-            });
-        }
-
-        @Override
-        public void onAddressedPlayerChangedToMediaButtonReceiver(
-                ComponentName mediaButtonReceiver) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onAddressedPlayerChanged(mediaButtonReceiver);
-                }
-            });
+            }
         }
     }
 }
diff --git a/media/java/android/media/tv/DvbDeviceInfo.java b/media/java/android/media/tv/DvbDeviceInfo.java
index a574fe1..96c8528 100644
--- a/media/java/android/media/tv/DvbDeviceInfo.java
+++ b/media/java/android/media/tv/DvbDeviceInfo.java
@@ -16,6 +16,8 @@
 
 package android.media.tv;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -26,10 +28,11 @@
  *
  * @hide
  */
+@SystemApi
 public final class DvbDeviceInfo implements Parcelable {
     static final String TAG = "DvbDeviceInfo";
 
-    public static final @android.annotation.NonNull Parcelable.Creator<DvbDeviceInfo> CREATOR =
+    public static final @NonNull Parcelable.Creator<DvbDeviceInfo> CREATOR =
             new Parcelable.Creator<DvbDeviceInfo>() {
                 @Override
                 public DvbDeviceInfo createFromParcel(Parcel source) {
@@ -86,7 +89,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mAdapterId);
         dest.writeInt(mDeviceId);
     }
diff --git a/media/java/android/media/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
old mode 100644
new mode 100755
index bd05184..f90c504
--- a/media/java/android/media/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -38,4 +38,5 @@
     void notifyHardwareRemoved(in TvInputHardwareInfo hardwareInfo);
     void notifyHdmiDeviceAdded(in HdmiDeviceInfo deviceInfo);
     void notifyHdmiDeviceRemoved(in HdmiDeviceInfo deviceInfo);
+    void notifyHdmiDeviceUpdated(in HdmiDeviceInfo deviceInfo);
 }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d22a298..854ea43 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -103,6 +103,12 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
+    @IntDef({DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_FRONTEND})
+    public @interface DvbDeviceType {}
+
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
     @IntDef({VIDEO_UNAVAILABLE_REASON_UNKNOWN, VIDEO_UNAVAILABLE_REASON_TUNING,
             VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING,
             VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY})
@@ -1663,6 +1669,9 @@
      * @return the list of {@link DvbDeviceInfo} objects representing available DVB devices.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.DVB_DEVICE)
+    @NonNull
     public List<DvbDeviceInfo> getDvbDeviceList() {
         try {
             return mService.getDvbDeviceList();
@@ -1676,19 +1685,24 @@
      * {@link DvbDeviceInfo}
      *
      * @param info A {@link DvbDeviceInfo} to open a DVB device.
-     * @param device A DVB device. The DVB device can be {@link #DVB_DEVICE_DEMUX},
+     * @param deviceType A DVB device type. The type can be {@link #DVB_DEVICE_DEMUX},
      *            {@link #DVB_DEVICE_DVR} or {@link #DVB_DEVICE_FRONTEND}.
      * @return a {@link ParcelFileDescriptor} of a specified DVB device for a given
-     *         {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo} was invalid
-     *         or the specified DVB device was busy with a previous request.
+     *         {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo}
+     *         failed to open.
+     * @throws IllegalArgumentException if {@code deviceType} is invalid or the device is not found.
      * @hide
      */
-    public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device) {
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.DVB_DEVICE)
+    @Nullable
+    public ParcelFileDescriptor openDvbDevice(@NonNull DvbDeviceInfo info,
+            @DvbDeviceType int deviceType) {
         try {
-            if (DVB_DEVICE_START > device || DVB_DEVICE_END < device) {
-                throw new IllegalArgumentException("Invalid DVB device: " + device);
+            if (DVB_DEVICE_START > deviceType || DVB_DEVICE_END < deviceType) {
+                throw new IllegalArgumentException("Invalid DVB device: " + deviceType);
             }
-            return mService.openDvbDevice(info, device);
+            return mService.openDvbDevice(info, deviceType);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
old mode 100644
new mode 100755
index ff69779..5c11ed9b
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -173,6 +173,12 @@
                 mServiceHandler.obtainMessage(ServiceHandler.DO_REMOVE_HDMI_INPUT,
                         deviceInfo).sendToTarget();
             }
+
+            @Override
+            public void notifyHdmiDeviceUpdated(HdmiDeviceInfo deviceInfo) {
+                mServiceHandler.obtainMessage(ServiceHandler.DO_UPDATE_HDMI_INPUT,
+                        deviceInfo).sendToTarget();
+            }
         };
     }
 
@@ -257,6 +263,24 @@
         return null;
     }
 
+    /**
+     * Called when {@code deviceInfo} is updated.
+     *
+     * <p>The changes are usually cuased by the corresponding HDMI-CEC logical device.
+     *
+     * <p>The default behavior ignores all changes.
+     *
+     * <p>The TV input service responsible for {@code deviceInfo} can update the {@link TvInputInfo}
+     * object based on the updated {@code deviceInfo} (e.g. update the label based on the preferred
+     * device OSD name).
+     *
+     * @param deviceInfo the updated {@link HdmiDeviceInfo} object.
+     * @hide
+     */
+    @SystemApi
+    public void onHdmiDeviceUpdated(@NonNull HdmiDeviceInfo deviceInfo) {
+    }
+
     private boolean isPassthroughInput(String inputId) {
         if (mTvInputManager == null) {
             mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
@@ -1962,6 +1986,7 @@
         private static final int DO_REMOVE_HARDWARE_INPUT = 5;
         private static final int DO_ADD_HDMI_INPUT = 6;
         private static final int DO_REMOVE_HDMI_INPUT = 7;
+        private static final int DO_UPDATE_HDMI_INPUT = 8;
 
         private void broadcastAddHardwareInput(int deviceId, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
@@ -2131,6 +2156,11 @@
                     }
                     return;
                 }
+                case DO_UPDATE_HDMI_INPUT: {
+                    HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
+                    onHdmiDeviceUpdated(deviceInfo);
+                    return;
+                }
                 default: {
                     Log.w(TAG, "Unhandled message code: " + msg.what);
                     return;
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 8d420e2..05aaa82 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -743,8 +743,10 @@
 }
 
 status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
-
-    status_t status = mCodec->getMetrics(reply);
+    mediametrics_handle_t reply2 = MediaAnalyticsItem::convert(reply);
+    status_t status = mCodec->getMetrics(reply2);
+    // getMetrics() updates reply2, pass the converted update along to our caller.
+    reply = MediaAnalyticsItem::convert(reply2);
     return status;
 }
 
@@ -1848,7 +1850,7 @@
     }
 
     // get what we have for the metrics from the codec
-    MediaAnalyticsItem *item = NULL;
+    MediaAnalyticsItem *item = 0;
 
     status_t err = codec->getMetrics(env, item);
     if (err != OK) {
@@ -1860,7 +1862,7 @@
 
     // housekeeping
     delete item;
-    item = NULL;
+    item = 0;
 
     return mybundle;
 }
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index baa779c..f5ba92e 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -19,7 +19,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AudioPresentationInfo.h>
-#include <media/MediaSource.h>
+#include <media/stagefright/MediaSource.h>
 #include <media/DataSource.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java
index 4bcf046..6554267 100644
--- a/mms/java/android/telephony/MmsManager.java
+++ b/mms/java/android/telephony/MmsManager.java
@@ -97,22 +97,4 @@
             // Ignore it
         }
     }
-
-    /**
-     * Get carrier-dependent configuration values.
-     *
-     * @param subId the subscription id
-     * @return bundle key/values pairs of configuration values
-     */
-    public Bundle getCarrierConfigValues(int subId) {
-        try {
-            IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
-            if (iMms != null) {
-                return iMms.getCarrierConfigValues(subId);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-        return null;
-    }
 }
diff --git a/mms/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl
index fa5073e..8be5111 100644
--- a/mms/java/com/android/internal/telephony/IMms.aidl
+++ b/mms/java/com/android/internal/telephony/IMms.aidl
@@ -60,13 +60,6 @@
             in PendingIntent downloadedIntent);
 
     /**
-     * Get carrier-dependent configuration values.
-     *
-     * @param subId the SIM id
-     */
-    Bundle getCarrierConfigValues(int subId);
-
-    /**
      * Import a text message into system's SMS store
      *
      * @param callingPkg the calling app's package name
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 177f2b8..203adfc 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -40,6 +40,7 @@
     AConfiguration_getOrientation;
     AConfiguration_getScreenHeightDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
     AConfiguration_getScreenLong;
+    AConfiguration_getScreenRound; # introduced=30
     AConfiguration_getScreenSize;
     AConfiguration_getScreenWidthDp; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
     AConfiguration_getSdkVersion;
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 3258d57..2697a10 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -29,6 +29,7 @@
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
+
 import com.android.internal.telephony.PhoneConstants;
 
 /**
@@ -138,7 +139,7 @@
                 SubscriptionManager.getDefaultVoiceSubscriptionId());
         logd("onRegisterDefaultNetworkAvail subId: " + subId);
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
-        telephonyMgr.carrierActionReportDefaultNetworkStatus(subId, true);
+        telephonyMgr.createForSubscriptionId(subId).reportDefaultNetworkStatus(true);
     }
 
     private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) {
@@ -146,7 +147,7 @@
                 SubscriptionManager.getDefaultVoiceSubscriptionId());
         logd("onDeregisterDefaultNetworkAvail subId: " + subId);
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
-        telephonyMgr.carrierActionReportDefaultNetworkStatus(subId, false);
+        telephonyMgr.createForSubscriptionId(subId).reportDefaultNetworkStatus(false);
     }
 
     private static void onDisableRadio(Intent intent, Context context) {
@@ -154,7 +155,7 @@
                 SubscriptionManager.getDefaultVoiceSubscriptionId());
         logd("onDisableRadio subId: " + subId);
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
-        telephonyMgr.carrierActionSetRadioEnabled(subId, !ENABLE);
+        telephonyMgr.createForSubscriptionId(subId).setRadioEnabled(!ENABLE);
     }
 
     private static void onEnableRadio(Intent intent, Context context) {
@@ -162,7 +163,7 @@
                 SubscriptionManager.getDefaultVoiceSubscriptionId());
         logd("onEnableRadio subId: " + subId);
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
-        telephonyMgr.carrierActionSetRadioEnabled(subId, ENABLE);
+        telephonyMgr.createForSubscriptionId(subId).setRadioEnabled(ENABLE);
     }
 
     private static void onShowCaptivePortalNotification(Intent intent, Context context) {
@@ -205,7 +206,7 @@
                 SubscriptionManager.getDefaultVoiceSubscriptionId());
         logd("onResetAllCarrierActions subId: " + subId);
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
-        telephonyMgr.carrierActionResetAll(subId);
+        telephonyMgr.createForSubscriptionId(subId).resetAllCarrierActions();
     }
 
     private static Notification getNotification(Context context, int titleId, int textId,
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
index 8a2948b..3b3933b 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.dynsystem;
 
-import static android.os.image.DynamicSystemClient.KEY_SYSTEM_SIZE;
-import static android.os.image.DynamicSystemClient.KEY_USERDATA_SIZE;
-
 import android.app.Activity;
 import android.app.KeyguardManager;
 import android.content.Context;
@@ -88,12 +85,8 @@
     private void startInstallationService() {
         // retrieve data from calling intent
         Intent callingIntent = getIntent();
-
         Uri url = callingIntent.getData();
-        long systemSize = callingIntent.getLongExtra(KEY_SYSTEM_SIZE, 0);
-        long userdataSize = callingIntent.getLongExtra(KEY_USERDATA_SIZE, 0);
-        boolean enableWhenCompleted = callingIntent.getBooleanExtra(
-                DynamicSystemInstallationService.KEY_ENABLE_WHEN_COMPLETED, false);
+        Bundle extras = callingIntent.getExtras();
 
         sVerifiedUrl = url.toString();
 
@@ -101,10 +94,7 @@
         Intent intent = new Intent(this, DynamicSystemInstallationService.class);
         intent.setData(url);
         intent.setAction(DynamicSystemClient.ACTION_START_INSTALL);
-        intent.putExtra(KEY_SYSTEM_SIZE, systemSize);
-        intent.putExtra(KEY_USERDATA_SIZE, userdataSize);
-        intent.putExtra(
-                DynamicSystemInstallationService.KEY_ENABLE_WHEN_COMPLETED, enableWhenCompleted);
+        intent.putExtras(extras);
 
         Log.d(TAG, "Starting Installation Service");
         startServiceAsUser(intent, UserHandle.SYSTEM);
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index d32e85f..ee44d0a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,7 +1,5 @@
 package com.android.settingslib;
 
-import static android.telephony.ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
-
 import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.Intent;
@@ -25,6 +23,8 @@
 import android.os.UserManager;
 import android.print.PrintManager;
 import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -420,15 +420,30 @@
         // service" or "emergency calls only" text that indicates that voice
         // is not available. Note that we ignore the IWLAN service state
         // because that state indicates the use of VoWIFI and not cell service
-        int state = serviceState.getState();
-        int dataState = serviceState.getDataRegState();
+        final int state = serviceState.getState();
+        final int dataState = serviceState.getDataRegState();
+
         if (state == ServiceState.STATE_OUT_OF_SERVICE
                 || state == ServiceState.STATE_EMERGENCY_ONLY) {
-            if (dataState == ServiceState.STATE_IN_SERVICE
-                    && serviceState.getDataNetworkType() != RIL_RADIO_TECHNOLOGY_IWLAN) {
+            if (dataState == ServiceState.STATE_IN_SERVICE && isNotInIwlan(serviceState)) {
                 return ServiceState.STATE_IN_SERVICE;
             }
         }
         return state;
     }
+
+    private static boolean isNotInIwlan(ServiceState serviceState) {
+        final NetworkRegistrationInfo networkRegWlan = serviceState.getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+        if (networkRegWlan == null) {
+            return true;
+        }
+
+        final boolean isInIwlan = (networkRegWlan.getRegistrationState()
+                == NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+                || (networkRegWlan.getRegistrationState()
+                == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+        return !isInIwlan;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 96aee51..a2bd210 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -155,8 +155,8 @@
     public boolean disconnect(BluetoothDevice device) {
         if (mService == null) return false;
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -179,23 +179,29 @@
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return false;
+        }
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
-        return mService.getPriority(device);
+        if (mService == null) {
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        }
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
     boolean isA2dpPlaying() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 55765dd..bc03c34 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -124,8 +124,8 @@
             return false;
         }
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -141,14 +141,14 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -156,21 +156,21 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
-    boolean isA2dpPlaying() {
+    boolean isAudioPlaying() {
         if (mService == null) {
             return false;
         }
         List<BluetoothDevice> srcs = mService.getConnectedDevices();
         if (!srcs.isEmpty()) {
-            if (mService.isA2dpPlaying(srcs.get(0))) {
+            if (mService.isAudioPlaying(srcs.get(0))) {
                 return true;
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 0d972c5..2f34b2b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -116,7 +116,7 @@
         }
         return new Pair<>(
                 getBluetoothDrawable(context,
-                        com.android.internal.R.drawable.ic_settings_bluetooth),
+                        com.android.internal.R.drawable.ic_settings_bluetooth).mutate(),
                 context.getString(R.string.bluetooth_talkback_bluetooth));
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 56be3bb..abfee1d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -164,9 +164,7 @@
 
     public void disconnect() {
         synchronized (mProfileLock) {
-            for (LocalBluetoothProfile profile : mProfiles) {
-                disconnect(profile);
-            }
+            mLocalAdapter.disconnectAllEnabledProfiles(mDevice);
         }
         // Disconnect  PBAP server in case its connected
         // This is to ensure all the profiles are disconnected as some CK/Hs do not
@@ -645,12 +643,8 @@
 
         refresh();
 
-        if (bondState == BluetoothDevice.BOND_BONDED) {
-            if (mDevice.isBluetoothDock()) {
-                onBondingDockConnect();
-            } else if (mDevice.isBondingInitiatedLocally()) {
-                connect(false);
-            }
+        if (bondState == BluetoothDevice.BOND_BONDED && mDevice.isBondingInitiatedLocally()) {
+            connect(false);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 9f7b718..560cb3b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -120,8 +120,8 @@
             return false;
         }
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -165,14 +165,14 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -180,11 +180,11 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index ebaeb74..b4b55f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -153,8 +153,8 @@
     public boolean disconnect(BluetoothDevice device) {
         if (mService == null) return false;
         // Downgrade priority as user is disconnecting the hearing aid.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -177,33 +177,32 @@
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return false;
+        }
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
-        return mService.getPriority(device);
+        if (mService == null) {
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        }
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
-    public int getVolume() {
-        if (mService == null) {
-            return 0;
-        }
-        return mService.getVolume();
-    }
-
     public void setVolume(int volume) {
         if (mService == null) {
             return;
@@ -218,20 +217,6 @@
         return mService.getHiSyncId(device);
     }
 
-    public int getDeviceSide(BluetoothDevice device) {
-        if (mService == null) {
-            return BluetoothHearingAid.SIDE_LEFT;
-        }
-        return mService.getDeviceSide(device);
-    }
-
-    public int getDeviceMode(BluetoothDevice device) {
-        if (mService == null) {
-            return BluetoothHearingAid.MODE_MONAURAL;
-        }
-        return mService.getDeviceMode(device);
-    }
-
     public String toString() {
         return NAME;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index 860b77d..a372e23 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -135,8 +135,8 @@
             return false;
         }
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -154,15 +154,15 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     @Override
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     @Override
@@ -171,11 +171,11 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 6d874ab..975a1e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -116,23 +116,27 @@
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
-        return mService.getPriority(device) != BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return false;
+        }
+        return mService.getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
-        return mService.getPriority(device);
+        if (mService == null) {
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        }
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
         if (mService == null) return;
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index 8f40ab4..80b03a4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -175,7 +175,7 @@
                     return;
                 }
                 A2dpSinkProfile a2dpSink = mProfileManager.getA2dpSinkProfile();
-                if ((a2dpSink != null) && (a2dpSink.isA2dpPlaying())){
+                if ((a2dpSink != null) && (a2dpSink.isAudioPlaying())) {
                     return;
                 }
             }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index d4dda32..95139a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -123,8 +123,8 @@
             return false;
         }
         // Downgrade priority as user is disconnecting.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -140,14 +140,14 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -155,11 +155,11 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
index b2a9a6a..31a0eea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -119,8 +119,8 @@
         if (mService == null) {
             return false;
         }
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -136,14 +136,14 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -151,11 +151,11 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
index 7162121..387bae1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
@@ -1,8 +1,7 @@
 # Default reviewers for this and subdirectories.
-asapperstein@google.com
-asargent@google.com
-eisenbach@google.com
-jackqdyulei@google.com
 siyuanh@google.com
+hughchen@google.com
+timhypeng@google.com
+robertluo@google.com
 
-# Emergency approvers in case the above are not available
\ No newline at end of file
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
index e1e5dbe..8e3f3ed 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
@@ -57,7 +57,7 @@
     }
 
     public int getPreferred(BluetoothDevice device) {
-        return BluetoothProfile.PRIORITY_OFF; // Settings app doesn't handle OPP
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; // Settings app doesn't handle OPP
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index a2da4fb..4ea0df6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -151,14 +151,14 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -166,11 +166,11 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
index d91226e..3f920a8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.bluetooth;
 
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothPbap;
@@ -52,14 +53,16 @@
 
     // These callbacks run on the main thread.
     private final class PbapServiceListener
-            implements BluetoothPbap.ServiceListener {
+            implements BluetoothProfile.ServiceListener {
 
-        public void onServiceConnected(BluetoothPbap proxy) {
+        @Override
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
             mService = (BluetoothPbap) proxy;
             mIsProfileReady=true;
         }
 
-        public void onServiceDisconnected() {
+        @Override
+        public void onServiceDisconnected(int profile) {
             mIsProfileReady=false;
         }
     }
@@ -74,7 +77,8 @@
     }
 
     PbapServerProfile(Context context) {
-        BluetoothPbap pbap = new BluetoothPbap(context, new PbapServiceListener());
+        BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new PbapServiceListener(),
+                BluetoothProfile.PBAP);
     }
 
     public boolean accessProfileEnabled() {
@@ -97,13 +101,8 @@
     }
 
     public int getConnectionStatus(BluetoothDevice device) {
-        if (mService == null) {
-            return BluetoothProfile.STATE_DISCONNECTED;
-        }
-        if (mService.isConnected(device))
-            return BluetoothProfile.STATE_CONNECTED;
-        else
-            return BluetoothProfile.STATE_DISCONNECTED;
+        if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
+        return mService.getConnectionState(device);
     }
 
     public boolean isPreferred(BluetoothDevice device) {
@@ -142,7 +141,8 @@
         Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
-                mService.close();
+                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.PBAP,
+                        mService);
                 mService = null;
             }catch (Throwable t) {
                 Log.w(TAG, "Error cleaning up PBAP proxy", t);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
index 9b733f2..0ca4d61 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -119,8 +119,8 @@
         if (mService == null) {
             return false;
         }
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        if (mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
         return mService.disconnect(device);
     }
@@ -136,14 +136,14 @@
         if (mService == null) {
             return false;
         }
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     public int getPreferred(BluetoothDevice device) {
         if (mService == null) {
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
-        return mService.getPriority(device);
+        return mService.getConnectionPolicy(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
@@ -151,11 +151,11 @@
             return;
         }
         if (preferred) {
-            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
-                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
             }
         } else {
-            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+            mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
         }
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 4d76e44..51806e0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -38,6 +38,8 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.text.TextUtils;
 
@@ -74,6 +76,8 @@
     private LocationManager mLocationManager;
     @Mock
     private ServiceState mServiceState;
+    @Mock
+    private NetworkRegistrationInfo mNetworkRegistrationInfo;
 
     @Before
     public void setUp() {
@@ -216,6 +220,7 @@
     @Test
     public void isInService_voiceInService_returnTrue() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
         assertThat(Utils.isInService(mServiceState)).isTrue();
     }
 
@@ -223,15 +228,23 @@
     public void isInService_voiceOutOfServiceDataInService_returnTrue() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+        when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+                NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN);
+
         assertThat(Utils.isInService(mServiceState)).isTrue();
     }
 
     @Test
     public void isInService_voiceOutOfServiceDataInServiceOnIwLan_returnFalse() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
-        when(mServiceState.getDataNetworkType())
-                .thenReturn(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN);
+        when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+        when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
         when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
         assertThat(Utils.isInService(mServiceState)).isFalse();
     }
 
@@ -239,12 +252,14 @@
     public void isInService_voiceOutOfServiceDataOutOfService_returnFalse() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+
         assertThat(Utils.isInService(mServiceState)).isFalse();
     }
 
     @Test
     public void isInService_ServiceStatePowerOff_returnFalse() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+
         assertThat(Utils.isInService(mServiceState)).isFalse();
     }
 
@@ -257,6 +272,7 @@
     @Test
     public void getCombinedServiceState_ServiceStatePowerOff_returnPowerOff() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+
         assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
                 ServiceState.STATE_POWER_OFF);
     }
@@ -264,6 +280,7 @@
     @Test
     public void getCombinedServiceState_voiceInService_returnInService() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
         assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
                 ServiceState.STATE_IN_SERVICE);
     }
@@ -272,14 +289,33 @@
     public void getCombinedServiceState_voiceOutOfServiceDataInService_returnInService() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+        when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+                NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN);
+
         assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
                 ServiceState.STATE_IN_SERVICE);
     }
 
     @Test
+    public void getCombinedServiceState_voiceOutOfServiceDataInServiceOnIwLan_returnOutOfService() {
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).thenReturn(mNetworkRegistrationInfo);
+        when(mNetworkRegistrationInfo.getRegistrationState()).thenReturn(
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
+                ServiceState.STATE_OUT_OF_SERVICE);
+    }
+
+    @Test
     public void getCombinedServiceState_voiceOutOfServiceDataOutOfService_returnOutOfService() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+
         assertThat(Utils.getCombinedServiceState(mServiceState)).isEqualTo(
                 ServiceState.STATE_OUT_OF_SERVICE);
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5e2b7c8..6821942 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -949,8 +949,7 @@
                                                 (1 << AudioManager.STREAM_NOTIFICATION) |
                                                 (1 << AudioManager.STREAM_SYSTEM) |
                                                 (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
-                if (!mContext.getResources().getBoolean(
-                        com.android.internal.R.bool.config_voice_capable)) {
+                if (!getTelephonyManager().isVoiceCapable()) {
                     ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
                 }
                 db.execSQL("DELETE FROM system WHERE name='"
@@ -2579,7 +2578,7 @@
             String val = "";
             String mode;
             for (int phoneId = 0;
-                    phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) {
+                    phoneId < getTelephonyManager().getPhoneCount(); phoneId++) {
                 mode = TelephonyManager.getTelephonyProperty(phoneId,
                         "ro.telephony.default_network",
                         Integer.toString(RILConstants.PREFERRED_NETWORK_MODE));
@@ -2693,4 +2692,9 @@
     private String getDefaultDeviceName() {
         return mContext.getResources().getString(R.string.def_device_name_simple, Build.MODEL);
     }
+
+    private TelephonyManager getTelephonyManager() {
+        return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
 }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 092eedf..efd31ca 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -213,6 +213,9 @@
       <!-- Permission required for CTS test - CarModeInCallServiceTest -->
     <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
 
+    <!-- Permission required for CTS test - TetheringManagerTest -->
+    <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
@@ -246,6 +249,7 @@
 
         <activity
             android:name=".BugreportWarningActivity"
+            android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight"
             android:finishOnCloseSystemDialogs="true"
             android:excludeFromRecents="true"
             android:exported="false" />
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 4dbca47..9d9cad8 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -163,8 +163,7 @@
     public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode,
             boolean showMissingSim) {
         mContext = context;
-        mIsEmergencyCallCapable = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_voice_capable);
+        mIsEmergencyCallCapable = getTelephonyManager().isVoiceCapable();
 
         mShowAirplaneMode = showAirplaneMode;
         mShowMissingSim = showMissingSim;
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index 210b82d..1acccf9 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -26,6 +26,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Slog;
 import android.view.MotionEvent;
@@ -92,13 +93,16 @@
 
     public EmergencyButton(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mIsVoiceCapable = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_voice_capable);
+        mIsVoiceCapable = getTelephonyManager().isVoiceCapable();
         mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
         mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
     }
 
+    private TelephonyManager getTelephonyManager() {
+        return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
index 812f215..0210e08 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfo.java
@@ -25,12 +25,12 @@
 final class ClockInfo {
 
     private final String mName;
-    private final String mTitle;
+    private final Supplier<String> mTitle;
     private final String mId;
     private final Supplier<Bitmap> mThumbnail;
     private final Supplier<Bitmap> mPreview;
 
-    private ClockInfo(String name, String title, String id,
+    private ClockInfo(String name, Supplier<String> title, String id,
             Supplier<Bitmap> thumbnail, Supplier<Bitmap> preview) {
         mName = name;
         mTitle = title;
@@ -50,7 +50,7 @@
      * Gets the name (title) of the clock face to be shown in the picker app.
      */
     String getTitle() {
-        return mTitle;
+        return mTitle.get();
     }
 
     /**
@@ -80,7 +80,7 @@
 
     static class Builder {
         private String mName;
-        private String mTitle;
+        private Supplier<String> mTitle;
         private String mId;
         private Supplier<Bitmap> mThumbnail;
         private Supplier<Bitmap> mPreview;
@@ -94,7 +94,7 @@
             return this;
         }
 
-        public Builder setTitle(String title) {
+        public Builder setTitle(Supplier<String> title) {
             mTitle = title;
             return this;
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9e2464e..5668c5f 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -243,11 +243,12 @@
         mPreviewClocks.reloadCurrentClock();
         mListeners.forEach((listener, clocks) -> {
             clocks.reloadCurrentClock();
-            ClockPlugin clock = clocks.getCurrentClock();
-            if (clock instanceof DefaultClockController) {
-                listener.onClockChanged(null);
+            final ClockPlugin clock = clocks.getCurrentClock();
+            if (Looper.myLooper() == Looper.getMainLooper()) {
+                listener.onClockChanged(clock instanceof DefaultClockController ? null : clock);
             } else {
-                listener.onClockChanged(clock);
+                mMainHandler.post(() -> listener.onClockChanged(
+                        clock instanceof DefaultClockController ? null : clock));
             }
         });
     }
@@ -322,7 +323,7 @@
             mClocks.put(plugin.getClass().getName(), plugin);
             mClockInfo.add(ClockInfo.builder()
                     .setName(plugin.getName())
-                    .setTitle(plugin.getTitle())
+                    .setTitle(plugin::getTitle)
                     .setId(id)
                     .setThumbnail(plugin::getThumbnail)
                     .setPreview(() -> plugin.getPreview(mWidth, mHeight))
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/OWNERS b/packages/SystemUI/src/com/android/systemui/biometrics/OWNERS
new file mode 100644
index 0000000..8765c9a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+kchyn@google.com
+jaggies@google.com
+curtislb@google.com
+ilyamaty@google.com
+joshmccloskey@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 75231448..582775e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -51,8 +51,8 @@
 
 import java.io.PrintWriter;
 import java.util.BitSet;
-import java.util.Objects;
 import java.util.List;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -91,7 +91,8 @@
     @VisibleForTesting
     boolean mIsShowingIconGracefully = false;
     // Some specific carriers have 5GE network which is special LTE CA network.
-    private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
+    private static final int NETWORK_TYPE_LTE_CA_5GE =
+            TelephonyManager.getAllNetworkTypes().length + 1;
 
     // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
     // need listener lists anymore.
@@ -556,8 +557,8 @@
         // If this is the data subscription, update the currentState data name
         if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null
                 && mCurrentState.dataSim
-                && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) {
-            mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort();
+                && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
+            mCurrentState.networkNameData = mServiceState.getOperatorAlphaShort();
         }
 
         notifyListenersIfNecessary();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
index d2b2654..4c0890a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockInfoTest.java
@@ -57,7 +57,7 @@
     @Test
     public void testGetTitle() {
         final String title = "title";
-        ClockInfo info = ClockInfo.builder().setTitle(title).build();
+        ClockInfo info = ClockInfo.builder().setTitle(() -> title).build();
         assertThat(info.getTitle()).isEqualTo(title);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
index 0cd6f9a..d2832fb9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockOptionsProviderTest.java
@@ -117,12 +117,12 @@
     public void testQuery_listOptions() {
         mClocks.add(ClockInfo.builder()
                 .setName("name_a")
-                .setTitle("title_a")
+                .setTitle(() -> "title_a")
                 .setId("id_a")
                 .build());
         mClocks.add(ClockInfo.builder()
                 .setName("name_b")
-                .setTitle("title_b")
+                .setTitle(() -> "title_b")
                 .setId("id_b")
                 .build());
         Cursor cursor = mProvider.query(mListOptionsUri, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index aa4723a..99e5a76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -500,7 +500,7 @@
     public void testUpdateDataNetworkName() {
         setupDefaultSignal();
         String newDataName = "TestDataName";
-        when(mServiceState.getDataOperatorAlphaShort()).thenReturn(newDataName);
+        when(mServiceState.getOperatorAlphaShort()).thenReturn(newDataName);
         updateServiceState();
         assertDataNetworkNameEquals(newDataName);
     }
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 7e8721d..08552cb 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -29,8 +29,11 @@
         "netlink-client",
         "networkstack-aidl-interfaces-unstable-java",
         "android.hardware.tetheroffload.control-V1.0-java",
-        "tethering-client",
     ],
+    libs: [
+        "framework-tethering",
+    ],
+
     manifest: "AndroidManifestBase.xml",
 }
 
@@ -89,6 +92,10 @@
     resource_dirs: [
         "res",
     ],
+    libs: [
+        "framework-tethering",
+    ],
+    jarjar_rules: "jarjar-rules.txt",
     optimize: {
         proguard_flags_files: ["proguard.flags"],
     },
@@ -103,7 +110,6 @@
     manifest: "AndroidManifest_InProcess.xml",
     // InProcessTethering is a replacement for Tethering
     overrides: ["Tethering"],
-    // TODO: use PlatformNetworkPermissionConfig.
 }
 
 // Updatable tethering packaged as an application
diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml
index 1430ed0..87a8c3f 100644
--- a/packages/Tethering/AndroidManifest.xml
+++ b/packages/Tethering/AndroidManifest.xml
@@ -17,10 +17,25 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.tethering"
+          package="com.android.networkstack.tethering"
           android:sharedUserId="android.uid.networkstack">
     <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
 
+    <!-- Permissions must be defined here, and not in the base manifest, as the tethering
+         running in the system server process does not need any permission, and having
+         privileged permissions added would cause crashes on startup unless they are also
+         added to the privileged permissions whitelist for that package. -->
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.MANAGE_USB" />
+    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+
     <application
         android:process="com.android.networkstack.process"
         android:extractNativeLibs="false"
diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml
index dc013da..fa85f66 100644
--- a/packages/Tethering/AndroidManifestBase.xml
+++ b/packages/Tethering/AndroidManifestBase.xml
@@ -17,7 +17,7 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.tethering"
+          package="com.android.networkstack.tethering"
           android:versionCode="1"
           android:versionName="R-initial">
     <application
diff --git a/packages/Tethering/AndroidManifest_InProcess.xml b/packages/Tethering/AndroidManifest_InProcess.xml
index 28d405c..02ea551 100644
--- a/packages/Tethering/AndroidManifest_InProcess.xml
+++ b/packages/Tethering/AndroidManifest_InProcess.xml
@@ -17,16 +17,14 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.tethering.inprocess"
+          package="com.android.networkstack.tethering.inprocess"
           android:sharedUserId="android.uid.system"
           android:process="system">
     <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
     <application>
-        <!-- TODO: Using MAINLINE_NETWORK_STACK instead of NETWORK_STACK when tethering run in the
-                   same process with networkstack -->
         <service android:name="com.android.server.connectivity.tethering.TetheringService"
                  android:process="system"
-                 android:permission="android.permission.NETWORK_STACK">
+                 android:permission="android.permission.MAINLINE_NETWORK_STACK">
             <intent-filter>
                 <action android:name="android.net.ITetheringConnector.InProcess"/>
             </intent-filter>
diff --git a/packages/Tethering/CleanSpec.mk b/packages/Tethering/CleanSpec.mk
deleted file mode 100644
index 70db351..0000000
--- a/packages/Tethering/CleanSpec.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# If you don't need to do a full clean build but would like to touch
-# a file or delete some intermediate files, add a clean step to the end
-# of the list.  These steps will only be run once, if they haven't been
-# run before.
-#
-# E.g.:
-#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
-#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
-#
-# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
-# files that are missing or have been moved.
-#
-# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
-# Use $(OUT_DIR) to refer to the "out" directory.
-#
-# If you need to re-do something that's already mentioned, just copy
-# the command and add it to the bottom of the list.  E.g., if a change
-# that you made last week required touching a file and a change you
-# made today requires touching the same file, just copy the old
-# touch step and add it to the end of the list.
-#
-# *****************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
-# *****************************************************************
-
-# For example:
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
-#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
-#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
-
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Tethering)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/InProcessTethering)
-
-# ******************************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
-# ******************************************************************
diff --git a/packages/Tethering/apex/Android.bp b/packages/Tethering/apex/Android.bp
index bca01ebd..94ef11c 100644
--- a/packages/Tethering/apex/Android.bp
+++ b/packages/Tethering/apex/Android.bp
@@ -15,21 +15,22 @@
 //
 
 apex {
-    name: "com.android.tethering.apex",
+    name: "com.android.tethering",
+    java_libs: ["framework-tethering"],
     apps: ["Tethering"],
     manifest: "manifest.json",
-    key: "com.android.tethering.apex.key",
+    key: "com.android.tethering.key",
 
     androidManifest: "AndroidManifest.xml",
 }
 
 apex_key {
-    name: "com.android.tethering.apex.key",
-    public_key: "com.android.tethering.apex.avbpubkey",
-    private_key: "com.android.tethering.apex.pem",
+    name: "com.android.tethering.key",
+    public_key: "com.android.tethering.avbpubkey",
+    private_key: "com.android.tethering.pem",
 }
 
 android_app_certificate {
-    name: "com.android.tethering.apex.certificate",
-    certificate: "com.android.tethering.apex",
+    name: "com.android.tethering.certificate",
+    certificate: "com.android.tethering",
 }
diff --git a/packages/Tethering/apex/AndroidManifest.xml b/packages/Tethering/apex/AndroidManifest.xml
index 7769b79..5c35c51 100644
--- a/packages/Tethering/apex/AndroidManifest.xml
+++ b/packages/Tethering/apex/AndroidManifest.xml
@@ -15,7 +15,7 @@
  * limitations under the License.
  -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-  package="com.android.tethering.apex">
+  package="com.android.tethering">
   <!-- APEX does not have classes.dex -->
   <application android:hasCode="false" />
   <!-- b/145383354: Current minSdk is locked to Q for development cycle, lock it to next version
diff --git a/packages/Tethering/apex/com.android.tethering.apex.avbpubkey b/packages/Tethering/apex/com.android.tethering.apex.avbpubkey
deleted file mode 100644
index 9c87111..0000000
--- a/packages/Tethering/apex/com.android.tethering.apex.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.apex.pem b/packages/Tethering/apex/com.android.tethering.apex.pem
deleted file mode 100644
index a8cd12e..0000000
--- a/packages/Tethering/apex/com.android.tethering.apex.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEAwloHpMmwszNBEgUVion141BTvF/oJ5g5DlQIYBtmht4tSpc3
-6elWXd+dhMzFxf/RkxSNRsU+dhD11cPKGp9nUYQQGrHEf3xEKwAHJKRMq26TkJ3o
-1TwOO70TaRKKA4ThNiM3VFDX2vy1ijArhZDIBTGVJCUl9HOHiO+ZJG5DKCx3KXbO
-QWz3c+Lbprr1L76dwIsl5kuoAFwgG0J+9BZhHEzIG1lVpGG7RRLxc8eDIxNN/oKT
-gPYBcOxFYqOECKGBBvElf6MxdRv6xG7gooALY2/HDMYUjAJSOosfwzeymugCzMhK
-e+6CSTAaEfUzuVZvMc2qnd1ly7zpLo9x+TOdH5LEVZpSwqmu2n5bqrUnSEAJUvMz
-SSw0YbsLWJZuTiTV7lecSITgqsmwuZyDexDmUkDQChzrTixsQV6S8vsh/FanjWoi
-zBlPneX8Q7/LME3hxHyLbrabxX0zWiyj8iM9h/8Y4mpO/MjEmmavglTAP4J8zrKD
-FBsntCoch9I49IpYBuO6NfKw1h7AUpLf8gARAjFjRxiJVcSgGY/Wt4/pBzJ57T5g
-xPvqxfpPQP0OA2CT8LqqzZIR8jXs8/TquvwLkkY2kRRPXx+azd5oU2A0uonrUY31
-Bc1obfmWPuEMz9bO/i06ETHuWPd4RiUNaB8qEmjYuKJfhv72YNcRwhrAYJECAwEA
-AQKCAgAaQn3b5yCH5fn5zFQPxvpBP35A6ph8mRXEeNg03B7rRCPMe0gjw9JWlrs6
-0Uw7p4gSnmlEUaxR2ZLN0kmBdV5JZlWitbg+HXU8diGA8u4lD6jCloN6JEYsDi0M
-OmQJe6/OV83HB7FStmh1BnMq9dgA06U6IAbT07RRbUY85OUQDYoAQTw3HNkGgHV7
-PrGYROIdvO9fAYPuoIP6Cu8KXee7Iii7gUOQFWBvQdL7+M4gNCCKrevuNc8WCeaK
-IFvbqq67WGPfrhYlo6UrW2vgqPpg8h5r/GuUS0/+9wNQpjrssUKHltxxiFV0PBqZ
-qI7XkPUvPoG6GMsDT0AWeW1F5ZJqEGPN67Xek0BCD0cpUli+nHD0yWGVHtkpHU2D
-qUOZdB2COfBuXRdW1LsYNPg8YjTCPsmGhISLTwiTNcZJeTxoK1y0CcVW9d7Af2aD
-lYzCegscQlXkSZiFj9s90Vd3KdD2XKrH/ADxzsOxQJ89ka004efdQa5/MKs9aChG
-/5XrwBEfN4O92OjY7KqXUAwB7CcVzNymOjD6r07LM24zbkRpwwXlkP0wmjsHBXkh
-8p0ISmY9QRdvhBgYmFmoPWZncM0zym9LI8atBs4CijQ7JjuOQ8HgHg+Se2eppWfe
-t8r6TVkDB8JeNAMxjX9q0G7icf3JjlIrgERZfyXLmpduR9NdkQKCAQEA5rp2fSKh
-RwihHNtJhNktFJuLR9OA++vyfjqhWnB8CrLPo3//LGWW/+WBr8EwXi/76hQpeKlf
-u8SmkTtxIHlTP2Brh2koh1Qf8HKzPHGjZeDFOoVPKHPqe3nV+cv3srd1mS0Eq3BA
-ZFQq+l61f2iiTZKxDroCahNEa8VMzirW6nKb5xhyMPHXgncCUdphHbwAGatas6be
-RUFg4ChH8BwX6jYw7leRUy2K6OqEl0fckT4Laitlb/ezKtwmD4PPE95q5hH0v3SO
-wetHWafiNrOXPn2wQqBrI2y+AfbTjNmQiaIPgcFKAQ7V3n+c3XfGZ9Xfv4L8m/wo
-RZ4ika1zur021QKCAQEA16OUBPA7BnWd+RJFri2kJBG5JZElaV9chO2ZHcXUbFR9
-HIPkWN19bJbki8Ca0w8FUQuS/M7JeeFjoZ194NlczbR899GVmb0X2AUKXilMacs3
-IONxIDczx3KFtsge8ewXRAjQvgE7M3NpmmJfPLPog7spMCbUIxbc3jzjiZgB/J1s
-WytlUTUY/Zy4V1wujkoydgK2KcHcEWG2oIy7EP0RwnL1NhTksXOtBH6+MoRMAT+H
-fcBK6yfJBNBRQzJ0PdkCCLdQPN1VtwRlWjPXZ3ey4fWvZ399wSLUkM2V1jB4GcOZ
-+DAgtwFKs9+HfOdV42GgFWFcjP+bkM3bcdrQFnmYzQKCAQAQnf1KpePXqddwrJpu
-5vVINquhUKpJeoTMcoyMZu2IF7i8nctS9z4Yz/63GcLSBcKu6STTe99ZNqCIdS+A
-lzxXpCoaZoh0tqpWNuyRvd12yOlrfY5l63NH0U6H3xjH1k6x6XwcnMkGcMlnnsqT
-koWd8KKv3NWvrhOPb3ZIou03lWmFC02uGLzcuJWCL6gu7AtVzfGKXspDUqIXgs8r
-i9ptE9oSUFw3EWCfxcQm4RYRn9ZSny1/EufkflZ/Z47Sb4Jjb4ehAlQFw1wwKNcx
-+V07MvIu2j7dHkfQ/GXgDwtJ3lIfljwuN1NP4wD5Mlcnw0+KC3UGBvMfkHQM6eEb
-4eTBAoIBAQDWfZsqHlpX3n431XkB+9wdFJP5ThrMaVJ51mxLNRBKgO/BgV+NFSNA
-9AZ5DCf0cCh1qPGYDYhSd2LGywT+trac1j7Hse0AcxpYgQsDBkk/oic/y3wm80HJ
-zZw7Z2uAb7nkrnATzt24G8CbE+ZvVvScs3oQr06raH5hgGdD4bN4No4lUVECKbKl
-8VFbdBHK7vqqb6AKgQ4JLAygPduE1nTn2bkXBklESS98HSXK0dVYGH0JFFBw/63v
-39Y05ObC7iwbx1tEb1RnKzQ1OQO1o1aHc/35ENNhXOfa8ONtneCYn/ty50xjPCG2
-MU1vbBv+hIjbO3D3vvhaXKk+4svAz0qxAoIBAQC84FJEjKHJHx17jLeoTuDfuxwX
-6bOQrI3nHbtnFRvPrMryWRDtHLv89Zma3o68/n4vTn5+AnvgYMZifOYlTlIPxinH
-tlE+qCD8KBXUlZdrc+5GGM18lp5tF3Ro4LireH+OhiOAWawaSzDIDYdiR6Kz9NU+
-SjcHKjDObeM6iMEukoaRsufMedpUSrnbzMraAJgBZGay1NZs/o8Icl3OySYPZWEK
-MJxVBMXU9QcUp2GEioYd/eNuP9rwyjq/EIUDJbP2vESAe6+FdGbIgvyYTV/gnKaH
-GcvyMNVZbCMp/wCYNonjlu+18m2w+pVs2uuZLqORkrKYhisK83TKxh4YOWJh
------END RSA PRIVATE KEY-----
diff --git a/packages/Tethering/apex/com.android.tethering.apex.pk8 b/packages/Tethering/apex/com.android.tethering.apex.pk8
deleted file mode 100644
index 5663246..0000000
--- a/packages/Tethering/apex/com.android.tethering.apex.pk8
+++ /dev/null
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.apex.x509.pem b/packages/Tethering/apex/com.android.tethering.apex.x509.pem
deleted file mode 100644
index a5e9401..0000000
--- a/packages/Tethering/apex/com.android.tethering.apex.x509.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGMzCCBBugAwIBAgIUXVtoDaXanhs7ma8VIICambMkj5UwDQYJKoZIhvcNAQEL
-BQAwgacxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMSMwIQYDVQQDDBpjb20uYW5kcm9pZC50ZXRoZXJpbmcuYXBleDEiMCAGCSqG
-SIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0xOTExMjgwNjU4MTRaGA80
-NzU3MTAyNDA2NTgxNFowgacxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9y
-bmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAw
-DgYDVQQLDAdBbmRyb2lkMSMwIQYDVQQDDBpjb20uYW5kcm9pZC50ZXRoZXJpbmcu
-YXBleDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBANwzufMBdOj9XlNwiX+bXl/94G0DklWW
-nzob0jPlubCFfRqYkjCf2eOd28Mu/O1pOBcvobnrs9OTpGzcHkz2h58L5/0UMVTS
-tBugwCE49XF5FHawqVHNZE+s5tDmnp2cufhNc5HXHY4oZKh80/WVdbcKxiLjSY2T
-PgRAfB6E6XByKD3t1cSsc3liRVKADoJOVDvmF+xnyvSV/SN38bvTQk9aVs95mj0W
-yov6gzXBnqN7iQlvkhcijZBnFWxvoNbJ5KFy1abYOrm+ueXje4BcNhVOeRMb4E9N
-eo7+9k1GEI7TYG7laNNcp7UJ1IXCJzv/wBFKRg3f1HB3unKfx2rtKerDnVsr3o7V
-KProkgRNKNhhQ6opNguiH1YMzKpWMaC988n4AQPryPdIOmVIxIC5jJrixdxgzDXT
-qeiwFiXis291uyls08B03PQFlY9oWaY9P8s+4hIUjB6rLl+XZXsLDtDFxXeJ97NB
-8XZN1gBJoBoLknFs0C4LKpmJZB/EBao9tXV9dL/5lydRo6HzQDpjW8QX06CTUM6z
-Lr3LVelhqbsuZsV42yBKl+/LfrvNjBLEPdSevt2oMrlJW7m4iSNaMtDtJ2Oy8fA5
-WSIgLWuMbkaFDza3JzwiMzxbtbJHYiy6rY7aVywo3Vqwr1+KO3cq4eLQq62zUjRY
-e6KJwvgE2YmpAgMBAAGjUzBRMB0GA1UdDgQWBBQ8h1oF5JfKFmJCN8nfimbUK+IR
-wjAfBgNVHSMEGDAWgBQ8h1oF5JfKFmJCN8nfimbUK+IRwjAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAP5hIkAxSyt9hRafMKiFlmXcL277bgoxNd
-qGZYbdcCFjfvM2r0QQcM/K7x2ZslFe7mJSzcyMifpm4YQTEo2yYbzKItXQV+eV1K
-9RNksRGFG9umsdWaSHhfQmcmxtr2nu9rGAgxy5OQFtyXmJPUPEM2cb/YeILwYhuQ
-Ux3kaj/fxGltX1JBag7HnMzCTZK++fRo5nqFVOJQgJH8ZpuzGeM9kZvP1+b55046
-PhSnlqmZoKhG4i5POPvvZvaakh/lM3x/N7lIlSaQpCGf7jmldni4L0/GenULVKzH
-iN73aBfh4GEvE0HRcOoH3L7V6kc3WMMLve0chZBHpoVYbzUJEJOUL4yrmwEehqtf
-xm4vlYg3vqtcE3UnU/UGdMb16t77Nz88LlpBY5ierIt0jZMU0M81ppRhr1uiD2Lj
-091sEA0Bxcw/6Q8QNF2eR7SG7Qwipnms+lw6Vcxve+7DdTrdEA0k3XgpdXp8Ya+2
-PAp9SLVp1UHiGq3qD9Jvm34QmlUWAIUTHZs3DSgs1y3K5eyw/cnzTvUUOljc/n2y
-VF0FFZtJ1dVLrzQ80Ik7apEXpBqkgBGV04/L3QYk4C0/sP+1yk6zjeeeAvDtUcHS
-gLtjAfacQl/kwfVQWfrF7VByLcivApC6EUdvT3cURM5DfZRQ4RcKr1D61VYPnNRH
-+/NVbMObwQ==
------END CERTIFICATE-----
diff --git a/packages/Tethering/apex/com.android.tethering.avbpubkey b/packages/Tethering/apex/com.android.tethering.avbpubkey
new file mode 100644
index 0000000..9a2c017
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.avbpubkey
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.pem b/packages/Tethering/apex/com.android.tethering.pem
new file mode 100644
index 0000000..d4f39ab
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEA+AWTp03PBRMGt4mVNLt5PDoFFSfmFOVTM7jt5AJXnQMIDsAM
+1cyWGWRridGIpoHAaCALVgW5aRySgi8yV5xP4w0YHcKbfh9M6I9oz4RUo4GQBZfX
++lFIGaLjb6I3tEJxPuxps4sW26Io63ihwTnKeGyADHdHGWDUs9WU0Ml+QTvKrdjy
+qC03M0dehYXILGiA9m+UXwKoKxhWgfDUhWLhDBUtLJLPL4WeqKc9sG9h+zzVqE+8
+LzJsfrodKhTTrLpWOXi6YLRTk8dzsuPz/Nu98sJd1w3fHd20DrmkqsxVhgN1h+nk
+zcPpxyGYIP6qYVZCmIXCwZZNtPeb7y/tOs967VHoZ4Qj7p2tE0CAWFMZFGjA/pcZ
+7fi6CsIuMOYBbj4+wRlJwpG1g5zSJBCjzhv7dZp8S5oXmLShNYOMYEdsPfaZbm08
+3pVY+k8DVf7idcANXNw1lM+sPbE2hp5VuEuVpK+ca5x8hIMpTqJ84wDAjnC1kCwm
+X2xfNvYPKNF58SvqlNCPN8X7hQjoeaEb7w24vCdZMRqeGBmu1GNQvCyzbBO0huQm
+f5CQPrZjPcnoImlP879VPxY4YB6tAjsA/ZLiub9VdT108lCjb5r8criMzpMAA/AQ
+NqQLWFI3M43xPemGBTiIguTYgpRgGcdRZf7XuTgTY5qzQZZuZMVuwaqSD2cCAwEA
+AQKCAgEA0jMvw3BPTrakT7Lb8JgelKt7mUV6WyVMUZ6eh0pw5JIoJxAfEKfWYmjY
+NzKNRMjcv6LA2MP7MplTld/YI6ZHkl+Lm9VOISL39HVuV8mIThbFb+gT1INEvu1t
+IjRyT2SsQ67rmo377mLNmVtgg7mt3kfecjI44MpPGqad/CF4zmKVUKd4aI4BpYUM
+F8+dKf3bpoBEWA2RZwy2bGQmSXHW132vDoLR8y2knL04rCqJ+PrC/WWuULXEe9bS
+VtLV3yMBZq3qD4Fk/+7fILLPGvNFVdPi4htQiChYrM4rP9HzfaO63VieYMF0hR70
+pqoOznXj9Q4QVC9FZmUgFCQjQ1+KhqJw3OldIo0SnvpsLdTO/inKkhQWKC5HlPyh
+/rqvro2j3pTHWPAziuBr+oQPcdVCOlCBZ+B99L1tO7aGktVPEIVQG7G7jlFMBiJ1
+j/kRGk2RTX8RaPQJTnwUqp8mWUV2fwxHiXNadjejA5ZU3eQT2eAOhXl1w6Lv2jEl
+0wMOwPMJGcF77CcqnnWHON8fkxCbAfyy5Uo6Pm9g/Zzecn+ji2sabG7Ge5t0gzdL
+LKRcGoyakN2CrbQ8pxlCTgE4HX5oPY+VuqOf8L3AIWIJBsyLbXHVkL1mqQ/Ed2uz
+zaaSFYUZw81+m/5bl8JLPaIFNPyikZrXTD0YRer3V06XiyP/kYECggEBAP033xeF
+OhgRwkRTjd68hwRJpyHsZDWxHiUqQf6l6yFv5mEE355G2IGI7cZmR2+tUDjQdxLv
+tAZIszTK4PFCdVTeWfGVFbVF84eNWLB124pHDMM79GN/AMcuHnQPR756a8IO1hIy
+4KxIUE1a1PKN5b9IgE5Lu4TZM96HDpFcUAmCT5urdYDmg3++IWT9PYQlGS7Hhiar
+r+Hh646waM8Qx619CwXBqy+Y37+WHVbYqJClr6AcpVMrGA+6cgpskFpZAPLsoy7G
+RSsVfyV8pH2JKm/hzk7XCwIpczxeWQSfpJWZ+oOPFHu+zM60Cdj2UrQyKrNHwew8
++WYe9eCA+MiNBcECggEBAPq/F1vdqROiLv9uzhKb8ybgdL7CmREELiqwK+MvNE9t
+W7lQz7lcWzav+b2n0M+VJBxUWB3XClgoIvA/AllgTgsYXfKAxNakhKLSBoMmvKCW
+HtWcGr/D3RcmacK+DTMWlVS/LuueAFLuH6UmBIUFKc+qA5x7oQecAFALBFupE3G4
+LtAspLBI6P8gRtRav5p2whs9H8qjYcyf2f6liWpkmFITcXvPvAxFHicR6ZJdwZ/S
+PiX2LJQnOpT7L3+2PWnYwzFStb4MkMGlFKcscU9CvS53JcP/J4Asjk0I4zDB2gri
+xzFHPlVzCr2IVVGptKCQ3sdYiMIzQKzEXQHCU8h37ycCggEBAJu8aC48Fz3Edlm1
+ldS+2L9vWSaJEBzhoSu0cMBgZVu8SdGzwKDE69XHVI4oS5lI28UFmaaA3JTc07MN
+cAmSGT2oP2NQkPhbXGsrKLfm1K6YAiZ1Ulp7OwxFth8lYreo7Wt92nV46yuqkhDx
+Y3UGhp39xkPhWiRbvgYHxJLsVqFyjumsK2mq3IeNdVZ6VgJXGsTlnAFeqJ7hZxHs
+N5natSRjeosA0PtGJ57agZLvT8Ue0gREef3LzFGoFwmIOcQHZ4kAt2BGOzZDU17H
+6Rb4bKxBEbT1l2St/5zKXi90zDHicOvG7Q8qiyY6HrBc1wLSs+ZtpLxZx/3h3tFE
+IT6fVUECggEBAMSAQm8Ey76OJ+SXUjk1K50442SnHcs/Cmr7urkEQitImUwl71Pk
+87pst/uP6szypOTqmE9yOTIS6iZ6Sn3+QcriIqWrkhZfwW3Tx7S6A7KZUrq15iSH
++thsiw9JXxC9TvOmC8AsBzb2U6hZncsc28JZCxFztSNAduJDb/vhCVLiMxWDFuDr
+kmR1R+yc3XDQRpeQFDz6QudYEj9EPOc6xD/16sZLaqP2+oVFvVSt0tJLsdaQECle
+gMNGAdhE2eX8MCOUHMc+E6cdlozYAEhMFfO2/cqWR79jq3TlVR3dnOFRDScqHMhc
+KnuTvsELjHkUbvGsCSiff7yk+fop7vy4OJsCggEAPemJdItO2rhib8EofrZdY72I
+oifX1jhPZ1BWD2GKgcx+eVyJGbONBbJVexvvskTfZBvCcAegmgp+sngP6MO6yZkr
+cHMfAJeApYZnshsgXksHGMDtSB50/w1JLrc/nqpxdpy/aTazt0Eu1pLWpze1HFZ/
+Xyu4PcmrU+4P1vN7c396slHMktEvly6QqOn4nfBbGDJ17Ow6X1XFvGjAxQPIDTB+
+6loV14AHymwmqwMrGn84O72rzqyw+41GxW5+oXhOZ4MeXF3u89TBLWvXDpPy/YQU
+EiKpodN0YeEn6Ghzplan8rUha+7TP7AYnS5pCszsCHKd03Py0lMLkF+uAfVsDA==
+-----END RSA PRIVATE KEY-----
diff --git a/packages/Tethering/apex/com.android.tethering.pk8 b/packages/Tethering/apex/com.android.tethering.pk8
new file mode 100644
index 0000000..3b94405
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.pk8
Binary files differ
diff --git a/packages/Tethering/apex/com.android.tethering.x509.pem b/packages/Tethering/apex/com.android.tethering.x509.pem
new file mode 100644
index 0000000..a1786e3
--- /dev/null
+++ b/packages/Tethering/apex/com.android.tethering.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKTCCBBGgAwIBAgIUNiSs5EMqxCZ31gWWCcRJVp9HffAwDQYJKoZIhvcNAQEL
+BQAwgaIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMR4wHAYDVQQDDBVjb20uYW5kcm9pZC50ZXRoZXJpbmcxIjAgBgkqhkiG9w0B
+CQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMTkxMjE4MDcwMDQ4WhgPNDc1NzEx
+MTMwNzAwNDhaMIGiMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
+MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE
+CwwHQW5kcm9pZDEeMBwGA1UEAwwVY29tLmFuZHJvaWQudGV0aGVyaW5nMSIwIAYJ
+KoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEAxvTUA4seblYjZLfTVNwZuJH914QVNFTj+vD94pWmt5Aq
+sH1DVTpBvpXXegc/P5HI2XF/71poSBib1WaQSuXG0fU5K75T18bOGL0qF+fhMtBO
+wUyvulcjO0h4XE/xf0txY54exUjAA4JS9ERGJOgb4GOwSbPyzekfmzIyCZ2Yawwu
++oGwD2ZNzZRaPOoWxjwohBWQ6mySuvF9RRRb300qmxxUGFM9Ki3aqrWlYlHEOwOC
+M+gIXxYFO7S+yUzf6/gMZLOz2YqfcTOup4hAxtExR7niutxJSsRLPBL237exAJoz
+OupoXjtWAlPK4ZwZ/Nl1jdTWauJ+Kv3WqzhHGEb2gn3ZpeO3IdOjJhDgFJ6m1OT/
+kjRbW1LCuKGrKaoqsEDT2X3a7Izfripn65hSNTfR5gNLtgELaI3/vXi8Fmzw1AfH
++qi6ulElZvSwx0qm+S0QiPyGFlxrsdnHoGJl1tzjJW8KdNZRvzRLUQtbphPp+VkL
+5i0bNKum+AwbfdUkLkNLfw9XdbujgBkZTZDQbZGsNjgrvyXcPO2KiJee0hVCZRs0
+rhDi5Pfm7BnN/I2vaTRz/W4mdct9H2RWMuqlSH90JvmKtWcND8ahmOJ3sggrvzfO
+QNs3k4JTRecamMzqIkylhlnEC4FjWc6Bx4wsEpwBMZOkF/tGGMZYf2C09a8tpP0C
+AwEAAaNTMFEwHQYDVR0OBBYEFNP5gIpNWmq0xa411M1GaRPbEijvMB8GA1UdIwQY
+MBaAFNP5gIpNWmq0xa411M1GaRPbEijvMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADggIBADJGmU3QP4EGbt6eBhVPeo/efsqrHsuB2fvFzvIobJbfkSob
+cmvjbzIikOlPAgFWj8lT5SDcIWRorFf1u2JylClJ0nSDcqJMHVKmT7wseV/KtX//
+1yUyJFRQVzmjC89dp8OIc00GmItivKLer3NbJdkR3rTUjg7+bNUO27Qp3AFREmiJ
+P+M7ouvcQRvByUWbp/LOrJpMdJLysRBO562RwrtwTjltdvufyYswbBZOKEiUh1Jc
+Ged+3+SJdhwq3Wy+R3Uj7YE7mUMu1QNbANIMrwF8W93EA53eoL2+cKmuaVU6ZURL
+xgSJaY6TrunnSI9XTROLtjsFlJorYWy2tvG7Q5Hw3OkO2Xdz/mm85VTkiusg9DMB
+WWTv607YtsIO0FhKmcV4bp3q/EkRj3t/zLvL9uFJrWDGkuShZq6fQvqbCvaokOPY
++M0ZRIwgwa9UpEE0BMklVWqR6BGyap614gOgcOjYM70WRNl59Qne+g128ZN7g9nz
+61F70i7kUngV0ZUz1/Fu/NCG+6wGF85ZbFmQl60YHPDw1FtjVUuKyBblaDzdJunx
+yQr2t9RUokzFBFK0lGW3+yf0WDQ5fqTMs5h8bz1FCq8/HzWmpdOfqePLe4zsld3b
+1nFuSohaIfbn/HDdTNtTBGQPgz8ZswQ6ejJJqTLz9D/odbqn9LeIhDZXcQTf
+-----END CERTIFICATE-----
diff --git a/packages/Tethering/apex/manifest.json b/packages/Tethering/apex/manifest.json
index 3fb62f3..b64de4f 100644
--- a/packages/Tethering/apex/manifest.json
+++ b/packages/Tethering/apex/manifest.json
@@ -1,4 +1,4 @@
 {
-  "name": "com.android.tethering.apex",
+  "name": "com.android.tethering",
   "version": 290000000
 }
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index adc5a72..5785707 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -12,7 +12,6 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-//
 
 // AIDL interfaces between the core system and the tethering mainline module.
 aidl_interface {
@@ -20,10 +19,7 @@
     local_include_dir: "src",
     include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
     srcs: [
-        "src/android/net/ITetherInternalCallback.aidl",
-        "src/android/net/ITetheringConnector.aidl",
-        "src/android/net/TetheringConfigurationParcel.aidl",
-        "src/android/net/TetherStatesParcel.aidl",
+        "src/android/net/*.aidl",
     ],
     backend: {
         ndk: {
@@ -36,16 +32,32 @@
 }
 
 java_library {
-    name: "tethering-client",
+    name: "framework-tethering",
     sdk_version: "system_current",
+    srcs: [
+        "src/android/net/TetheringManager.java",
+        ":framework-tethering-annotations",
+    ],
     static_libs: [
         "tethering-aidl-interfaces-java",
     ],
+    jarjar_rules: "jarjar-rules.txt",
+    installable: true,
+
+    libs: [
+        "android_system_stubs_current",
+    ],
 }
 
-// This is temporary file group which would be removed after TetheringManager is built
-// into tethering-client. Will be done by aosp/1156906.
 filegroup {
-    name: "tethering-manager",
-    srcs: ["src/android/net/TetheringManager.java"],
+    name: "framework-tethering-srcs",
+    srcs: [
+        "src/android/net/TetheringManager.java",
+        "src/android/net/IIntResultListener.aidl",
+        "src/android/net/ITetheringEventCallback.aidl",
+        "src/android/net/ITetheringConnector.aidl",
+        "src/android/net/TetheringConfigurationParcel.aidl",
+        "src/android/net/TetherStatesParcel.aidl",
+    ],
+    path: "src"
 }
diff --git a/packages/Tethering/common/TetheringLib/jarjar-rules.txt b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
new file mode 100644
index 0000000..35e0f88
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
@@ -0,0 +1 @@
+rule android.annotation.** com.android.networkstack.tethering.annotation.@1
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
similarity index 77%
rename from core/java/android/net/ITetheringEventCallback.aidl
rename to packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
index d502088..c3d66ee 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/IIntResultListener.aidl
@@ -16,13 +16,10 @@
 
 package android.net;
 
-import android.net.Network;
-
 /**
- * Callback class for receiving tethering changed events
- * @hide
+ * Listener interface allowing objects to listen to various module event.
+ * {@hide}
  */
-oneway interface ITetheringEventCallback
-{
-    void onUpstreamChanged(in Network network);
+oneway interface IIntResultListener {
+    void onResult(int resultCode);
 }
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
index bfe502f..d30c399 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
@@ -15,23 +15,31 @@
  */
 package android.net;
 
-import android.net.ITetherInternalCallback;
+import android.net.IIntResultListener;
+import android.net.ITetheringEventCallback;
 import android.os.ResultReceiver;
 
 /** @hide */
 oneway interface ITetheringConnector {
-    void tether(String iface);
+    void tether(String iface, String callerPkg, IIntResultListener receiver);
 
-    void untether(String iface);
+    void untether(String iface, String callerPkg, IIntResultListener receiver);
 
-    void setUsbTethering(boolean enable);
+    void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);
 
-    void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi);
+    void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
+            String callerPkg);
 
-    void stopTethering(int type);
+    void stopTethering(int type, String callerPkg, IIntResultListener receiver);
 
     void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
-            boolean showEntitlementUi);
+            boolean showEntitlementUi, String callerPkg);
 
-    void registerTetherInternalCallback(ITetherInternalCallback callback);
+    void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+
+    void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+
+    void isTetheringSupported(String callerPkg, IIntResultListener receiver);
+
+    void stopAllTethering(String callerPkg, IIntResultListener receiver);
 }
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
similarity index 83%
rename from packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl
rename to packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
index abb00e8..2836195 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetherInternalCallback.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
@@ -21,14 +21,15 @@
 import android.net.TetherStatesParcel;
 
 /**
- * Callback class for receiving tethering changed events
+ * Callback class for receiving tethering changed events.
  * @hide
  */
-oneway interface ITetherInternalCallback
+oneway interface ITetheringEventCallback
 {
+    void onCallbackStarted(in Network network, in TetheringConfigurationParcel config,
+            in TetherStatesParcel states);
+    void onCallbackStopped(int errorCode);
     void onUpstreamChanged(in Network network);
     void onConfigurationChanged(in TetheringConfigurationParcel config);
     void onTetherStatesChanged(in TetherStatesParcel states);
-    void onCallbackCreated(in Network network, in TetheringConfigurationParcel config,
-            in TetherStatesParcel states);
 }
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index eb0d443..a49ab85 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,94 +15,142 @@
  */
 package android.net;
 
-import static android.Manifest.permission.NETWORK_STACK;
 import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.util.SharedLog;
+import android.content.Context;
+import android.net.ConnectivityManager.OnTetheringEventCallback;
 import android.os.ConditionVariable;
 import android.os.IBinder;
-import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.util.Slog;
+import android.util.ArrayMap;
+import android.util.Log;
 
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.PrintWriter;
-import java.util.StringJoiner;
+import java.util.concurrent.Executor;
 
 /**
- * Service used to communicate with the tethering, which is running in a separate module.
+ * This class provides the APIs to control the tethering service.
+ * <p> The primary responsibilities of this class are to provide the APIs for applications to
+ * start tethering, stop tethering, query configuration and query status.
+ *
  * @hide
  */
+// TODO: make it @SystemApi
 public class TetheringManager {
     private static final String TAG = TetheringManager.class.getSimpleName();
+    private static final int DEFAULT_TIMEOUT_MS = 60_000;
 
     private static TetheringManager sInstance;
 
-    @Nullable
-    private ITetheringConnector mConnector;
-    private TetherInternalCallback mCallback;
-    private Network mTetherUpstream;
+    private final ITetheringConnector mConnector;
+    private final TetheringCallbackInternal mCallback;
+    private final Context mContext;
+    private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+            mTetheringEventCallbacks = new ArrayMap<>();
+
     private TetheringConfigurationParcel mTetheringConfiguration;
     private TetherStatesParcel mTetherStatesParcel;
 
-    private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
-            new RemoteCallbackList<>();
-    @GuardedBy("mLog")
-    private final SharedLog mLog = new SharedLog(TAG);
-
-    private TetheringManager() { }
+    public static final int TETHER_ERROR_NO_ERROR           = 0;
+    public static final int TETHER_ERROR_UNKNOWN_IFACE      = 1;
+    public static final int TETHER_ERROR_SERVICE_UNAVAIL    = 2;
+    public static final int TETHER_ERROR_UNSUPPORTED        = 3;
+    public static final int TETHER_ERROR_UNAVAIL_IFACE      = 4;
+    public static final int TETHER_ERROR_MASTER_ERROR       = 5;
+    public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
+    public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
+    public static final int TETHER_ERROR_ENABLE_NAT_ERROR     = 8;
+    public static final int TETHER_ERROR_DISABLE_NAT_ERROR    = 9;
+    public static final int TETHER_ERROR_IFACE_CFG_ERROR      = 10;
+    public static final int TETHER_ERROR_PROVISION_FAILED     = 11;
+    public static final int TETHER_ERROR_DHCPSERVER_ERROR     = 12;
+    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN  = 13;
+    public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
+    public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
 
     /**
-     * Get the TetheringManager singleton instance.
+     * Create a TetheringManager object for interacting with the tethering service.
      */
-    public static synchronized TetheringManager getInstance() {
-        if (sInstance == null) {
-            sInstance = new TetheringManager();
-        }
-        return sInstance;
-    }
+    public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) {
+        mContext = context;
+        mConnector = ITetheringConnector.Stub.asInterface(service);
+        mCallback = new TetheringCallbackInternal();
 
-    private class TetheringConnection implements
-            ConnectivityModuleConnector.ModuleServiceCallback {
-        @Override
-        public void onModuleServiceConnected(@NonNull IBinder service) {
-            logi("Tethering service connected");
-            registerTetheringService(service);
-        }
-    }
-
-    private void registerTetheringService(@NonNull IBinder service) {
-        final ITetheringConnector connector = ITetheringConnector.Stub.asInterface(service);
-
-        log("Tethering service registered");
-
-        // Currently TetheringManager instance is only used by ConnectivityService and mConnector
-        // only expect to assign once when system server start and bind tethering service.
-        // STOPSHIP: Change mConnector to final before TetheringManager put into boot classpath.
-        mConnector = connector;
-        mCallback = new TetherInternalCallback();
+        final String pkgName = mContext.getOpPackageName();
+        Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
         try {
-            mConnector.registerTetherInternalCallback(mCallback);
+            mConnector.registerTetheringEventCallback(mCallback, pkgName);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw new IllegalStateException(e);
         }
     }
 
-    private class TetherInternalCallback extends ITetherInternalCallback.Stub {
-        private final ConditionVariable mWaitForCallback = new ConditionVariable(false);
-        private static final int EVENT_CALLBACK_TIMEOUT_MS = 60_000;
+    private interface RequestHelper {
+        void runRequest(IIntResultListener listener);
+    }
+
+    private class RequestDispatcher {
+        private final ConditionVariable mWaiting;
+        public int mRemoteResult;
+
+        private final IIntResultListener mListener = new IIntResultListener.Stub() {
+                @Override
+                public void onResult(final int resultCode) {
+                    mRemoteResult = resultCode;
+                    mWaiting.open();
+                }
+        };
+
+        RequestDispatcher() {
+            mWaiting = new ConditionVariable();
+        }
+
+        int waitForResult(final RequestHelper request) {
+            request.runRequest(mListener);
+            if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
+                throw new IllegalStateException("Callback timeout");
+            }
+
+            throwIfPermissionFailure(mRemoteResult);
+
+            return mRemoteResult;
+        }
+    }
+
+    private void throwIfPermissionFailure(final int errorCode) {
+        switch (errorCode) {
+            case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
+                throw new SecurityException("No android.permission.TETHER_PRIVILEGED"
+                        + " or android.permission.WRITE_SETTINGS permission");
+            case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
+                throw new SecurityException(
+                        "No android.permission.ACCESS_NETWORK_STATE permission");
+        }
+    }
+
+    private class TetheringCallbackInternal extends ITetheringEventCallback.Stub {
+        private int mError = TETHER_ERROR_NO_ERROR;
+        private final ConditionVariable mWaitForCallback = new ConditionVariable();
 
         @Override
-        public void onUpstreamChanged(Network network) {
-            mTetherUpstream = network;
-            reportUpstreamChanged(network);
+        public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
+                TetherStatesParcel states) {
+            mTetheringConfiguration = config;
+            mTetherStatesParcel = states;
+            mWaitForCallback.open();
         }
 
         @Override
+        public void onCallbackStopped(int errorCode) {
+            mError = errorCode;
+            mWaitForCallback.open();
+        }
+
+        @Override
+        public void onUpstreamChanged(Network network) { }
+
+        @Override
         public void onConfigurationChanged(TetheringConfigurationParcel config) {
             mTetheringConfiguration = config;
         }
@@ -112,49 +160,10 @@
             mTetherStatesParcel = states;
         }
 
-        @Override
-        public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
-                TetherStatesParcel states) {
-            mTetherUpstream = network;
-            mTetheringConfiguration = config;
-            mTetherStatesParcel = states;
-            mWaitForCallback.open();
+        public void waitForStarted() {
+            mWaitForCallback.block(DEFAULT_TIMEOUT_MS);
+            throwIfPermissionFailure(mError);
         }
-
-        boolean awaitCallbackCreation() {
-            return mWaitForCallback.block(EVENT_CALLBACK_TIMEOUT_MS);
-        }
-    }
-
-    private void reportUpstreamChanged(Network network) {
-        final int length = mTetheringEventCallbacks.beginBroadcast();
-        try {
-            for (int i = 0; i < length; i++) {
-                try {
-                    mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
-                } catch (RemoteException e) {
-                    // Not really very much to do here.
-                }
-            }
-        } finally {
-            mTetheringEventCallbacks.finishBroadcast();
-        }
-    }
-
-    /**
-     * Start the tethering service. Should be called only once on device startup.
-     *
-     * <p>This method will start the tethering service either in the network stack process,
-     * or inside the system server on devices that do not support the tethering module.
-     *
-     * {@hide}
-     */
-    public void start() {
-        // Using MAINLINE_NETWORK_STACK permission after cutting off the dpendency of system server.
-        ConnectivityModuleConnector.getInstance().startModuleService(
-                ITetheringConnector.class.getName(), NETWORK_STACK,
-                new TetheringConnection());
-        log("Tethering service start requested");
     }
 
     /**
@@ -164,88 +173,110 @@
      * IP network interface is available, dhcp will still run and traffic will be
      * allowed between the tethered devices and this device, though upstream net
      * access will of course fail until an upstream network interface becomes
-     * active. Note: return value do not have any meaning. It is better to use
-     * #getTetherableIfaces() to ensure corresponding interface is available for
-     * tethering before calling #tether().
+     * active.
      *
-     * @deprecated The only usages should be in PanService and Wifi P2P which
-     * need direct access.
+     * @deprecated The only usages is PanService. It uses this for legacy reasons
+     * and will migrate away as soon as possible.
      *
-     * {@hide}
+     * @param iface the interface name to tether.
+     * @return error a {@code TETHER_ERROR} value indicating success or failure type
      */
     @Deprecated
-    public int tether(@NonNull String iface) {
-        try {
-            mConnector.tether(iface);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return TETHER_ERROR_NO_ERROR;
+    public int tether(@NonNull final String iface) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "tether caller:" + callerPkg);
+        final RequestDispatcher dispatcher = new RequestDispatcher();
+
+        return dispatcher.waitForResult(listener -> {
+            try {
+                mConnector.tether(iface, callerPkg, listener);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        });
     }
 
     /**
      * Stop tethering the named interface.
      *
-     * @deprecated
-     * {@hide}
+     * @deprecated The only usages is PanService. It uses this for legacy reasons
+     * and will migrate away as soon as possible.
      */
     @Deprecated
-    public int untether(@NonNull String iface) {
-        try {
-            mConnector.untether(iface);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return TETHER_ERROR_NO_ERROR;
+    public int untether(@NonNull final String iface) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "untether caller:" + callerPkg);
+
+        final RequestDispatcher dispatcher = new RequestDispatcher();
+
+        return dispatcher.waitForResult(listener -> {
+            try {
+                mConnector.untether(iface, callerPkg, listener);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        });
     }
 
     /**
-     * Attempt to both alter the mode of USB and Tethering of USB. WARNING: New client should not
-     * use this API anymore. All clients should use #startTethering or #stopTethering which
-     * encapsulate proper entitlement logic. If the API is used and an entitlement check is needed,
-     * downstream USB tethering will be enabled but will not have any upstream.
+     * Attempt to both alter the mode of USB and Tethering of USB.
      *
-     * @deprecated
-     * {@hide}
+     * @deprecated New client should not use this API anymore. All clients should use
+     * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is
+     * used and an entitlement check is needed, downstream USB tethering will be enabled but will
+     * not have any upstream.
      */
     @Deprecated
-    public int setUsbTethering(boolean enable) {
-        try {
-            mConnector.setUsbTethering(enable);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return TETHER_ERROR_NO_ERROR;
+    public int setUsbTethering(final boolean enable) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "setUsbTethering caller:" + callerPkg);
+
+        final RequestDispatcher dispatcher = new RequestDispatcher();
+
+        return dispatcher.waitForResult(listener -> {
+            try {
+                mConnector.setUsbTethering(enable, callerPkg, listener);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        });
     }
 
     /**
      * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
      * fails, stopTethering will be called automatically.
      *
-     * {@hide}
      */
     // TODO: improve the usage of ResultReceiver, b/145096122
-    public void startTethering(int type, @NonNull ResultReceiver receiver,
-            boolean showProvisioningUi) {
+    public void startTethering(final int type, @NonNull final ResultReceiver receiver,
+            final boolean showProvisioningUi) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "startTethering caller:" + callerPkg);
+
         try {
-            mConnector.startTethering(type, receiver, showProvisioningUi);
+            mConnector.startTethering(type, receiver, showProvisioningUi, callerPkg);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw new IllegalStateException(e);
         }
     }
 
     /**
      * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
      * applicable.
-     *
-     * {@hide}
      */
-    public void stopTethering(int type) {
-        try {
-            mConnector.stopTethering(type);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
+    public void stopTethering(final int type) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "stopTethering caller:" + callerPkg);
+
+        final RequestDispatcher dispatcher = new RequestDispatcher();
+
+        dispatcher.waitForResult(listener -> {
+            try {
+                mConnector.stopTethering(type, callerPkg, listener);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        });
     }
 
     /**
@@ -256,43 +287,109 @@
      * if it's really needed.
      */
     // TODO: improve the usage of ResultReceiver, b/145096122
-    public void requestLatestTetheringEntitlementResult(int type, @NonNull ResultReceiver receiver,
-            boolean showEntitlementUi) {
+    public void requestLatestTetheringEntitlementResult(final int type,
+            @NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
+
         try {
-            mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
+            mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi,
+                    callerPkg);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw new IllegalStateException(e);
         }
     }
 
     /**
-     * Register tethering event callback.
+     * Start listening to tethering change events. Any new added callback will receive the last
+     * tethering status right away. If callback is registered,
+     * {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
+     * has no upstream or disabled, the argument of callback will be null. The same callback object
+     * cannot be registered twice.
      *
-     * {@hide}
+     * @param executor the executor on which callback will be invoked.
+     * @param callback the callback to be called when tethering has change events.
      */
-    public void registerTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
-        mTetheringEventCallbacks.register(callback);
+    public void registerTetheringEventCallback(@NonNull Executor executor,
+            @NonNull OnTetheringEventCallback callback) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
+
+        synchronized (mTetheringEventCallbacks) {
+            if (!mTetheringEventCallbacks.containsKey(callback)) {
+                throw new IllegalArgumentException("callback was already registered.");
+            }
+            final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+                @Override
+                public void onUpstreamChanged(Network network) throws RemoteException {
+                    executor.execute(() -> {
+                        callback.onUpstreamChanged(network);
+                    });
+                }
+
+                @Override
+                public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
+                        TetherStatesParcel states) {
+                    executor.execute(() -> {
+                        callback.onUpstreamChanged(network);
+                    });
+                }
+
+                @Override
+                public void onCallbackStopped(int errorCode) {
+                    executor.execute(() -> {
+                        throwIfPermissionFailure(errorCode);
+                    });
+                }
+
+                @Override
+                public void onConfigurationChanged(TetheringConfigurationParcel config) { }
+
+                @Override
+                public void onTetherStatesChanged(TetherStatesParcel states) { }
+            };
+            try {
+                mConnector.registerTetheringEventCallback(remoteCallback, callerPkg);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+            mTetheringEventCallbacks.put(callback, remoteCallback);
+        }
     }
 
     /**
-     * Unregister tethering event callback.
+     * Remove tethering event callback previously registered with
+     * {@link #registerTetheringEventCallback}.
      *
-     * {@hide}
+     * @param callback previously registered callback.
      */
-    public void unregisterTetheringEventCallback(@NonNull ITetheringEventCallback callback) {
-        mTetheringEventCallbacks.unregister(callback);
+    public void unregisterTetheringEventCallback(@NonNull final OnTetheringEventCallback callback) {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
+
+        synchronized (mTetheringEventCallbacks) {
+            ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
+            if (remoteCallback == null) {
+                throw new IllegalArgumentException("callback was not registered.");
+            }
+            try {
+                mConnector.unregisterTetheringEventCallback(remoteCallback, callerPkg);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        }
     }
 
     /**
      * Get a more detailed error code after a Tethering or Untethering
      * request asynchronously failed.
      *
-     * {@hide}
+     * @param iface The name of the interface of interest
+     * @return error The error code of the last error tethering or untethering the named
+     *               interface
      */
-    public int getLastTetherError(@NonNull String iface) {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+    public int getLastTetherError(@NonNull final String iface) {
+        mCallback.waitForStarted();
         if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
 
         int i = 0;
@@ -309,12 +406,11 @@
      * USB network interfaces.  If USB tethering is not supported by the
      * device, this list should be empty.
      *
-     * {@hide}
+     * @return an array of 0 or more regular expression Strings defining
+     *        what interfaces are considered tetherable usb interfaces.
      */
     public @NonNull String[] getTetherableUsbRegexs() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         return mTetheringConfiguration.tetherableUsbRegexs;
     }
 
@@ -323,12 +419,11 @@
      * Wifi network interfaces.  If Wifi tethering is not supported by the
      * device, this list should be empty.
      *
-     * {@hide}
+     * @return an array of 0 or more regular expression Strings defining
+     *        what interfaces are considered tetherable wifi interfaces.
      */
     public @NonNull String[] getTetherableWifiRegexs() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         return mTetheringConfiguration.tetherableWifiRegexs;
     }
 
@@ -337,12 +432,11 @@
      * Bluetooth network interfaces.  If Bluetooth tethering is not supported by the
      * device, this list should be empty.
      *
-     * {@hide}
+     * @return an array of 0 or more regular expression Strings defining
+     *        what interfaces are considered tetherable bluetooth interfaces.
      */
     public @NonNull String[] getTetherableBluetoothRegexs() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         return mTetheringConfiguration.tetherableBluetoothRegexs;
     }
 
@@ -350,40 +444,42 @@
      * Get the set of tetherable, available interfaces.  This list is limited by
      * device configuration and current interface existence.
      *
-     * {@hide}
+     * @return an array of 0 or more Strings of tetherable interface names.
      */
     public @NonNull String[] getTetherableIfaces() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         if (mTetherStatesParcel == null) return new String[0];
+
         return mTetherStatesParcel.availableList;
     }
 
     /**
      * Get the set of tethered interfaces.
      *
-     * {@hide}
+     * @return an array of 0 or more String of currently tethered interface names.
      */
     public @NonNull String[] getTetheredIfaces() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         if (mTetherStatesParcel == null) return new String[0];
+
         return mTetherStatesParcel.tetheredList;
     }
 
     /**
      * Get the set of interface names which attempted to tether but
-     * failed.
+     * failed.  Re-attempting to tether may cause them to reset to the Tethered
+     * state.  Alternatively, causing the interface to be destroyed and recreated
+     * may cause them to reset to the available state.
+     * {@link ConnectivityManager#getLastTetherError} can be used to get more
+     * information on the cause of the errors.
      *
-     * {@hide}
+     * @return an array of 0 or more String indicating the interface names
+     *        which failed to tether.
      */
     public @NonNull String[] getTetheringErroredIfaces() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         if (mTetherStatesParcel == null) return new String[0];
+
         return mTetherStatesParcel.erroredIfaceList;
     }
 
@@ -391,123 +487,49 @@
      * Get the set of tethered dhcp ranges.
      *
      * @deprecated This API just return the default value which is not used in DhcpServer.
-     * {@hide}
      */
     @Deprecated
     public @NonNull String[] getTetheredDhcpRanges() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
+        mCallback.waitForStarted();
         return mTetheringConfiguration.legacyDhcpRanges;
     }
 
     /**
-     * Check if the device allows for tethering.
+     * Check if the device allows for tethering.  It may be disabled via
+     * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
+     * due to device configuration.
      *
-     * {@hide}
+     * @return a boolean - {@code true} indicating Tethering is supported.
      */
-    public boolean hasTetherableConfiguration() {
-        if (!mCallback.awaitCallbackCreation()) {
-            throw new NullPointerException("callback was not ready yet");
-        }
-        final boolean hasDownstreamConfiguration =
-                (mTetheringConfiguration.tetherableUsbRegexs.length != 0)
-                || (mTetheringConfiguration.tetherableWifiRegexs.length != 0)
-                || (mTetheringConfiguration.tetherableBluetoothRegexs.length != 0);
-        final boolean hasUpstreamConfiguration =
-                (mTetheringConfiguration.preferredUpstreamIfaceTypes.length != 0)
-                || mTetheringConfiguration.chooseUpstreamAutomatically;
+    public boolean isTetheringSupported() {
+        final String callerPkg = mContext.getOpPackageName();
 
-        return hasDownstreamConfiguration && hasUpstreamConfiguration;
+        final RequestDispatcher dispatcher = new RequestDispatcher();
+        final int ret = dispatcher.waitForResult(listener -> {
+            try {
+                mConnector.isTetheringSupported(callerPkg, listener);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        });
+
+        return ret == TETHER_ERROR_NO_ERROR;
     }
 
     /**
-     * Log a message in the local log.
+     * Stop all active tethering.
      */
-    private void log(@NonNull String message) {
-        synchronized (mLog) {
-            mLog.log(message);
-        }
-    }
+    public void stopAllTethering() {
+        final String callerPkg = mContext.getOpPackageName();
+        Log.i(TAG, "stopAllTethering caller:" + callerPkg);
 
-    /**
-     * Log a condition that should never happen.
-     */
-    private void logWtf(@NonNull String message, @Nullable Throwable e) {
-        Slog.wtf(TAG, message);
-        synchronized (mLog) {
-            mLog.e(message, e);
-        }
-    }
-
-    /**
-     * Log a ERROR level message in the local and system logs.
-     */
-    private void loge(@NonNull String message, @Nullable Throwable e) {
-        synchronized (mLog) {
-            mLog.e(message, e);
-        }
-    }
-
-    /**
-     * Log a INFO level message in the local and system logs.
-     */
-    private void logi(@NonNull String message) {
-        synchronized (mLog) {
-            mLog.i(message);
-        }
-    }
-
-    /**
-     * Dump TetheringManager logs to the specified {@link PrintWriter}.
-     */
-    public void dump(@NonNull PrintWriter pw) {
-        // dump is thread-safe on SharedLog
-        mLog.dump(null, pw, null);
-
-        pw.print("subId: ");
-        pw.println(mTetheringConfiguration.subId);
-
-        dumpStringArray(pw, "tetherableUsbRegexs",
-                mTetheringConfiguration.tetherableUsbRegexs);
-        dumpStringArray(pw, "tetherableWifiRegexs",
-                mTetheringConfiguration.tetherableWifiRegexs);
-        dumpStringArray(pw, "tetherableBluetoothRegexs",
-                mTetheringConfiguration.tetherableBluetoothRegexs);
-
-        pw.print("isDunRequired: ");
-        pw.println(mTetheringConfiguration.isDunRequired);
-
-        pw.print("chooseUpstreamAutomatically: ");
-        pw.println(mTetheringConfiguration.chooseUpstreamAutomatically);
-
-        dumpStringArray(pw, "legacyDhcpRanges", mTetheringConfiguration.legacyDhcpRanges);
-        dumpStringArray(pw, "defaultIPv4DNS", mTetheringConfiguration.defaultIPv4DNS);
-
-        dumpStringArray(pw, "provisioningApp", mTetheringConfiguration.provisioningApp);
-        pw.print("provisioningAppNoUi: ");
-        pw.println(mTetheringConfiguration.provisioningAppNoUi);
-
-        pw.print("enableLegacyDhcpServer: ");
-        pw.println(mTetheringConfiguration.enableLegacyDhcpServer);
-
-        pw.println();
-    }
-
-    private static void dumpStringArray(@NonNull PrintWriter pw, @NonNull String label,
-            @Nullable String[] values) {
-        pw.print(label);
-        pw.print(": ");
-
-        if (values != null) {
-            final StringJoiner sj = new StringJoiner(", ", "[", "]");
-            for (String value : values) sj.add(value);
-
-            pw.print(sj.toString());
-        } else {
-            pw.print("null");
-        }
-
-        pw.println();
+        final RequestDispatcher dispatcher = new RequestDispatcher();
+        dispatcher.waitForResult(listener -> {
+            try {
+                mConnector.stopAllTethering(callerPkg, listener);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+        });
     }
 }
diff --git a/packages/Tethering/jarjar-rules.txt b/packages/Tethering/jarjar-rules.txt
new file mode 100644
index 0000000..dd9eab7
--- /dev/null
+++ b/packages/Tethering/jarjar-rules.txt
@@ -0,0 +1,15 @@
+# These must be kept in sync with the framework-tethering-shared-srcs filegroup.
+# If there are files in that filegroup that do not appear here, the classes in the
+# module will be overwritten by the ones in the framework.
+# Don't jar-jar the entire package because tethering still use some internal classes
+# (like TrafficStatsConstants in com.android.internal.util)
+# TODO: simply these when tethering is built as system_current.
+rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
+rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
+rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
+rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
+rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
+rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
+rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+
+rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags
index 77fc024..1f83a66 100644
--- a/packages/Tethering/proguard.flags
+++ b/packages/Tethering/proguard.flags
@@ -1 +1,9 @@
-#TBD
+# Keep class's integer static field for MessageUtils to parsing their name.
+-keep class com.android.server.connectivity.tethering.Tethering$TetherMasterSM {
+    static final int CMD_*;
+    static final int EVENT_*;
+}
+
+-keepclassmembers class android.net.ip.IpServer {
+    static final int CMD_*;
+}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index ff3d7bc..8fde520 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -30,7 +30,6 @@
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
-import android.net.NetworkStackClient;
 import android.net.RouteInfo;
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
@@ -122,7 +121,7 @@
          * @param state one of STATE_*
          * @param lastError one of ConnectivityManager.TETHER_ERROR_*
          */
-        public void updateInterfaceState(IpServer who, int state, int lastError) {}
+        public void updateInterfaceState(IpServer who, int state, int lastError) { }
 
         /**
          * Notify that |who| has new LinkProperties.
@@ -130,11 +129,11 @@
          * @param who the calling instance of IpServer
          * @param newLp the new LinkProperties to report
          */
-        public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
+        public void updateLinkProperties(IpServer who, LinkProperties newLp) { }
     }
 
     /** Capture IpServer dependencies, for injection. */
-    public static class Dependencies {
+    public abstract static class Dependencies {
         /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
         public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
             return new RouterAdvertisementDaemon(ifParams);
@@ -149,13 +148,9 @@
             return NetdService.getInstance();
         }
 
-        /**
-         * Create a DhcpServer instance to be used by IpServer.
-         */
-        public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
-                DhcpServerCallbacks cb) {
-            NetworkStackClient.getInstance().makeDhcpServer(ifName, params, cb);
-        }
+        /** Create a DhcpServer instance to be used by IpServer. */
+        public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
+                DhcpServerCallbacks cb);
     }
 
     private static final int BASE_IFACE              = Protocol.BASE_TETHERING + 100;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
index edfe3ca..9305414 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -21,7 +21,6 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.net.NetworkState;
 import android.net.RouteInfo;
 import android.net.ip.IpServer;
 import android.net.util.NetworkConstants;
@@ -72,7 +71,7 @@
     private final LinkedList<Downstream> mActiveDownstreams;
     private final byte[] mUniqueLocalPrefix;
     private short mNextSubnetId;
-    private NetworkState mUpstreamNetworkState;
+    private UpstreamNetworkState mUpstreamNetworkState;
 
     public IPv6TetheringCoordinator(ArrayList<IpServer> notifyList, SharedLog log) {
         mNotifyList = notifyList;
@@ -115,11 +114,11 @@
     }
 
     /**
-     * Call when upstream NetworkState may be changed.
-     * If upstream has ipv6 for tethering, update this new NetworkState
+     * Call when UpstreamNetworkState may be changed.
+     * If upstream has ipv6 for tethering, update this new UpstreamNetworkState
      * to IpServer. Otherwise stop ipv6 tethering on downstream interfaces.
      */
-    public void updateUpstreamNetworkState(NetworkState ns) {
+    public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
         if (VDBG) {
             Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
         }
@@ -144,18 +143,15 @@
         }
     }
 
-    private void setUpstreamNetworkState(NetworkState ns) {
+    private void setUpstreamNetworkState(UpstreamNetworkState ns) {
         if (ns == null) {
             mUpstreamNetworkState = null;
         } else {
             // Make a deep copy of the parts we need.
-            mUpstreamNetworkState = new NetworkState(
-                    null,
+            mUpstreamNetworkState = new UpstreamNetworkState(
                     new LinkProperties(ns.linkProperties),
                     new NetworkCapabilities(ns.networkCapabilities),
-                    new Network(ns.network),
-                    null,
-                    null);
+                    new Network(ns.network));
         }
 
         mLog.log("setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
@@ -295,14 +291,11 @@
         return in6addr;
     }
 
-    private static String toDebugString(NetworkState ns) {
+    private static String toDebugString(UpstreamNetworkState ns) {
         if (ns == null) {
-            return "NetworkState{null}";
+            return "UpstreamNetworkState{null}";
         }
-        return String.format("NetworkState{%s, %s, %s}",
-                ns.network,
-                ns.networkCapabilities,
-                ns.linkProperties);
+        return ns.toString();
     }
 
     private static void stopIPv6TetheringOn(IpServer ipServer) {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 7c78ef8..3116321 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -16,6 +16,7 @@
 
 package com.android.server.connectivity.tethering;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.hardware.usb.UsbManager.USB_CONFIGURED;
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
@@ -63,13 +64,12 @@
 import android.net.INetd;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
-import android.net.ITetherInternalCallback;
+import android.net.ITetheringEventCallback;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkInfo;
-import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.TetherStatesParcel;
 import android.net.TetheringConfigurationParcel;
@@ -89,6 +89,7 @@
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -103,13 +104,12 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
-import com.android.tethering.R;
+import com.android.networkstack.tethering.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -162,6 +162,8 @@
     }
 
     private final SharedLog mLog = new SharedLog(TAG);
+    private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
+            new RemoteCallbackList<>();
 
     // used to synchronize public access to members
     private final Object mPublicSync;
@@ -188,8 +190,8 @@
     private final NetdCallback mNetdCallback;
     private final UserRestrictionActionListener mTetheringRestriction;
     private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
-    // All the usage of mTetherInternalCallback should run in the same thread.
-    private ITetherInternalCallback mTetherInternalCallback = null;
+    // All the usage of mTetheringEventCallback should run in the same thread.
+    private ITetheringEventCallback mTetheringEventCallback = null;
 
     private volatile TetheringConfiguration mConfig;
     private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -573,6 +575,11 @@
         }
     }
 
+    boolean isTetherProvisioningRequired() {
+        final TetheringConfiguration cfg = mConfig;
+        return mEntitlementMgr.isTetherProvisioningRequired(cfg);
+    }
+
     // TODO: Figure out how to update for local hotspot mode interfaces.
     private void sendTetherStateChangedBroadcast() {
         if (!mDeps.isTetheringSupported()) return;
@@ -588,7 +595,7 @@
         boolean bluetoothTethered = false;
 
         final TetheringConfiguration cfg = mConfig;
-        final TetherStatesParcel mTetherStatesParcel = new TetherStatesParcel();
+        mTetherStatesParcel = new TetherStatesParcel();
 
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
@@ -1144,7 +1151,7 @@
 
     // Needed because the canonical source of upstream truth is just the
     // upstream interface set, |mCurrentUpstreamIfaceSet|.
-    private boolean pertainsToCurrentUpstream(NetworkState ns) {
+    private boolean pertainsToCurrentUpstream(UpstreamNetworkState ns) {
         if (ns != null && ns.linkProperties != null && mCurrentUpstreamIfaceSet != null) {
             for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
                 if (mCurrentUpstreamIfaceSet.ifnames.contains(ifname)) {
@@ -1312,7 +1319,7 @@
             maybeDunSettingChanged();
 
             final TetheringConfiguration config = mConfig;
-            final NetworkState ns = (config.chooseUpstreamAutomatically)
+            final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically)
                     ? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
                     : mUpstreamNetworkMonitor.selectPreferredUpstreamType(
                             config.preferredUpstreamIfaceTypes);
@@ -1333,7 +1340,7 @@
             }
         }
 
-        protected void setUpstreamNetwork(NetworkState ns) {
+        protected void setUpstreamNetwork(UpstreamNetworkState ns) {
             InterfaceSet ifaces = null;
             if (ns != null) {
                 // Find the interface with the default IPv4 route. It may be the
@@ -1349,7 +1356,7 @@
             }
             notifyDownstreamsOfNewUpstreamIface(ifaces);
             if (ns != null && pertainsToCurrentUpstream(ns)) {
-                // If we already have NetworkState for this network update it immediately.
+                // If we already have UpstreamNetworkState for this network update it immediately.
                 handleNewUpstreamNetworkState(ns);
             } else if (mCurrentUpstreamIfaceSet == null) {
                 // There are no available upstream networks.
@@ -1386,7 +1393,7 @@
             }
         }
 
-        protected void handleNewUpstreamNetworkState(NetworkState ns) {
+        protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
             mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
             mOffload.updateUpstreamNetworkState(ns);
         }
@@ -1450,7 +1457,7 @@
                 return;
             }
 
-            final NetworkState ns = (NetworkState) o;
+            final UpstreamNetworkState ns = (UpstreamNetworkState) o;
 
             if (ns == null || !pertainsToCurrentUpstream(ns)) {
                 // TODO: In future, this is where upstream evaluation and selection
@@ -1720,7 +1727,7 @@
                 mOffloadController.stop();
             }
 
-            public void updateUpstreamNetworkState(NetworkState ns) {
+            public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
                 mOffloadController.setUpstreamLinkProperties(
                         (ns != null) ? ns.linkProperties : null);
             }
@@ -1796,47 +1803,67 @@
     }
 
     /** Register tethering event callback */
-    void registerTetherInternalCallback(ITetherInternalCallback callback) {
+    void registerTetheringEventCallback(ITetheringEventCallback callback) {
         mHandler.post(() -> {
-            mTetherInternalCallback = callback;
+            mTetheringEventCallbacks.register(callback);
             try {
-                mTetherInternalCallback.onCallbackCreated(mTetherUpstream,
-                        mConfig.toStableParcelable(), mTetherStatesParcel);
+                callback.onCallbackStarted(mTetherUpstream, mConfig.toStableParcelable(),
+                        mTetherStatesParcel);
             } catch (RemoteException e) {
                 // Not really very much to do here.
             }
         });
     }
 
-    private void reportUpstreamChanged(Network network) {
-        // Don't need to synchronized mTetherInternalCallback because all the usage of this variable
-        // should run at the same thread.
-        if (mTetherInternalCallback == null) return;
+    /** Unregister tethering event callback */
+    void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+        mHandler.post(() -> {
+            mTetheringEventCallbacks.unregister(callback);
+        });
+    }
 
+    private void reportUpstreamChanged(Network network) {
+        final int length = mTetheringEventCallbacks.beginBroadcast();
         try {
-            mTetherInternalCallback.onUpstreamChanged(network);
-        } catch (RemoteException e) {
-            // Not really very much to do here.
+            for (int i = 0; i < length; i++) {
+                try {
+                    mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
+                } catch (RemoteException e) {
+                    // Not really very much to do here.
+                }
+            }
+        } finally {
+            mTetheringEventCallbacks.finishBroadcast();
         }
     }
 
     private void reportConfigurationChanged(TetheringConfigurationParcel config) {
-        if (mTetherInternalCallback == null) return;
-
+        final int length = mTetheringEventCallbacks.beginBroadcast();
         try {
-            mTetherInternalCallback.onConfigurationChanged(config);
-        } catch (RemoteException e) {
-            // Not really very much to do here.
+            for (int i = 0; i < length; i++) {
+                try {
+                    mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config);
+                } catch (RemoteException e) {
+                    // Not really very much to do here.
+                }
+            }
+        } finally {
+            mTetheringEventCallbacks.finishBroadcast();
         }
     }
 
     private void reportTetherStateChanged(TetherStatesParcel states) {
-        if (mTetherInternalCallback == null) return;
-
+        final int length = mTetheringEventCallbacks.beginBroadcast();
         try {
-            mTetherInternalCallback.onTetherStatesChanged(states);
-        } catch (RemoteException e) {
-            // Not really very much to do here.
+            for (int i = 0; i < length; i++) {
+                try {
+                    mTetheringEventCallbacks.getBroadcastItem(i).onTetherStatesChanged(states);
+                } catch (RemoteException e) {
+                    // Not really very much to do here.
+                }
+            }
+        } finally {
+            mTetheringEventCallbacks.finishBroadcast();
         }
     }
 
@@ -1844,7 +1871,11 @@
         // Binder.java closes the resource for us.
         @SuppressWarnings("resource")
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump.");
+            return;
+        }
 
         pw.println("Tethering:");
         pw.increaseIndent();
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
index 0ba8412..b16b329 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -39,7 +39,7 @@
  *
  * @hide
  */
-public class TetheringDependencies {
+public abstract class TetheringDependencies {
     /**
      * Get a reference to the offload hardware interface to be used by tethering.
      */
@@ -66,9 +66,7 @@
     /**
      * Get dependencies to be used by IpServer.
      */
-    public IpServer.Dependencies getIpServerDependencies() {
-        return new IpServer.Dependencies();
-    }
+    public abstract IpServer.Dependencies getIpServerDependencies();
 
     /**
      * Indicates whether tethering is supported on the device.
@@ -80,9 +78,7 @@
     /**
      * Get the NetworkRequest that should be fulfilled by the default network.
      */
-    public NetworkRequest getDefaultNetworkRequest() {
-        return null;
-    }
+    public abstract NetworkRequest getDefaultNetworkRequest();
 
     /**
      * Get a reference to the EntitlementManager to be used by tethering.
@@ -138,14 +134,10 @@
     /**
      * Get tethering thread looper.
      */
-    public Looper getTetheringLooper() {
-        return null;
-    }
+    public abstract Looper getTetheringLooper();
 
     /**
      *  Get Context of TetheringSerice.
      */
-    public Context getContext() {
-        return null;
-    }
+    public abstract Context getContext();
 }
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
index 0ef3805..6334c20 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringInterfaceUtils.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
-import android.net.NetworkState;
 import android.net.RouteInfo;
 import android.net.util.InterfaceSet;
 
@@ -35,7 +34,7 @@
      * Get upstream interfaces for tethering based on default routes for IPv4/IPv6.
      * @return null if there is no usable interface, or a set of at least one interface otherwise.
      */
-    public static @Nullable InterfaceSet getTetheringInterfaces(NetworkState ns) {
+    public static @Nullable InterfaceSet getTetheringInterfaces(UpstreamNetworkState ns) {
         if (ns == null) {
             return null;
         }
@@ -51,7 +50,7 @@
      * Get the upstream interface for IPv6 tethering.
      * @return null if there is no usable interface, or the interface name otherwise.
      */
-    public static @Nullable String getIPv6Interface(NetworkState ns) {
+    public static @Nullable String getIPv6Interface(UpstreamNetworkState ns) {
         // Broadly speaking:
         //
         //     [1] does the upstream have an IPv6 default route?
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index 456f2f7..ba30845 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -16,20 +16,36 @@
 
 package com.android.server.connectivity.tethering;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
+
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
-import android.net.ITetherInternalCallback;
+import android.net.IIntResultListener;
+import android.net.INetworkStackConnector;
 import android.net.ITetheringConnector;
+import android.net.ITetheringEventCallback;
 import android.net.NetworkRequest;
+import android.net.dhcp.DhcpServerCallbacks;
+import android.net.dhcp.DhcpServingParamsParcel;
+import android.net.ip.IpServer;
 import android.net.util.SharedLog;
+import android.os.Binder;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserManager;
 import android.provider.Settings;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -52,6 +68,7 @@
     private Context mContext;
     private TetheringDependencies mDeps;
     private Tethering mTethering;
+    private UserManager mUserManager;
 
     @Override
     public void onCreate() {
@@ -59,6 +76,7 @@
         mDeps = getTetheringDependencies();
         mContext = mDeps.getContext();
         mTethering = makeTethering(mDeps);
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
     }
 
     /**
@@ -74,7 +92,7 @@
      */
     private synchronized IBinder makeConnector() {
         if (mConnector == null) {
-            mConnector = new TetheringConnector(mTethering);
+            mConnector = new TetheringConnector(mTethering, TetheringService.this);
         }
         return mConnector;
     }
@@ -87,55 +105,197 @@
     }
 
     private static class TetheringConnector extends ITetheringConnector.Stub {
-        private final Tethering mService;
+        private final TetheringService mService;
+        private final Tethering mTethering;
 
-        TetheringConnector(Tethering tether) {
-            mService = tether;
+        TetheringConnector(Tethering tether, TetheringService service) {
+            mTethering = tether;
+            mService = service;
         }
 
         @Override
-        public void tether(String iface) {
-            mService.tether(iface);
+        public void tether(String iface, String callerPkg, IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+            try {
+                listener.onResult(mTethering.tether(iface));
+            } catch (RemoteException e) { }
         }
 
         @Override
-        public void untether(String iface) {
-            mService.untether(iface);
+        public void untether(String iface, String callerPkg, IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+            try {
+                listener.onResult(mTethering.untether(iface));
+            } catch (RemoteException e) { }
         }
 
         @Override
-        public void setUsbTethering(boolean enable) {
-            mService.setUsbTethering(enable);
+        public void setUsbTethering(boolean enable, String callerPkg, IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+            try {
+                listener.onResult(mTethering.setUsbTethering(enable));
+            } catch (RemoteException e) { }
         }
 
         @Override
-        public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
-            mService.startTethering(type, receiver, showProvisioningUi);
+        public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
+                String callerPkg) {
+            if (checkAndNotifyCommonError(callerPkg, receiver)) return;
+
+            mTethering.startTethering(type, receiver, showProvisioningUi);
         }
 
         @Override
-        public void stopTethering(int type) {
-            mService.stopTethering(type);
+        public void stopTethering(int type, String callerPkg, IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+            try {
+                mTethering.stopTethering(type);
+                listener.onResult(TETHER_ERROR_NO_ERROR);
+            } catch (RemoteException e) { }
         }
 
         @Override
         public void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
-                boolean showEntitlementUi) {
-            mService.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
+                boolean showEntitlementUi, String callerPkg) {
+            if (checkAndNotifyCommonError(callerPkg, receiver)) return;
+
+            mTethering.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
         }
 
         @Override
-        public void registerTetherInternalCallback(ITetherInternalCallback callback) {
-            mService.registerTetherInternalCallback(callback);
+        public void registerTetheringEventCallback(ITetheringEventCallback callback,
+                String callerPkg) {
+            try {
+                if (!mService.hasTetherAccessPermission()) {
+                    callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
+                    return;
+                }
+                mTethering.registerTetheringEventCallback(callback);
+            } catch (RemoteException e) { }
         }
+
+        @Override
+        public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
+                String callerPkg) {
+            try {
+                if (!mService.hasTetherAccessPermission()) {
+                    callback.onCallbackStopped(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
+                    return;
+                }
+                mTethering.unregisterTetheringEventCallback(callback);
+            } catch (RemoteException e) { }
+        }
+
+        @Override
+        public void stopAllTethering(String callerPkg, IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+            try {
+                mTethering.untetherAll();
+                listener.onResult(TETHER_ERROR_NO_ERROR);
+            } catch (RemoteException e) { }
+        }
+
+        @Override
+        public void isTetheringSupported(String callerPkg, IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
+
+            try {
+                listener.onResult(TETHER_ERROR_NO_ERROR);
+            } catch (RemoteException e) { }
+        }
+
+        @Override
+        protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
+                    @Nullable String[] args) {
+            mTethering.dump(fd, writer, args);
+        }
+
+        private boolean checkAndNotifyCommonError(String callerPkg, IIntResultListener listener) {
+            try {
+                if (!mService.hasTetherChangePermission(callerPkg)) {
+                    listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+                    return true;
+                }
+                if (!mService.isTetheringSupported()) {
+                    listener.onResult(TETHER_ERROR_UNSUPPORTED);
+                    return true;
+                }
+            } catch (RemoteException e) {
+                return true;
+            }
+
+            return false;
+        }
+
+        private boolean checkAndNotifyCommonError(String callerPkg, ResultReceiver receiver) {
+            if (!mService.hasTetherChangePermission(callerPkg)) {
+                receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
+                return true;
+            }
+            if (!mService.isTetheringSupported()) {
+                receiver.send(TETHER_ERROR_UNSUPPORTED, null);
+                return true;
+            }
+
+            return false;
+        }
+
     }
 
-    @Override
-    protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
-                @Nullable String[] args) {
-        mTethering.dump(fd, writer, args);
+    // if ro.tether.denied = true we default to no tethering
+    // gservices could set the secure setting to 1 though to enable it on a build where it
+    // had previously been turned off.
+    private boolean isTetheringSupported() {
+        final int defaultVal =
+                SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
+        final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
+        final boolean tetherEnabledInSettings = tetherSupported
+                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
+
+        return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
     }
 
+    private boolean hasTetherChangePermission(String callerPkg) {
+        if (checkCallingOrSelfPermission(
+                android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
+            return true;
+        }
+
+        if (mTethering.isTetherProvisioningRequired()) return false;
+
+
+        int uid = Binder.getCallingUid();
+        // If callerPkg's uid is not same as Binder.getCallingUid(),
+        // checkAndNoteWriteSettingsOperation will return false and the operation will be denied.
+        if (Settings.checkAndNoteWriteSettingsOperation(mContext, uid, callerPkg,
+                false /* throwException */)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private boolean hasTetherAccessPermission() {
+        if (checkCallingOrSelfPermission(
+                android.Manifest.permission.TETHER_PRIVILEGED) == PERMISSION_GRANTED) {
+            return true;
+        }
+
+        if (checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_NETWORK_STATE) == PERMISSION_GRANTED) {
+            return true;
+        }
+
+        return false;
+    }
+
+
     /**
      * An injection method for testing.
      */
@@ -159,20 +319,55 @@
 
                 @Override
                 public boolean isTetheringSupported() {
-                    int defaultVal =
-                            SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
-                    boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
-                            Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
-                    return tetherSupported;
+                    return TetheringService.this.isTetheringSupported();
                 }
 
                 @Override
                 public Context getContext() {
                     return TetheringService.this;
                 }
+
+                @Override
+                public IpServer.Dependencies getIpServerDependencies() {
+                    return new IpServer.Dependencies() {
+                        @Override
+                        public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
+                                DhcpServerCallbacks cb) {
+                            try {
+                                final INetworkStackConnector service = getNetworkStackConnector();
+                                if (service == null) return;
+
+                                service.makeDhcpServer(ifName, params, cb);
+                            } catch (RemoteException e) {
+                                e.rethrowFromSystemServer();
+                            }
+                        }
+                    };
+                }
+
+                // TODO: replace this by NetworkStackClient#getRemoteConnector after refactoring
+                // networkStackClient.
+                static final int NETWORKSTACK_TIMEOUT_MS = 60_000;
+                private INetworkStackConnector getNetworkStackConnector() {
+                    IBinder connector;
+                    try {
+                        final long before = System.currentTimeMillis();
+                        while ((connector = ServiceManager.getService(
+                                Context.NETWORK_STACK_SERVICE)) == null) {
+                            if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
+                                Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
+                                return null;
+                            }
+                            Thread.sleep(200);
+                        }
+                    } catch (InterruptedException e) {
+                        Log.wtf(TAG, "Interrupted, fail to get INetworkStackConnector");
+                        return null;
+                    }
+                    return INetworkStackConnector.Stub.asInterface(connector);
+                }
             };
         }
-
         return mDeps;
     }
 }
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 9769596..dc38c49a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -32,7 +32,6 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
-import android.net.NetworkState;
 import android.net.util.PrefixUtils;
 import android.net.util.SharedLog;
 import android.os.Handler;
@@ -90,7 +89,7 @@
     private final StateMachine mTarget;
     private final Handler mHandler;
     private final int mWhat;
-    private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
+    private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>();
     private HashSet<IpPrefix> mLocalPrefixes;
     private ConnectivityManager mCM;
     private EntitlementManager mEntitlementMgr;
@@ -236,7 +235,7 @@
     /**
      * Select the first available network from |perferredTypes|.
      */
-    public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
+    public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
         final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
                 mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
 
@@ -274,8 +273,8 @@
      * preferred upstream would be DUN otherwise preferred upstream is the same as default network.
      * Returns null if no current upstream is available.
      */
-    public NetworkState getCurrentPreferredUpstream() {
-        final NetworkState dfltState = (mDefaultInternetNetwork != null)
+    public UpstreamNetworkState getCurrentPreferredUpstream() {
+        final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
                 ? mNetworkMap.get(mDefaultInternetNetwork)
                 : null;
         if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
@@ -312,11 +311,11 @@
         if (mNetworkMap.containsKey(network)) return;
 
         if (VDBG) Log.d(TAG, "onAvailable for " + network);
-        mNetworkMap.put(network, new NetworkState(null, null, null, network, null, null));
+        mNetworkMap.put(network, new UpstreamNetworkState(null, null, network));
     }
 
     private void handleNetCap(Network network, NetworkCapabilities newNc) {
-        final NetworkState prev = mNetworkMap.get(network);
+        final UpstreamNetworkState prev = mNetworkMap.get(network);
         if (prev == null || newNc.equals(prev.networkCapabilities)) {
             // Ignore notifications about networks for which we have not yet
             // received onAvailable() (should never happen) and any duplicate
@@ -336,15 +335,15 @@
             mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
         }
 
-        mNetworkMap.put(network, new NetworkState(
-                null, prev.linkProperties, newNc, network, null, null));
+        mNetworkMap.put(network, new UpstreamNetworkState(
+                prev.linkProperties, newNc, network));
         // TODO: If sufficient information is available to select a more
         // preferable upstream, do so now and notify the target.
         notifyTarget(EVENT_ON_CAPABILITIES, network);
     }
 
     private void handleLinkProp(Network network, LinkProperties newLp) {
-        final NetworkState prev = mNetworkMap.get(network);
+        final UpstreamNetworkState prev = mNetworkMap.get(network);
         if (prev == null || newLp.equals(prev.linkProperties)) {
             // Ignore notifications about networks for which we have not yet
             // received onAvailable() (should never happen) and any duplicate
@@ -357,8 +356,8 @@
                     network, newLp));
         }
 
-        mNetworkMap.put(network, new NetworkState(
-                null, newLp, prev.networkCapabilities, network, null, null));
+        mNetworkMap.put(network, new UpstreamNetworkState(
+                newLp, prev.networkCapabilities, network));
         // TODO: If sufficient information is available to select a more
         // preferable upstream, do so now and notify the target.
         notifyTarget(EVENT_ON_LINKPROPERTIES, network);
@@ -509,11 +508,11 @@
 
     private static class TypeStatePair {
         public int type = TYPE_NONE;
-        public NetworkState ns = null;
+        public UpstreamNetworkState ns = null;
     }
 
     private static TypeStatePair findFirstAvailableUpstreamByType(
-            Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes,
+            Iterable<UpstreamNetworkState> netStates, Iterable<Integer> preferredTypes,
             boolean isCellularUpstreamPermitted) {
         final TypeStatePair result = new TypeStatePair();
 
@@ -532,7 +531,7 @@
 
             nc.setSingleUid(Process.myUid());
 
-            for (NetworkState value : netStates) {
+            for (UpstreamNetworkState value : netStates) {
                 if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
                     continue;
                 }
@@ -546,10 +545,10 @@
         return result;
     }
 
-    private static HashSet<IpPrefix> allLocalPrefixes(Iterable<NetworkState> netStates) {
+    private static HashSet<IpPrefix> allLocalPrefixes(Iterable<UpstreamNetworkState> netStates) {
         final HashSet<IpPrefix> prefixSet = new HashSet<>();
 
-        for (NetworkState ns : netStates) {
+        for (UpstreamNetworkState ns : netStates) {
             final LinkProperties lp = ns.linkProperties;
             if (lp == null) continue;
             prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp));
@@ -563,7 +562,7 @@
         return Integer.toString(nc.getSignalStrength());
     }
 
-    private static boolean isCellular(NetworkState ns) {
+    private static boolean isCellular(UpstreamNetworkState ns) {
         return (ns != null) && isCellular(ns.networkCapabilities);
     }
 
@@ -572,18 +571,19 @@
                && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
     }
 
-    private static boolean hasCapability(NetworkState ns, int netCap) {
+    private static boolean hasCapability(UpstreamNetworkState ns, int netCap) {
         return (ns != null) && (ns.networkCapabilities != null)
                && ns.networkCapabilities.hasCapability(netCap);
     }
 
-    private static boolean isNetworkUsableAndNotCellular(NetworkState ns) {
+    private static boolean isNetworkUsableAndNotCellular(UpstreamNetworkState ns) {
         return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null)
                && !isCellular(ns.networkCapabilities);
     }
 
-    private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) {
-        for (NetworkState ns : netStates) {
+    private static UpstreamNetworkState findFirstDunNetwork(
+            Iterable<UpstreamNetworkState> netStates) {
+        for (UpstreamNetworkState ns : netStates) {
             if (isCellular(ns) && hasCapability(ns, NET_CAPABILITY_DUN)) return ns;
         }
 
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java
new file mode 100644
index 0000000..68bb837
--- /dev/null
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkState.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.connectivity.tethering;
+
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Snapshot of tethering upstream network state.
+ */
+public class UpstreamNetworkState {
+    /** {@link LinkProperties}. */
+    public final LinkProperties linkProperties;
+    /** {@link NetworkCapabilities}. */
+    public final NetworkCapabilities networkCapabilities;
+    /** {@link Network}. */
+    public final Network network;
+
+    /** Constructs a new UpstreamNetworkState. */
+    public UpstreamNetworkState(LinkProperties linkProperties,
+            NetworkCapabilities networkCapabilities, Network network) {
+        this.linkProperties = linkProperties;
+        this.networkCapabilities = networkCapabilities;
+        this.network = network;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return String.format("UpstreamNetworkState{%s, %s, %s}",
+                network == null ? "null" : network,
+                networkCapabilities == null ? "null" : networkCapabilities,
+                linkProperties == null ? "null" : linkProperties);
+    }
+}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 5b018df..81a0548 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -33,10 +33,12 @@
         "android.test.runner",
         "android.test.base",
         "android.test.mock",
+        "framework-tethering",
     ],
     jni_libs: [
         // For mockito extended
         "libdexmakerjvmtiagent",
         "libstaticjvmtiagent",
     ],
+    jarjar_rules: "jarjar-rules.txt",
 }
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
index 049ff6d..0a1cdd3 100644
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -14,13 +14,13 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.tethering.tests.unit">
+          package="com.android.networkstack.tethering.tests.unit">
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.tethering.tests.unit"
+        android:targetPackage="com.android.networkstack.tethering.tests.unit"
         android:label="Tethering service tests">
     </instrumentation>
 </manifest>
diff --git a/packages/Tethering/tests/unit/jarjar-rules.txt b/packages/Tethering/tests/unit/jarjar-rules.txt
new file mode 100644
index 0000000..64fdebd
--- /dev/null
+++ b/packages/Tethering/tests/unit/jarjar-rules.txt
@@ -0,0 +1,11 @@
+# Don't jar-jar the entire package because this test use some
+# internal classes (like ArrayUtils in com.android.internal.util)
+rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
+rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
+rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
+rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
+rule com.android.internal.util.Preconditions* com.android.networkstack.tethering.util.Preconditions@1
+rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
+rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
+
+rule android.net.LocalLog* com.android.networkstack.tethering.LocalLog@1
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 0273ed3..0bc8c79 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -27,7 +27,6 @@
 import static android.net.ConnectivityManager.TETHERING_WIFI;
 import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
@@ -72,7 +71,7 @@
 import android.net.INetd;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
-import android.net.ITetherInternalCallback;
+import android.net.ITetheringEventCallback;
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
@@ -81,7 +80,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
-import android.net.NetworkState;
+import android.net.NetworkRequest;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.TetherStatesParcel;
@@ -167,6 +166,7 @@
     @Mock private IDhcpServer mDhcpServer;
     @Mock private INetd mNetd;
     @Mock private UserManager mUserManager;
+    @Mock private NetworkRequest mNetworkRequest;
 
     private final MockIpServerDependencies mIpServerDependencies =
             spy(new MockIpServerDependencies());
@@ -311,6 +311,11 @@
         }
 
         @Override
+        public NetworkRequest getDefaultNetworkRequest() {
+            return mNetworkRequest;
+        }
+
+        @Override
         public boolean isTetheringSupported() {
             mIsTetheringSupportedCalls++;
             return true;
@@ -353,10 +358,8 @@
         }
     }
 
-    private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
-            boolean with464xlat) {
-        final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
-        info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+    private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
+            boolean withIPv6, boolean with464xlat) {
         final LinkProperties prop = new LinkProperties();
         prop.setInterfaceName(TEST_MOBILE_IFNAME);
 
@@ -386,22 +389,22 @@
 
         final NetworkCapabilities capabilities = new NetworkCapabilities()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
+        return new UpstreamNetworkState(prop, capabilities, new Network(100));
     }
 
-    private static NetworkState buildMobileIPv4UpstreamState() {
+    private static UpstreamNetworkState buildMobileIPv4UpstreamState() {
         return buildMobileUpstreamState(true, false, false);
     }
 
-    private static NetworkState buildMobileIPv6UpstreamState() {
+    private static UpstreamNetworkState buildMobileIPv6UpstreamState() {
         return buildMobileUpstreamState(false, true, false);
     }
 
-    private static NetworkState buildMobileDualStackUpstreamState() {
+    private static UpstreamNetworkState buildMobileDualStackUpstreamState() {
         return buildMobileUpstreamState(true, true, false);
     }
 
-    private static NetworkState buildMobile464xlatUpstreamState() {
+    private static UpstreamNetworkState buildMobile464xlatUpstreamState() {
         return buildMobileUpstreamState(false, true, true);
     }
 
@@ -555,7 +558,7 @@
         verifyNoMoreInteractions(mWifiManager);
     }
 
-    private void prepareUsbTethering(NetworkState upstreamState) {
+    private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
         when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
         when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                 .thenReturn(upstreamState);
@@ -570,7 +573,7 @@
 
     @Test
     public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
-        NetworkState upstreamState = buildMobileIPv4UpstreamState();
+        UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
         prepareUsbTethering(upstreamState);
 
         // This should produce no activity of any kind.
@@ -650,14 +653,14 @@
     /**
      * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
      */
-    private void sendIPv6TetherUpdates(NetworkState upstreamState) {
+    private void sendIPv6TetherUpdates(UpstreamNetworkState upstreamState) {
         // IPv6TetheringCoordinator must have been notified of downstream
         verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
                 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
                 eq(IpServer.STATE_TETHERED));
 
         for (IpServer ipSrv : mTetheringDependencies.mIpv6CoordinatorNotifyList) {
-            NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
+            UpstreamNetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
             ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
                     upstreamState.linkProperties.isIpv6Provisioned()
                             ? ipv6OnlyState.linkProperties
@@ -666,7 +669,7 @@
         mLooper.dispatchAll();
     }
 
-    private void runUsbTethering(NetworkState upstreamState) {
+    private void runUsbTethering(UpstreamNetworkState upstreamState) {
         prepareUsbTethering(upstreamState);
         sendUsbBroadcast(true, true, true);
         mLooper.dispatchAll();
@@ -674,7 +677,7 @@
 
     @Test
     public void workingMobileUsbTethering_IPv4() throws Exception {
-        NetworkState upstreamState = buildMobileIPv4UpstreamState();
+        UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
         runUsbTethering(upstreamState);
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -689,7 +692,7 @@
     public void workingMobileUsbTethering_IPv4LegacyDhcp() {
         Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
         sendConfigurationChanged();
-        final NetworkState upstreamState = buildMobileIPv4UpstreamState();
+        final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
         runUsbTethering(upstreamState);
         sendIPv6TetherUpdates(upstreamState);
 
@@ -698,7 +701,7 @@
 
     @Test
     public void workingMobileUsbTethering_IPv6() throws Exception {
-        NetworkState upstreamState = buildMobileIPv6UpstreamState();
+        UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
         runUsbTethering(upstreamState);
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -711,7 +714,7 @@
 
     @Test
     public void workingMobileUsbTethering_DualStack() throws Exception {
-        NetworkState upstreamState = buildMobileDualStackUpstreamState();
+        UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
         runUsbTethering(upstreamState);
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -726,7 +729,7 @@
 
     @Test
     public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
-        NetworkState upstreamState = buildMobile464xlatUpstreamState();
+        UpstreamNetworkState upstreamState = buildMobile464xlatUpstreamState();
         runUsbTethering(upstreamState);
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
@@ -744,7 +747,7 @@
     @Test
     public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
         // Setup IPv6
-        NetworkState upstreamState = buildMobileIPv6UpstreamState();
+        UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
         runUsbTethering(upstreamState);
 
         verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
@@ -782,7 +785,7 @@
         sendConfigurationChanged();
 
         // Setup IPv6
-        final NetworkState upstreamState = buildMobileIPv6UpstreamState();
+        final UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
         runUsbTethering(upstreamState);
 
         // UpstreamNetworkMonitor should choose upstream automatically
@@ -1039,7 +1042,7 @@
                 expectedInteractionsWithShowNotification);
     }
 
-    private class TestTetherInternalCallback extends ITetherInternalCallback.Stub {
+    private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
         private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
         private final ArrayList<TetheringConfigurationParcel> mTetheringConfigs =
                 new ArrayList<>();
@@ -1100,13 +1103,16 @@
         }
 
         @Override
-        public void onCallbackCreated(Network network, TetheringConfigurationParcel config,
+        public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
                 TetherStatesParcel states) {
             mActualUpstreams.add(network);
             mTetheringConfigs.add(config);
             mTetherStates.add(states);
         }
 
+        @Override
+        public void onCallbackStopped(int errorCode) { }
+
         public void assertNoUpstreamChangeCallback() {
             assertTrue(mActualUpstreams.isEmpty());
         }
@@ -1115,10 +1121,20 @@
             assertTrue(mTetheringConfigs.isEmpty());
         }
 
+        public void assertNoStateChangeCallback() {
+            assertTrue(mTetherStates.isEmpty());
+        }
+
         public void assertStateChangeCallback() {
             assertFalse(mTetherStates.isEmpty());
         }
 
+        public void assertNoCallback() {
+            assertNoUpstreamChangeCallback();
+            assertNoConfigChangeCallback();
+            assertNoStateChangeCallback();
+        }
+
         private void assertTetherConfigParcelEqual(@NonNull TetheringConfigurationParcel actual,
                 @NonNull TetheringConfigurationParcel expect) {
             assertEquals(actual.subId, expect.subId);
@@ -1139,19 +1155,20 @@
     }
 
     @Test
-    public void testRegisterTetherInternalCallback() throws Exception {
-        TestTetherInternalCallback callback = new TestTetherInternalCallback();
+    public void testRegisterTetheringEventCallback() throws Exception {
+        TestTetheringEventCallback callback = new TestTetheringEventCallback();
+        TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
 
         // 1. Register one callback before running any tethering.
-        mTethering.registerTetherInternalCallback(callback);
+        mTethering.registerTetheringEventCallback(callback);
         mLooper.dispatchAll();
         callback.expectUpstreamChanged(new Network[] {null});
         callback.expectConfigurationChanged(
                 mTethering.getTetheringConfiguration().toStableParcelable());
         TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
         assertEquals(tetherState, null);
-        // 2. Enable wifi tethering
-        NetworkState upstreamState = buildMobileDualStackUpstreamState();
+        // 2. Enable wifi tethering.
+        UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
         when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
         when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                 .thenReturn(upstreamState);
@@ -1168,14 +1185,26 @@
         assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
         callback.expectUpstreamChanged(upstreamState.network);
 
-        // 3. Disable wifi tethering.
+        // 3. Register second callback.
+        mTethering.registerTetheringEventCallback(callback2);
+        mLooper.dispatchAll();
+        callback2.expectUpstreamChanged(upstreamState.network);
+        callback2.expectConfigurationChanged(
+                mTethering.getTetheringConfiguration().toStableParcelable());
+        tetherState = callback2.pollTetherStatesChanged();
+        assertEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
+
+        // 4. Unregister first callback and disable wifi tethering
+        mTethering.unregisterTetheringEventCallback(callback);
+        mLooper.dispatchAll();
         mTethering.stopTethering(TETHERING_WIFI);
         sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
         mLooper.dispatchAll();
-        tetherState = callback.pollTetherStatesChanged();
+        tetherState = callback2.pollTetherStatesChanged();
         assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
         mLooper.dispatchAll();
-        callback.expectUpstreamChanged(new Network[] {null});
+        callback2.expectUpstreamChanged(new Network[] {null});
+        callback.assertNoCallback();
     }
 
     @Test
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index c028d6d..c90abbb 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -50,7 +50,6 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
-import android.net.NetworkState;
 import android.net.util.SharedLog;
 import android.os.Handler;
 import android.os.Message;
@@ -539,7 +538,7 @@
                 mUNM.selectPreferredUpstreamType(preferredTypes));
         verify(mEntitleMgr, times(1)).maybeRunProvisioning();
     }
-    private void assertSatisfiesLegacyType(int legacyType, NetworkState ns) {
+    private void assertSatisfiesLegacyType(int legacyType, UpstreamNetworkState ns) {
         if (legacyType == TYPE_NONE) {
             assertTrue(ns == null);
             return;
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 3eb9049..eecc101 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -42,7 +42,7 @@
 	IconPackRoundedLauncherOverlay \
 	IconPackRoundedSettingsOverlay \
 	IconPackRoundedSystemUIOverlay \
-	IconPackRoundedThemePickerUIOverlay \
+	IconPackRoundedThemePickerOverlay \
 	IconShapeRoundedRectOverlay \
 	IconShapeSquircleOverlay \
 	IconShapeTeardropOverlay \
diff --git a/services/Android.bp b/services/Android.bp
index ef40a35..53d792d 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -1,3 +1,37 @@
+filegroup {
+    name: "services-main-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "services-sources",
+    srcs: [
+        ":services.core-sources",
+        ":services.accessibility-sources",
+        ":services.appprediction-sources",
+        ":services.appwidget-sources",
+        ":services.autofill-sources",
+        ":services.backup-sources",
+        ":services.companion-sources",
+        ":services.contentcapture-sources",
+        ":services.contentsuggestions-sources",
+        ":services.coverage-sources",
+        ":services.devicepolicy-sources",
+        ":services.midi-sources",
+        ":services.net-sources",
+        ":services.print-sources",
+        ":services.restrictions-sources",
+        ":services.startop.iorap-sources",
+        ":services.systemcaptions-sources",
+        ":services.usage-sources",
+        ":services.usb-sources",
+        ":services.voiceinteraction-sources",
+    ],
+    visibility: ["//visibility:private"],
+}
+
 // merge all required services into one jar
 // ============================================================
 java_library {
@@ -9,9 +43,7 @@
         profile: "art-profile",
     },
 
-    srcs: [
-        "java/**/*.java",
-    ],
+    srcs: [":services-main-sources"],
 
     // The convention is to name each service module 'services.$(module_name)'
     static_libs: [
@@ -40,6 +72,7 @@
 
     libs: [
         "android.hidl.manager-V1.0-java",
+        "framework-tethering"
     ],
 
     plugins: [
@@ -69,3 +102,29 @@
     name: "art-profile",
     srcs: ["art-profile"],
 }
+
+// API stub
+// =============================================================
+
+droidstubs {
+    name: "services-stubs.sources",
+    srcs: [":services-sources"],
+    installable: false,
+    // TODO: remove the --hide options below
+    args: " --show-single-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES,process=android.annotation.SystemApi.Process.SYSTEM_SERVER\\)" +
+        " --hide-annotation android.annotation.Hide" +
+        " --hide-package com.google.android.startop.iorap" +
+        " --hide ReferencesHidden" +
+        " --hide DeprecationMismatch" +
+        " --hide HiddenTypedefConstant",
+    libs: [
+        "framework-all",
+    ],
+    visibility: ["//visibility:private"],
+}
+
+java_library {
+    name: "services-stubs",
+    srcs: [":services-stubs.sources"],
+    installable: false,
+}
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index f991d7b..284a2f2 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.accessibility-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.accessibility",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.accessibility-sources"],
     libs: ["services.core"],
 }
diff --git a/services/appprediction/Android.bp b/services/appprediction/Android.bp
index a7be587..e14e1df 100644
--- a/services/appprediction/Android.bp
+++ b/services/appprediction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.appprediction-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.appprediction",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.appprediction-sources"],
     libs: ["services.core"],
 }
diff --git a/services/appwidget/Android.bp b/services/appwidget/Android.bp
index aad2ad19..54cf6ce 100644
--- a/services/appwidget/Android.bp
+++ b/services/appwidget/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.appwidget-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.appwidget",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.appwidget-sources"],
     libs: ["services.core"],
 }
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index 2768c18..539eb1a 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.autofill-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.autofill",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.autofill-sources"],
     libs: ["services.core"],
 }
diff --git a/services/backup/Android.bp b/services/backup/Android.bp
index ef03d83..f945d0f 100644
--- a/services/backup/Android.bp
+++ b/services/backup/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.backup-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.backup",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.backup-sources"],
     libs: ["services.core"],
 }
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index d2dac35..9677a7d 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.companion-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.companion",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.companion-sources"],
     libs: ["services.core"],
 }
diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp
index 57e859e..96e2072 100644
--- a/services/contentcapture/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.contentcapture-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.contentcapture",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.contentcapture-sources"],
     libs: ["services.core"],
 }
diff --git a/services/contentsuggestions/Android.bp b/services/contentsuggestions/Android.bp
index fc09d2e..d17f06f 100644
--- a/services/contentsuggestions/Android.bp
+++ b/services/contentsuggestions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.contentsuggestions-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.contentsuggestions",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.contentsuggestions-sources"],
     libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 4e75e00..cbd095b 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -1,24 +1,21 @@
+filegroup {
+    name: "services.core-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.core.unboosted",
-
-    aidl: {
-        include_dirs: [
-            "frameworks/base/cmds/idmap2/idmap2d/aidl",
-            "frameworks/native/aidl/binder",
-            "frameworks/native/cmds/dumpstate/binder",
-            "system/core/storaged/binder",
-            "system/vold/binder",
-            "system/gsid/aidl",
-        ],
-    },
     srcs: [
         "java/**/*.java",
         ":dumpstate_aidl",
+        ":framework_native_aidl",
+        ":gsiservice_aidl",
         ":idmap2_aidl",
         ":installd_aidl",
         ":storaged_aidl",
         ":vold_aidl",
-        ":gsiservice_aidl",
         ":platform-compat-config",
         "java/com/android/server/EventLogTags.logtags",
         "java/com/android/server/am/EventLogTags.logtags",
@@ -32,6 +29,7 @@
         "android.hardware.tv.cec-V1.0-java",
         "app-compat-annotations",
         "vintf-vibrator-java",
+        "framework-tethering",
     ],
 
     required: [
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index 8c5ee7f..316306d 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -231,8 +231,8 @@
                 Slog.d(TAG, "mCurrentGravityVector = " + currentGravityVectorString);
                 Slog.d(TAG, "mPreviousGravityVector = " + previousGravityVectorString);
             }
-            mRunningStats.reset();
             status = getStationaryStatus();
+            mRunningStats.reset();
             if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
             if (status != RESULT_UNKNOWN) {
                 if (mWakeLock.isHeld()) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 798a4c6..cdfd310 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -613,22 +613,7 @@
     }
 
     public boolean isEnabled() {
-        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
-            Slog.w(TAG, "isEnabled(): not allowed for non-active and non system user");
-            return false;
-        }
-
-        try {
-            mBluetoothLock.readLock().lock();
-            if (mBluetooth != null) {
-                return mBluetooth.isEnabled();
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "isEnabled()", e);
-        } finally {
-            mBluetoothLock.readLock().unlock();
-        }
-        return false;
+        return getState() == BluetoothAdapter.STATE_ON;
     }
 
     public int getState() {
@@ -1766,14 +1751,8 @@
 
                         //Do enable request
                         try {
-                            if (!mQuietEnable) {
-                                if (!mBluetooth.enable()) {
-                                    Slog.e(TAG, "IBluetooth.enable() returned false");
-                                }
-                            } else {
-                                if (!mBluetooth.enableNoAutoConnect()) {
-                                    Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
-                                }
+                            if (!mBluetooth.enable(mQuietEnable)) {
+                                Slog.e(TAG, "IBluetooth.enable() returned false");
                             }
                         } catch (RemoteException e) {
                             Slog.e(TAG, "Unable to call enable()", e);
@@ -2048,14 +2027,8 @@
             } else if (mBluetooth != null) {
                 //Enable bluetooth
                 try {
-                    if (!mQuietEnable) {
-                        if (!mBluetooth.enable()) {
-                            Slog.e(TAG, "IBluetooth.enable() returned false");
-                        }
-                    } else {
-                        if (!mBluetooth.enableNoAutoConnect()) {
-                            Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
-                        }
+                    if (!mBluetooth.enable(mQuietEnable)) {
+                        Slog.e(TAG, "IBluetooth.enable() returned false");
                     }
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Unable to call enable()", e);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 753c117..bb78ace 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -77,7 +77,6 @@
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
 import android.net.ISocketKeepaliveCallback;
-import android.net.ITetheringEventCallback;
 import android.net.InetAddresses;
 import android.net.IpMemoryStore;
 import android.net.IpPrefix;
@@ -278,8 +277,6 @@
 
     private MockableSystemProperties mSystemProperties;
 
-    private TetheringManager mTetheringManager;
-
     @VisibleForTesting
     protected final PermissionMonitor mPermissionMonitor;
 
@@ -867,13 +864,6 @@
         }
 
         /**
-         * Get a reference to the TetheringManager.
-         */
-        public TetheringManager getTetheringManager() {
-            return TetheringManager.getInstance();
-        }
-
-        /**
          * @see ProxyTracker
          */
         public ProxyTracker makeProxyTracker(@NonNull Context context,
@@ -1072,8 +1062,6 @@
 
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
 
-        mTetheringManager = mDeps.getTetheringManager();
-
         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
 
         // Set up the listener for user state for creating user VPNs.
@@ -1887,14 +1875,6 @@
             }
             mHandler.sendMessage(mHandler.obtainMessage(
                     EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0));
-
-            // TODO: relocate this specific callback in Tethering.
-            if (restrictBackground) {
-                log("onRestrictBackgroundChanged(true): disabling tethering");
-                mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
-                mTetheringManager.stopTethering(ConnectivityManager.TETHERING_USB);
-                mTetheringManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
-            }
         }
     };
 
@@ -2024,12 +2004,6 @@
                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid);
     }
 
-    private void enforceTetherAccessPermission() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.ACCESS_NETWORK_STATE,
-                "ConnectivityService");
-    }
-
     private void enforceControlAlwaysOnVpnPermission() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_ALWAYS_ON_VPN,
@@ -2463,12 +2437,6 @@
         mKeepaliveTracker.dump(pw);
 
         pw.println();
-        pw.println("TetheringManager logs:");
-        pw.increaseIndent();
-        TetheringManager.getInstance().dump(pw);
-        pw.decreaseIndent();
-
-        pw.println();
         dumpAvoidBadWifiSettings(pw);
 
         pw.println();
@@ -3993,183 +3961,55 @@
         }
     }
 
-    // javadoc from interface
     @Override
-    public int tether(String iface, String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        if (isTetheringSupported()) {
-            return mTetheringManager.tether(iface);
-        } else {
-            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
-        }
-    }
-
-    // javadoc from interface
-    @Override
-    public int untether(String iface, String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-
-        if (isTetheringSupported()) {
-            return mTetheringManager.untether(iface);
-        } else {
-            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
-        }
-    }
-
-    // javadoc from interface
-    @Override
+    @Deprecated
     public int getLastTetherError(String iface) {
-        enforceTetherAccessPermission();
-
-        if (isTetheringSupported()) {
-            return mTetheringManager.getLastTetherError(iface);
-        } else {
-            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
-        }
-    }
-
-    // TODO - proper iface API for selection by property, inspection, etc
-    @Override
-    public String[] getTetherableUsbRegexs() {
-        enforceTetherAccessPermission();
-        if (isTetheringSupported()) {
-            return mTetheringManager.getTetherableUsbRegexs();
-        } else {
-            return new String[0];
-        }
+        final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+                Context.TETHERING_SERVICE);
+        return tm.getLastTetherError(iface);
     }
 
     @Override
-    public String[] getTetherableWifiRegexs() {
-        enforceTetherAccessPermission();
-        if (isTetheringSupported()) {
-            return mTetheringManager.getTetherableWifiRegexs();
-        } else {
-            return new String[0];
-        }
-    }
-
-    @Override
-    public String[] getTetherableBluetoothRegexs() {
-        enforceTetherAccessPermission();
-        if (isTetheringSupported()) {
-            return mTetheringManager.getTetherableBluetoothRegexs();
-        } else {
-            return new String[0];
-        }
-    }
-
-    @Override
-    public int setUsbTethering(boolean enable, String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        if (isTetheringSupported()) {
-            return mTetheringManager.setUsbTethering(enable);
-        } else {
-            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
-        }
-    }
-
-    // TODO - move iface listing, queries, etc to new module
-    // javadoc from interface
-    @Override
+    @Deprecated
     public String[] getTetherableIfaces() {
-        enforceTetherAccessPermission();
-        return mTetheringManager.getTetherableIfaces();
+        final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+                Context.TETHERING_SERVICE);
+        return tm.getTetherableIfaces();
     }
 
     @Override
+    @Deprecated
     public String[] getTetheredIfaces() {
-        enforceTetherAccessPermission();
-        return mTetheringManager.getTetheredIfaces();
+        final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+                Context.TETHERING_SERVICE);
+        return tm.getTetheredIfaces();
     }
 
+
     @Override
+    @Deprecated
     public String[] getTetheringErroredIfaces() {
-        enforceTetherAccessPermission();
-        return mTetheringManager.getTetheringErroredIfaces();
+        final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+                Context.TETHERING_SERVICE);
+
+        return tm.getTetheringErroredIfaces();
     }
 
     @Override
-    public String[] getTetheredDhcpRanges() {
-        enforceSettingsPermission();
-        return mTetheringManager.getTetheredDhcpRanges();
+    @Deprecated
+    public String[] getTetherableUsbRegexs() {
+        final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+                Context.TETHERING_SERVICE);
+
+        return tm.getTetherableUsbRegexs();
     }
 
     @Override
-    public boolean isTetheringSupported(String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        return isTetheringSupported();
-    }
-
-    // if ro.tether.denied = true we default to no tethering
-    // gservices could set the secure setting to 1 though to enable it on a build where it
-    // had previously been turned off.
-    private boolean isTetheringSupported() {
-        int defaultVal = encodeBool(!mSystemProperties.get("ro.tether.denied").equals("true"));
-        boolean tetherSupported = toBool(Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.TETHER_SUPPORTED, defaultVal));
-        boolean tetherEnabledInSettings = tetherSupported
-                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
-
-        // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
-        boolean adminUser = false;
-        final long token = Binder.clearCallingIdentity();
-        try {
-            adminUser = mUserManager.isAdminUser();
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-
-        return tetherEnabledInSettings && adminUser
-                && mTetheringManager.hasTetherableConfiguration();
-    }
-
-    @Override
-    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
-            String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        if (!isTetheringSupported()) {
-            receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
-            return;
-        }
-        mTetheringManager.startTethering(type, receiver, showProvisioningUi);
-    }
-
-    @Override
-    public void stopTethering(int type, String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        mTetheringManager.stopTethering(type);
-    }
-
-    /**
-     * Get the latest value of the tethering entitlement check.
-     *
-     * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
-     * out some such apps are observed to abuse this API, change to per-UID limits on this API
-     * if it's really needed.
-     */
-    @Override
-    public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
-            boolean showEntitlementUi, String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        mTetheringManager.requestLatestTetheringEntitlementResult(
-                type, receiver, showEntitlementUi);
-    }
-
-    /** Register tethering event callback. */
-    @Override
-    public void registerTetheringEventCallback(ITetheringEventCallback callback,
-            String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        mTetheringManager.registerTetheringEventCallback(callback);
-    }
-
-    /** Unregister tethering event callback. */
-    @Override
-    public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
-            String callerPkg) {
-        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        mTetheringManager.unregisterTetheringEventCallback(callback);
+    @Deprecated
+    public String[] getTetherableWifiRegexs() {
+        final TetheringManager tm = (TetheringManager) mContext.getSystemService(
+                Context.TETHERING_SERVICE);
+        return tm.getTetherableWifiRegexs();
     }
 
     // Called when we lose the default network and have no replacement yet.
@@ -5573,7 +5413,7 @@
      * @param linkProperties the initial link properties of this network. They can be updated
      *         later : see {@link #updateLinkProperties}.
      * @param networkCapabilities the initial capabilites of this network. They can be updated
-     *         later : see {@link #updateNetworkCapabilities}.
+     *         later : see {@link #updateCapabilities}.
      * @param currentScore the initial score of the network. See
      *         {@link NetworkAgentInfo#getCurrentScore}.
      * @param networkMisc metadata about the network. This is never updated.
@@ -5596,7 +5436,7 @@
                 ns, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
                 mDnsResolver, mNMS, factorySerialNumber);
         // Make sure the network capabilities reflect what the agent info says.
-        nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
+        nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
         final String extraInfo = networkInfo.getExtraInfo();
         final String name = TextUtils.isEmpty(extraInfo)
                 ? nai.networkCapabilities.getSSID() : extraInfo;
@@ -5950,11 +5790,7 @@
             }
         }
 
-        final NetworkCapabilities prevNc;
-        synchronized (nai) {
-            prevNc = nai.networkCapabilities;
-            nai.setNetworkCapabilities(newNc);
-        }
+        final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
 
         updateUids(nai, prevNc, newNc);
 
@@ -5963,7 +5799,7 @@
             // the change we're processing can't affect any requests, it can only affect the listens
             // on this network. We might have been called by rematchNetworkAndRequests when a
             // network changed foreground state.
-            processListenRequests(nai, true);
+            processListenRequests(nai);
         } else {
             // If the requestable capabilities have changed or the score changed, we can't have been
             // called by rematchNetworkAndRequests, so it's safe to start a rematch.
@@ -6271,8 +6107,14 @@
         updateAllVpnsCapabilities();
     }
 
-    private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
+    private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
         // For consistency with previous behaviour, send onLost callbacks before onAvailable.
+        processNewlyLostListenRequests(nai);
+        notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
+        processNewlySatisfiedListenRequests(nai);
+    }
+
+    private void processNewlyLostListenRequests(@NonNull final NetworkAgentInfo nai) {
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
             NetworkRequest nr = nri.request;
             if (!nr.isListen()) continue;
@@ -6281,11 +6123,9 @@
                 callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
             }
         }
+    }
 
-        if (capabilitiesChanged) {
-            notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
-        }
-
+    private void processNewlySatisfiedListenRequests(@NonNull final NetworkAgentInfo nai) {
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
             NetworkRequest nr = nri.request;
             if (!nr.isListen()) continue;
@@ -6468,19 +6308,20 @@
         // before LegacyTypeTracker sends legacy broadcasts
         for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
 
-        // Second pass: process all listens.
-        if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
-            // TODO : most of the following is useless because the only thing that changed
-            // here is whether the network is a background network. Clean this up.
+        // Finally, process listen requests and update capabilities if the background state has
+        // changed for this network. For consistency with previous behavior, send onLost callbacks
+        // before onAvailable.
+        processNewlyLostListenRequests(newNetwork);
 
-            NetworkCapabilities newNc = mixInCapabilities(newNetwork,
+        // Maybe the network changed background states. Update its capabilities.
+        final boolean backgroundChanged = wasBackgroundNetwork != newNetwork.isBackgroundNetwork();
+        if (backgroundChanged) {
+            final NetworkCapabilities newNc = mixInCapabilities(newNetwork,
                     newNetwork.networkCapabilities);
 
-            if (Objects.equals(newNetwork.networkCapabilities, newNc)) return;
-
             final int oldPermission = getNetworkPermission(newNetwork.networkCapabilities);
             final int newPermission = getNetworkPermission(newNc);
-            if (oldPermission != newPermission && newNetwork.created && !newNetwork.isVPN()) {
+            if (oldPermission != newPermission) {
                 try {
                     mNMS.setNetworkPermission(newNetwork.network.netId, newPermission);
                 } catch (RemoteException e) {
@@ -6488,53 +6329,11 @@
                 }
             }
 
-            final NetworkCapabilities prevNc;
-            synchronized (newNetwork) {
-                prevNc = newNetwork.networkCapabilities;
-                newNetwork.setNetworkCapabilities(newNc);
-            }
-
-            updateUids(newNetwork, prevNc, newNc);
-
-            if (newNetwork.getCurrentScore() == score
-                    && newNc.equalRequestableCapabilities(prevNc)) {
-                // If the requestable capabilities haven't changed, and the score hasn't changed,
-                // then the change we're processing can't affect any requests, it can only affect
-                // the listens on this network.
-                processListenRequests(newNetwork, true);
-            } else {
-                rematchAllNetworksAndRequests();
-                notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_CAP_CHANGED);
-            }
-
-            if (prevNc != null) {
-                final boolean oldMetered = prevNc.isMetered();
-                final boolean newMetered = newNc.isMetered();
-                final boolean meteredChanged = oldMetered != newMetered;
-
-                if (meteredChanged) {
-                    maybeNotifyNetworkBlocked(newNetwork, oldMetered, newMetered,
-                            mRestrictBackground, mRestrictBackground);
-                }
-
-                final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING)
-                        != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
-
-                // Report changes that are interesting for network statistics tracking.
-                if (meteredChanged || roamingChanged) {
-                    notifyIfacesChangedForNetworkStats();
-                }
-            }
-
-            if (!newNc.hasTransport(TRANSPORT_VPN)) {
-                // Tell VPNs about updated capabilities, since they may need to
-                // bubble those changes through.
-                updateAllVpnsCapabilities();
-            }
-
-        } else {
-            processListenRequests(newNetwork, false);
+            newNetwork.getAndSetNetworkCapabilities(newNc);
+            notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_CAP_CHANGED);
         }
+
+        processNewlySatisfiedListenRequests(newNetwork);
     }
 
     /**
@@ -6719,9 +6518,8 @@
 
             // NetworkCapabilities need to be set before sending the private DNS config to
             // NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required.
-            synchronized (networkAgent) {
-                networkAgent.setNetworkCapabilities(networkAgent.networkCapabilities);
-            }
+            networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
+
             handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
             updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
                     null);
@@ -7092,14 +6890,6 @@
         // Turn airplane mode off
         setAirplaneMode(false);
 
-        if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
-            // Untether
-            String pkgName = mContext.getOpPackageName();
-            for (String tether : getTetheredIfaces()) {
-                untether(tether, pkgName);
-            }
-        }
-
         if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) {
             // Remove always-on package
             synchronized (mVpns) {
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 7b02b6e..7909e30 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -179,18 +179,7 @@
 
     @Override
     public boolean isInUse() throws RemoteException {
-        boolean gsidWasRunning = "running".equals(SystemProperties.get("init.svc.gsid"));
-        boolean isInUse = false;
-
-        try {
-            isInUse = getGsiService().isGsiRunning();
-        } finally {
-            if (!gsidWasRunning && !isInUse) {
-                mGsiService = null;
-            }
-        }
-
-        return isInUse;
+        return SystemProperties.getBoolean("ro.gsid.image_running", false);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index c0f10a3..fe154ed 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -137,11 +137,6 @@
         }
 
         @Override
-        public Bundle getCarrierConfigValues(int subId) throws RemoteException {
-            return null;
-        }
-
-        @Override
         public Uri importTextMessage(String callingPkg, String address, int type, String text,
                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
             return null;
@@ -370,12 +365,6 @@
         }
 
         @Override
-        public Bundle getCarrierConfigValues(int subId) throws RemoteException {
-            Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
-            return getServiceGuarded().getCarrierConfigValues(subId);
-        }
-
-        @Override
         public Uri importTextMessage(String callingPkg, String address, int type, String text,
                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index e79a289..0d496b6 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
 import static android.Manifest.permission.SHUTDOWN;
@@ -57,6 +58,7 @@
 import android.net.NetworkStats;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.TetherConfigParcel;
 import android.net.TetherStatsParcel;
 import android.net.UidRange;
 import android.net.UidRangeParcel;
@@ -737,7 +739,9 @@
     //
     @Override
     public String[] listInterfaces() {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+        //  APIs.
+        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         try {
             return mNetdService.interfaceGetList();
         } catch (RemoteException | ServiceSpecificException e) {
@@ -787,7 +791,9 @@
 
     @Override
     public InterfaceConfiguration getInterfaceConfig(String iface) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+        //  APIs.
+        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         final InterfaceConfigurationParcel result;
         try {
             result = mNetdService.interfaceGetCfg(iface);
@@ -805,7 +811,9 @@
 
     @Override
     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+        //  APIs.
+        NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
         LinkAddress linkAddr = cfg.getLinkAddress();
         if (linkAddr == null || linkAddr.getAddress() == null) {
             throw new IllegalStateException("Null LinkAddress given");
@@ -1016,7 +1024,10 @@
         NetworkStack.checkNetworkStackPermission(mContext);
         // an odd number of addrs will fail
         try {
-            mNetdService.tetherStartWithConfiguration(usingLegacyDnsProxy, dhcpRange);
+            final TetherConfigParcel config = new TetherConfigParcel();
+            config.usingLegacyDnsProxy = usingLegacyDnsProxy;
+            config.dhcpRanges = dhcpRange;
+            mNetdService.tetherStartWithConfiguration(config);
         } catch (RemoteException | ServiceSpecificException e) {
             throw new IllegalStateException(e);
         }
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
index b0b45f4..39be311 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
@@ -35,11 +35,11 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.util.NtpTrustedTime;
 import android.util.TimeUtils;
 
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.DumpUtils;
 
 import java.io.FileDescriptor;
@@ -137,7 +137,7 @@
 
     private void registerForTelephonyIntents() {
         IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+        intentFilter.addAction(TelephonyManager.ACTION_NETWORK_SET_TIME);
         mContext.registerReceiver(mNitzReceiver, intentFilter);
     }
 
@@ -247,7 +247,7 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (DBG) Log.d(TAG, "Received " + action);
-            if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
+            if (TelephonyManager.ACTION_NETWORK_SET_TIME.equals(action)) {
                 mNitzTimeSetTime = SystemClock.elapsedRealtime();
             }
         }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8436e38..b5ecd19 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -30,7 +30,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -52,7 +51,6 @@
 import android.telephony.LocationAccessPolicy;
 import android.telephony.PhoneCapability;
 import android.telephony.PhoneStateListener;
-import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 import android.telephony.PreciseDisconnectCause;
@@ -72,7 +70,6 @@
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.ITelephonyRegistry;
-import com.android.internal.telephony.PhoneConstantConversions;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyPermissions;
@@ -210,12 +207,8 @@
 
     private int[] mDataConnectionNetworkType;
 
-    private int[] mOtaspMode;
-
     private ArrayList<List<CellInfo>> mCellInfo = null;
 
-    private ArrayList<List<PhysicalChannelConfig>> mPhysicalChannelConfigs;
-
     private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList;
 
     private EmergencyNumber[] mOutgoingSmsEmergencyNumber;
@@ -262,7 +255,9 @@
 
     private final LocalLog mListenLog = new LocalLog(100);
 
-    private PreciseDataConnectionState[] mPreciseDataConnectionState;
+    // Per-phoneMap of APN Type to DataConnectionState
+    private List<Map<String, PreciseDataConnectionState>> mPreciseDataConnectionStates =
+            new ArrayList<Map<String, PreciseDataConnectionState>>();
 
     // Nothing here yet, but putting it here in case we want to add more in the future.
     static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK = 0;
@@ -359,7 +354,7 @@
                         SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                         SubscriptionManager.getDefaultSubscriptionId());
                 int newDefaultPhoneId = intent.getIntExtra(
-                        PhoneConstants.PHONE_KEY,
+                        SubscriptionManager.EXTRA_SLOT_INDEX,
                         SubscriptionManager.getPhoneId(newDefaultSubId));
                 if (DBG) {
                     log("onReceive:current mDefaultSubId=" + mDefaultSubId
@@ -407,7 +402,6 @@
         mCallForwarding = copyOf(mCallForwarding, mNumPhones);
         mCellLocation = copyOf(mCellLocation, mNumPhones);
         mSrvccState = copyOf(mSrvccState, mNumPhones);
-        mOtaspMode = copyOf(mOtaspMode, mNumPhones);
         mPreciseCallState = copyOf(mPreciseCallState, mNumPhones);
         mForegroundCallState = copyOf(mForegroundCallState, mNumPhones);
         mBackgroundCallState = copyOf(mBackgroundCallState, mNumPhones);
@@ -417,7 +411,6 @@
         mCallQuality = copyOf(mCallQuality, mNumPhones);
         mCallNetworkType = copyOf(mCallNetworkType, mNumPhones);
         mCallAttributes = copyOf(mCallAttributes, mNumPhones);
-        mPreciseDataConnectionState = copyOf(mPreciseDataConnectionState, mNumPhones);
         mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones);
         mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones);
 
@@ -425,7 +418,7 @@
         if (mNumPhones < oldNumPhones) {
             cutListToSize(mCellInfo, mNumPhones);
             cutListToSize(mImsReasonInfo, mNumPhones);
-            cutListToSize(mPhysicalChannelConfigs, mNumPhones);
+            cutListToSize(mPreciseDataConnectionStates, mNumPhones);
             return;
         }
 
@@ -446,19 +439,17 @@
             mCellInfo.add(i, null);
             mImsReasonInfo.add(i, null);
             mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
-            mPhysicalChannelConfigs.add(i, new ArrayList<>());
-            mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
             mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
             mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
-            mCallQuality[i] = new CallQuality();
-            mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
-                    TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+            mCallQuality[i] = createCallQuality();
+            mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
+                    TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
             mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-            mPreciseCallState[i] = new PreciseCallState();
+            mPreciseCallState[i] = createPreciseCallState();
             mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
             mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
             mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
-            mPreciseDataConnectionState[i] = new PreciseDataConnectionState();
+            mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
         }
 
         // Note that location can be null for non-phone builds like
@@ -510,7 +501,6 @@
         mCallForwarding = new boolean[numPhones];
         mCellLocation = new Bundle[numPhones];
         mSrvccState = new int[numPhones];
-        mOtaspMode = new int[numPhones];
         mPreciseCallState = new PreciseCallState[numPhones];
         mForegroundCallState = new int[numPhones];
         mBackgroundCallState = new int[numPhones];
@@ -520,10 +510,9 @@
         mCallQuality = new CallQuality[numPhones];
         mCallNetworkType = new int[numPhones];
         mCallAttributes = new CallAttributes[numPhones];
-        mPreciseDataConnectionState = new PreciseDataConnectionState[numPhones];
+        mPreciseDataConnectionStates = new ArrayList<>();
         mCellInfo = new ArrayList<>();
         mImsReasonInfo = new ArrayList<>();
-        mPhysicalChannelConfigs = new ArrayList<>();
         mEmergencyNumberList = new HashMap<>();
         mOutgoingCallEmergencyNumber = new EmergencyNumber[numPhones];
         mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones];
@@ -543,19 +532,17 @@
             mCellInfo.add(i, null);
             mImsReasonInfo.add(i, null);
             mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
-            mPhysicalChannelConfigs.add(i, new ArrayList<>());
-            mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
             mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
             mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
-            mCallQuality[i] = new CallQuality();
-            mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
-                    TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+            mCallQuality[i] = createCallQuality();
+            mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
+                    TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
             mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-            mPreciseCallState[i] = new PreciseCallState();
+            mPreciseCallState[i] = createPreciseCallState();
             mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
             mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
             mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
-            mPreciseDataConnectionState[i] = new PreciseDataConnectionState();
+            mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
         }
 
         // Note that location can be null for non-phone builds like
@@ -875,13 +862,6 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
-                        try {
-                            r.callback.onOtaspChanged(mOtaspMode[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
-                    }
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
                         try {
                             if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
@@ -917,8 +897,10 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                         try {
-                            r.callback.onPreciseDataConnectionStateChanged(
-                                    mPreciseDataConnectionState[phoneId]);
+                            for (PreciseDataConnectionState pdcs
+                                    : mPreciseDataConnectionStates.get(phoneId).values()) {
+                                r.callback.onPreciseDataConnectionStateChanged(pdcs);
+                            }
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -932,7 +914,8 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) !=0) {
                         try {
-                            r.callback.onVoiceActivationStateChanged(mVoiceActivationState[phoneId]);
+                            r.callback.onVoiceActivationStateChanged(
+                                    mVoiceActivationState[phoneId]);
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -951,14 +934,6 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) {
-                        try {
-                            r.callback.onPhysicalChannelConfigurationChanged(
-                                    mPhysicalChannelConfigs.get(phoneId));
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
-                    }
                     if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
                         try {
                             r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
@@ -1383,43 +1358,6 @@
         }
     }
 
-    /**
-     * Notify physical channel configuration according to subscripton ID and phone ID
-     */
-    public void notifyPhysicalChannelConfigurationForSubscriber(int phoneId, int subId,
-            List<PhysicalChannelConfig> configs) {
-        if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) {
-            return;
-        }
-
-        if (VDBG) {
-            log("notifyPhysicalChannelConfiguration: subId=" + subId + " phoneId=" + phoneId
-                    + " configs=" + configs);
-        }
-
-        synchronized (mRecords) {
-            if (validatePhoneId(phoneId)) {
-                mPhysicalChannelConfigs.set(phoneId, configs);
-                for (Record r : mRecords) {
-                    if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION)
-                            && idMatch(r.subId, subId, phoneId)) {
-                        try {
-                            if (DBG_LOC) {
-                                log("notifyPhysicalChannelConfiguration: mPhysicalChannelConfigs="
-                                        + configs + " r=" + r);
-                            }
-                            r.callback.onPhysicalChannelConfigurationChanged(configs);
-                        } catch (RemoteException ex) {
-                            mRemoveList.add(r.binder);
-                        }
-                    }
-                }
-            }
-            handleRemoveListLocked();
-        }
-    }
-
     @Override
     public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
         if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
@@ -1535,30 +1473,38 @@
         }
     }
 
-    public void notifyDataConnection(int state, boolean isDataAllowed, String apn, String apnType,
-                                     LinkProperties linkProperties,
-                                     NetworkCapabilities networkCapabilities, int networkType,
-                                     boolean roaming) {
-        notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_PHONE_INDEX,
-                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,  state,
-                isDataAllowed, apn, apnType, linkProperties,
-                networkCapabilities, networkType, roaming);
-    }
-
-    public void notifyDataConnectionForSubscriber(int phoneId, int subId, int state,
-                                                  boolean isDataAllowed,
-                                                  String apn, String apnType,
-            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
-            int networkType, boolean roaming) {
+    /**
+     * Send a notification to registrants that the data connection state has changed.
+     *
+     * @param phoneId the phoneId carrying the data connection
+     * @param subId the subscriptionId for the data connection
+     * @param apnType the APN type that triggered a change in the data connection
+     * @param preciseState a PreciseDataConnectionState that has info about the data connection
+     */
+    public void notifyDataConnectionForSubscriber(
+            int phoneId, int subId, String apnType, PreciseDataConnectionState preciseState) {
         if (!checkNotifyPermission("notifyDataConnection()" )) {
             return;
         }
+
+        String apn = "";
+        int state = TelephonyManager.DATA_UNKNOWN;
+        int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        LinkProperties linkProps = null;
+
+        if (preciseState != null) {
+            apn = preciseState.getDataConnectionApn();
+            state = preciseState.getState();
+            networkType = preciseState.getNetworkType();
+            linkProps = preciseState.getDataConnectionLinkProperties();
+        }
         if (VDBG) {
             log("notifyDataConnectionForSubscriber: subId=" + subId
-                + " state=" + state + " isDataAllowed=" + isDataAllowed
-                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
-                + " mRecords.size()=" + mRecords.size());
+                    + " state=" + state + "' apn='" + apn
+                    + "' apnType=" + apnType + " networkType=" + networkType
+                    + "' preciseState=" + preciseState);
         }
+
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 // We only call the callback when the change is for default APN type.
@@ -1590,35 +1536,45 @@
                     mDataConnectionState[phoneId] = state;
                     mDataConnectionNetworkType[phoneId] = networkType;
                 }
-                mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState(
-                        state, networkType,
-                        ApnSetting.getApnTypesBitmaskFromString(apnType), apn,
-                        linkProperties, DataFailCause.NONE);
-                for (Record r : mRecords) {
-                    if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
-                            && idMatch(r.subId, subId, phoneId)) {
-                        try {
-                            r.callback.onPreciseDataConnectionStateChanged(
-                                    mPreciseDataConnectionState[phoneId]);
-                        } catch (RemoteException ex) {
-                            mRemoveList.add(r.binder);
+
+                boolean needsNotify = false;
+                // State has been cleared for this APN Type
+                if (preciseState == null) {
+                    // We try clear the state and check if the state was previously not cleared
+                    needsNotify = mPreciseDataConnectionStates.get(phoneId).remove(apnType) != null;
+                } else {
+                    // We need to check to see if the state actually changed
+                    PreciseDataConnectionState oldPreciseState =
+                            mPreciseDataConnectionStates.get(phoneId).put(apnType, preciseState);
+                    needsNotify = !preciseState.equals(oldPreciseState);
+                }
+
+                if (needsNotify) {
+                    for (Record r : mRecords) {
+                        if (r.matchPhoneStateListenerEvent(
+                                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
+                                && idMatch(r.subId, subId, phoneId)) {
+                            try {
+                                r.callback.onPreciseDataConnectionStateChanged(preciseState);
+                            } catch (RemoteException ex) {
+                                mRemoveList.add(r.binder);
+                            }
                         }
                     }
                 }
             }
             handleRemoveListLocked();
         }
-        broadcastDataConnectionStateChanged(state, isDataAllowed, apn, apnType, linkProperties,
-                networkCapabilities, roaming, subId);
-        broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn,
-                linkProperties, DataFailCause.NONE);
+
+        broadcastDataConnectionStateChanged(state, apn, apnType, subId);
     }
 
+    /**
+     * Stub to satisfy the ITelephonyRegistry aidl interface; do not use this function.
+     * @see #notifyDataConnectionFailedForSubscriber
+     */
     public void notifyDataConnectionFailed(String apnType) {
-         notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_PHONE_INDEX,
-                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
-                 apnType);
+        loge("This function should not be invoked");
     }
 
     public void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType) {
@@ -1631,17 +1587,20 @@
         }
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
-                mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState(
-                        TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                        ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
-                        DataFailCause.NONE);
+                mPreciseDataConnectionStates.get(phoneId).put(
+                        apnType,
+                        new PreciseDataConnectionState(
+                                TelephonyManager.DATA_UNKNOWN,
+                                TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                                ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
+                                DataFailCause.NONE));
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
                             PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onPreciseDataConnectionStateChanged(
-                                    mPreciseDataConnectionState[phoneId]);
+                                    mPreciseDataConnectionStates.get(phoneId).get(apnType));
                         } catch (RemoteException ex) {
                             mRemoveList.add(r.binder);
                         }
@@ -1652,9 +1611,6 @@
             handleRemoveListLocked();
         }
         broadcastDataConnectionFailed(apnType, subId);
-        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, null, null,
-                DataFailCause.NONE);
     }
 
     public void notifyCellLocation(Bundle cellLocation) {
@@ -1695,29 +1651,6 @@
         }
     }
 
-    public void notifyOtaspChanged(int subId, int otaspMode) {
-        if (!checkNotifyPermission("notifyOtaspChanged()" )) {
-            return;
-        }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
-        synchronized (mRecords) {
-            if (validatePhoneId(phoneId)) {
-                mOtaspMode[phoneId] = otaspMode;
-                for (Record r : mRecords) {
-                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_OTASP_CHANGED)
-                            && idMatch(r.subId, subId, phoneId)) {
-                        try {
-                            r.callback.onOtaspChanged(otaspMode);
-                        } catch (RemoteException ex) {
-                            mRemoveList.add(r.binder);
-                        }
-                    }
-                }
-            }
-            handleRemoveListLocked();
-        }
-    }
-
     public void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
                                        int foregroundCallState, int backgroundCallState) {
         if (!checkNotifyPermission("notifyPreciseCallState()")) {
@@ -1744,7 +1677,7 @@
                     if (mPreciseCallState[phoneId].getForegroundCallState()
                             != PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
                         mCallNetworkType[phoneId] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-                        mCallQuality[phoneId] = new CallQuality();
+                        mCallQuality[phoneId] = createCallQuality();
                     }
                     mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
                             mCallNetworkType[phoneId], mCallQuality[phoneId]);
@@ -1772,8 +1705,6 @@
             }
             handleRemoveListLocked();
         }
-        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState,
-                backgroundCallState);
     }
 
     public void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
@@ -1834,29 +1765,34 @@
         if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
             return;
         }
+
+        // precise notify invokes imprecise notify
+        notifyDataConnectionFailedForSubscriber(phoneId, subId, apnType);
+
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
-                mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState(
-                        TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                        ApnSetting.getApnTypesBitmaskFromString(apnType), apn, null, failCause);
+                mPreciseDataConnectionStates.get(phoneId).put(
+                        apnType,
+                        new PreciseDataConnectionState(
+                                TelephonyManager.DATA_UNKNOWN,
+                                TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                                ApnSetting.getApnTypesBitmaskFromString(apnType), null, null,
+                                failCause));
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
                             PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onPreciseDataConnectionStateChanged(
-                                    mPreciseDataConnectionState[phoneId]);
+                                    mPreciseDataConnectionStates.get(phoneId).get(apnType));
                         } catch (RemoteException ex) {
                             mRemoveList.add(r.binder);
                         }
                     }
                 }
             }
-
             handleRemoveListLocked();
         }
-        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, null, failCause);
     }
 
     @Override
@@ -2112,7 +2048,6 @@
         }
     }
 
-
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -2146,12 +2081,11 @@
                 pw.println("mCellInfo=" + mCellInfo.get(i));
                 pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
                 pw.println("mSrvccState=" + mSrvccState[i]);
-                pw.println("mOtaspMode=" + mOtaspMode[i]);
                 pw.println("mCallPreciseDisconnectCause=" + mCallPreciseDisconnectCause[i]);
                 pw.println("mCallQuality=" + mCallQuality[i]);
                 pw.println("mCallAttributes=" + mCallAttributes[i]);
                 pw.println("mCallNetworkType=" + mCallNetworkType[i]);
-                pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState[i]);
+                pw.println("mPreciseDataConnectionStates=" + mPreciseDataConnectionStates.get(i));
                 pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
                 pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
                 pw.decreaseIndent();
@@ -2186,6 +2120,16 @@
     // the legacy intent broadcasting
     //
 
+    // Legacy intent action.
+    /** Fired when a subscription's phone state changes. */
+    private static final String ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED =
+            "android.intent.action.SUBSCRIPTION_PHONE_STATE";
+
+    // Legacy intent extra keys, copied from PhoneConstants.
+    // Used in legacy intents sent here, for backward compatibility.
+    private static final String PHONE_CONSTANTS_SLOT_KEY = "slot";
+    private static final String PHONE_CONSTANTS_SUBSCRIPTION_KEY = "subscription";
+
     private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) {
         long ident = Binder.clearCallingIdentity();
         try {
@@ -2202,9 +2146,10 @@
         state.fillInNotifierBundle(data);
         intent.putExtras(data);
         // Pass the subscription along with the intent.
-        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+        intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
-        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+        intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
+        intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
@@ -2223,8 +2168,8 @@
         Bundle data = new Bundle();
         signalStrength.fillInNotifierBundle(data);
         intent.putExtras(data);
-        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
-        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+        intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
+        intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
@@ -2254,19 +2199,19 @@
         }
 
         Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
-        intent.putExtra(PhoneConstants.STATE_KEY,
-                PhoneConstantConversions.convertCallState(state).toString());
+        intent.putExtra(TelephonyManager.EXTRA_STATE, callStateToString(state));
 
         // If a valid subId was specified, we should fire off a subId-specific state
         // change intent and include the subId.
         if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            intent.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
-            intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+            intent.setAction(ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
+            intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
             intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
         }
         // If the phoneId is invalid, the broadcast is for overall call state.
         if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
-            intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+            intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
+            intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
         }
 
         // Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast.
@@ -2288,71 +2233,39 @@
                         android.Manifest.permission.READ_CALL_LOG});
     }
 
-    private void broadcastDataConnectionStateChanged(int state, boolean isDataAllowed, String apn,
-                                                     String apnType, LinkProperties linkProperties,
-                                                     NetworkCapabilities networkCapabilities,
-                                                     boolean roaming, int subId) {
+    /** Converts TelephonyManager#CALL_STATE_* to TelephonyManager#EXTRA_STATE_*. */
+    private static String callStateToString(int callState) {
+        switch (callState) {
+            case TelephonyManager.CALL_STATE_RINGING:
+                return TelephonyManager.EXTRA_STATE_RINGING;
+            case TelephonyManager.CALL_STATE_OFFHOOK:
+                return TelephonyManager.EXTRA_STATE_OFFHOOK;
+            default:
+                return TelephonyManager.EXTRA_STATE_IDLE;
+        }
+    }
+
+    private void broadcastDataConnectionStateChanged(int state, String apn,
+                                                     String apnType, int subId) {
         // Note: not reporting to the battery stats service here, because the
         // status bar takes care of that after taking into account all of the
         // required info.
         Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
-        intent.putExtra(PhoneConstants.STATE_KEY,
-                PhoneConstantConversions.convertDataState(state).toString());
-        if (!isDataAllowed) {
-            intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
-        }
-        if (linkProperties != null) {
-            intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
-            String iface = linkProperties.getInterfaceName();
-            if (iface != null) {
-                intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface);
-            }
-        }
-        if (networkCapabilities != null) {
-            intent.putExtra(PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY, networkCapabilities);
-        }
-        if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true);
+        intent.putExtra(TelephonyManager.EXTRA_STATE, dataStateToString(state));
 
         intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
         intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
-        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+        intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void broadcastDataConnectionFailed(String apnType, int subId) {
         Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
         intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
-        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+        intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
-                                                  int backgroundCallState) {
-        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
-        intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
-        intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
-        intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
-        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
-                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
-    }
-
-    private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
-            String apnType, String apn, LinkProperties linkProperties,
-            @DataFailureCause int failCause) {
-        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
-        intent.putExtra(PhoneConstants.STATE_KEY, state);
-        intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
-        if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
-        if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
-        if (linkProperties != null) {
-            intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
-        }
-        intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
-
-        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
-                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
-    }
-
     private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
         if (checkNotifyPermission()) {
             return;
@@ -2681,11 +2594,11 @@
     }
 
     /**
-     * Convert data state to string
+     * Convert TelephonyManager.DATA_* to string.
      *
      * @return The data state in string format.
      */
-    private String dataStateToString(@TelephonyManager.DataState int state) {
+    private static String dataStateToString(int state) {
         switch (state) {
             case TelephonyManager.DATA_DISCONNECTED: return "DISCONNECTED";
             case TelephonyManager.DATA_CONNECTING: return "CONNECTING";
@@ -2748,4 +2661,18 @@
                 return "UNKNOWN";
         }
     }
+
+    /** Returns a new PreciseCallState object with default values. */
+    private static PreciseCallState createPreciseCallState() {
+        return new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+            PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+            PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+            DisconnectCause.NOT_VALID,
+            PreciseDisconnectCause.NOT_VALID);
+    }
+
+    /** Returns a new CallQuality object with default values. */
+    private static CallQuality createCallQuality() {
+        return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    }
 }
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 0db8495..a1480e3 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -60,6 +60,7 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.DebugUtils;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.StatsLog;
@@ -161,6 +162,8 @@
     private int mHapticFeedbackIntensity;
     private int mNotificationIntensity;
     private int mRingIntensity;
+    private SparseArray<Pair<VibrationEffect, AudioAttributes>> mAlwaysOnEffects =
+            new SparseArray<>();
 
     static native boolean vibratorExists();
     static native void vibratorInit();
@@ -172,6 +175,8 @@
     static native boolean vibratorSupportsExternalControl();
     static native void vibratorSetExternalControl(boolean enabled);
     static native long vibratorGetCapabilities();
+    static native void vibratorAlwaysOnEnable(long id, long effect, long strength);
+    static native void vibratorAlwaysOnDisable(long id);
 
     private final IUidObserver mUidObserver = new IUidObserver.Stub() {
         @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
@@ -518,6 +523,41 @@
         }
     }
 
+    @Override // Binder call
+    public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attrs) {
+        if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
+            throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
+        }
+        if ((mCapabilities & IVibrator.CAP_ALWAYS_ON_CONTROL) == 0) {
+            Slog.e(TAG, "Always-on effects not supported.");
+            return false;
+        }
+        if (effect == null) {
+            synchronized (mLock) {
+                mAlwaysOnEffects.delete(id);
+                vibratorAlwaysOnDisable(id);
+            }
+        } else {
+            if (!verifyVibrationEffect(effect)) {
+                return false;
+            }
+            if (!(effect instanceof VibrationEffect.Prebaked)) {
+                Slog.e(TAG, "Only prebaked effects supported for always-on.");
+                return false;
+            }
+            if (attrs == null) {
+                attrs = new AudioAttributes.Builder()
+                        .setUsage(AudioAttributes.USAGE_UNKNOWN)
+                        .build();
+            }
+            synchronized (mLock) {
+                mAlwaysOnEffects.put(id, Pair.create(effect, attrs));
+                updateAlwaysOnLocked(id, effect, attrs);
+            }
+        }
+        return true;
+    }
+
     private void verifyIncomingUid(int uid) {
         if (uid == Binder.getCallingUid()) {
             return;
@@ -988,6 +1028,8 @@
                 // If the state changes out from under us then just reset.
                 doCancelVibrateLocked();
             }
+
+            updateAlwaysOnLocked();
         }
     }
 
@@ -1054,6 +1096,27 @@
                 mVibrator.getDefaultRingVibrationIntensity(), UserHandle.USER_CURRENT);
     }
 
+    private void updateAlwaysOnLocked(int id, VibrationEffect effect, AudioAttributes attrs) {
+        // TODO: Check DND and LowPower settings
+        final Vibration vib = new Vibration(null, effect, attrs, 0, null, null);
+        final int intensity = getCurrentIntensityLocked(vib);
+        if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+            vibratorAlwaysOnDisable(id);
+        } else {
+            final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) effect;
+            final int strength = intensityToEffectStrength(intensity);
+            vibratorAlwaysOnEnable(id, prebaked.getId(), strength);
+        }
+    }
+
+    private void updateAlwaysOnLocked() {
+        for (int i = 0; i < mAlwaysOnEffects.size(); i++) {
+            int id = mAlwaysOnEffects.keyAt(i);
+            Pair<VibrationEffect, AudioAttributes> pair = mAlwaysOnEffects.valueAt(i);
+            updateAlwaysOnLocked(id, pair.first, pair.second);
+        }
+    }
+
     @Override
     public void onInputDeviceAdded(int deviceId) {
         updateVibrators();
diff --git a/services/core/java/com/android/server/ZramWriteback.java b/services/core/java/com/android/server/ZramWriteback.java
index 49bf29b..5d97def 100644
--- a/services/core/java/com/android/server/ZramWriteback.java
+++ b/services/core/java/com/android/server/ZramWriteback.java
@@ -60,6 +60,7 @@
     private static final String MARK_IDLE_DELAY_PROP = "ro.zram.mark_idle_delay_mins";
     private static final String FIRST_WB_DELAY_PROP = "ro.zram.first_wb_delay_mins";
     private static final String PERIODIC_WB_DELAY_PROP = "ro.zram.periodic_wb_delay_hours";
+    private static final String FORCE_WRITEBACK_PROP = "zram.force_writeback";
 
     private void markPagesAsIdle() {
         String idlePath = String.format(IDLE_SYS, sZramDeviceId);
@@ -122,11 +123,12 @@
 
     private static void schedNextWriteback(Context context) {
         int nextWbDelay = SystemProperties.getInt(PERIODIC_WB_DELAY_PROP, 24);
+        boolean forceWb = SystemProperties.getBoolean(FORCE_WRITEBACK_PROP, false);
         JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
 
         js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback)
                         .setMinimumLatency(TimeUnit.HOURS.toMillis(nextWbDelay))
-                        .setRequiresDeviceIdle(true)
+                        .setRequiresDeviceIdle(!forceWb)
                         .build());
     }
 
@@ -167,6 +169,7 @@
     public static void scheduleZramWriteback(Context context) {
         int markIdleDelay = SystemProperties.getInt(MARK_IDLE_DELAY_PROP, 20);
         int firstWbDelay = SystemProperties.getInt(FIRST_WB_DELAY_PROP, 180);
+        boolean forceWb = SystemProperties.getBoolean(FORCE_WRITEBACK_PROP, false);
 
         JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
 
@@ -182,7 +185,7 @@
         // by ro.zram.periodic_wb_delay_hours.
         js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback)
                         .setMinimumLatency(TimeUnit.MINUTES.toMillis(firstWbDelay))
-                        .setRequiresDeviceIdle(true)
+                        .setRequiresDeviceIdle(!forceWb)
                         .build());
     }
 }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6cbbcdd..f021008 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2935,7 +2935,9 @@
                     } catch (Exception e) {
                         Slog.w(TAG, "Exception when unbinding service "
                                 + r.shortInstanceName, e);
+                        needOomAdj = false;
                         serviceProcessGoneLocked(r);
+                        break;
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5ffdf02..1c4f1e3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2411,7 +2411,8 @@
         mConstants = hasHandlerThread
                 ? new ActivityManagerConstants(mContext, this, mHandler) : null;
         final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
-        mProcessList.init(this, activeUids);
+        mPlatformCompat = null;
+        mProcessList.init(this, activeUids, mPlatformCompat);
         mLowMemDetector = null;
         mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
 
@@ -2432,7 +2433,6 @@
         mProcStartHandler = null;
         mHiddenApiBlacklist = null;
         mFactoryTest = FACTORY_TEST_OFF;
-        mPlatformCompat = null;
     }
 
     // Note: This method is invoked on the main thread but may need to attach various
@@ -2461,7 +2461,9 @@
 
         mConstants = new ActivityManagerConstants(mContext, this, mHandler);
         final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
-        mProcessList.init(this, activeUids);
+        mPlatformCompat = (PlatformCompat) ServiceManager.getService(
+                Context.PLATFORM_COMPAT_SERVICE);
+        mProcessList.init(this, activeUids, mPlatformCompat);
         mLowMemDetector = new LowMemDetector(this);
         mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
 
@@ -2569,9 +2571,6 @@
 
         mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
 
-        mPlatformCompat = (PlatformCompat) ServiceManager.getService(
-                Context.PLATFORM_COMPAT_SERVICE);
-
         Watchdog.getInstance().addMonitor(this);
         Watchdog.getInstance().addThread(mHandler);
 
@@ -5048,9 +5047,7 @@
             bindApplicationTimeMillis = SystemClock.elapsedRealtime();
             mAtmInternal.preBindApplication(app.getWindowProcessController());
             final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
-            long[] disabledCompatChanges = {};
             if (mPlatformCompat != null) {
-                disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
                 mPlatformCompat.resetReporting(app.info);
             }
             if (app.isolatedEntryPoint != null) {
@@ -5069,7 +5066,7 @@
                         app.compat, getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
                         buildSerial, autofillOptions, contentCaptureOptions,
-                        disabledCompatChanges);
+                        app.mDisabledCompatChanges);
             } else {
                 thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                         null, null, null, testMode,
@@ -5079,7 +5076,7 @@
                         app.compat, getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
                         buildSerial, autofillOptions, contentCaptureOptions,
-                        disabledCompatChanges);
+                        app.mDisabledCompatChanges);
             }
             if (profilerInfo != null) {
                 profilerInfo.closeFd();
@@ -12802,14 +12799,31 @@
                     pw.println(totalPss - cachedPss);
                 }
             }
-            long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
+            long kernelUsed = memInfo.getKernelUsedSizeKb();
+            final long ionHeap = Debug.getIonHeapsSizeKb();
+            if (ionHeap > 0) {
+                final long ionMapped = Debug.getIonMappedSizeKb();
+                final long ionUnmapped = ionHeap - ionMapped;
+                final long ionPool = Debug.getIonPoolsSizeKb();
+                pw.print("      ION: ");
+                        pw.print(stringifyKBSize(ionHeap + ionPool));
+                        pw.print(" (");
+                        pw.print(stringifyKBSize(ionMapped));
+                        pw.print(" mapped + ");
+                        pw.print(stringifyKBSize(ionUnmapped));
+                        pw.print(" unmapped + ");
+                        pw.print(stringifyKBSize(ionPool));
+                        pw.println(" pools)");
+                kernelUsed += ionUnmapped;
+            }
+            final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
                     - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
-                    - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
+                    - kernelUsed - memInfo.getZramTotalSizeKb();
             if (!opts.isCompact) {
                 pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss
-                        + memInfo.getKernelUsedSizeKb())); pw.print(" (");
+                        + kernelUsed)); pw.print(" (");
                 pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + ");
-                pw.print(stringifyKBSize(memInfo.getKernelUsedSizeKb())); pw.print(" kernel)\n");
+                pw.print(stringifyKBSize(kernelUsed)); pw.print(" kernel)\n");
                 pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM));
             } else {
                 pw.print("lostram,"); pw.println(lostRAM);
@@ -13528,14 +13542,25 @@
         memInfoBuilder.append(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
                 + memInfo.getFreeSizeKb()));
         memInfoBuilder.append("\n");
+        long kernelUsed = memInfo.getKernelUsedSizeKb();
+        final long ionHeap = Debug.getIonHeapsSizeKb();
+        if (ionHeap > 0) {
+            final long ionMapped = Debug.getIonMappedSizeKb();
+            final long ionUnmapped = ionHeap - ionMapped;
+            final long ionPool = Debug.getIonPoolsSizeKb();
+            memInfoBuilder.append("       ION: ");
+            memInfoBuilder.append(stringifyKBSize(ionHeap + ionPool));
+            memInfoBuilder.append("\n");
+            kernelUsed += ionUnmapped;
+        }
         memInfoBuilder.append("  Used RAM: ");
         memInfoBuilder.append(stringifyKBSize(
-                                  totalPss - cachedPss + memInfo.getKernelUsedSizeKb()));
+                                  totalPss - cachedPss + kernelUsed));
         memInfoBuilder.append("\n");
         memInfoBuilder.append("  Lost RAM: ");
         memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb()
                 - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
-                - memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb()));
+                - kernelUsed - memInfo.getZramTotalSizeKb()));
         memInfoBuilder.append("\n");
         Slog.i(TAG, "Low on memory:");
         Slog.i(TAG, shortNativeBuilder.toString());
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 59070c7..b406ce6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2875,6 +2875,12 @@
         final PlatformCompat platformCompat = (PlatformCompat)
                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
         String toggleValue = getNextArgRequired();
+        if (toggleValue.equals("reset-all")) {
+            final String packageName = getNextArgRequired();
+            pw.println("Reset all changes for " + packageName + " to default value.");
+            platformCompat.clearOverrides(packageName);
+            return 0;
+        }
         long changeId;
         String changeIdString = getNextArgRequired();
         try {
@@ -3233,9 +3239,14 @@
             pw.println("      without restarting any processes.");
             pw.println("  write");
             pw.println("      Write all pending state to storage.");
-            pw.println("  compat enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
-            pw.println("      Toggles a change either by id or by name for <PACKAGE_NAME>.");
-            pw.println("      It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
+            pw.println("  compat [COMMAND] [...]: sub-commands for toggling app-compat changes.");
+            pw.println("         enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
+            pw.println("            Toggles a change either by id or by name for <PACKAGE_NAME>.");
+            pw.println("            It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
+            pw.println("         reset-all <PACKAGE_NAME>");
+            pw.println("            Removes all existing overrides for all changes for ");
+            pw.println("            <PACKAGE_NAME> (back to default behaviour).");
+            pw.println("            It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
             pw.println();
             Intent.printIntentArgsHelp(pw, "");
         }
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
new file mode 100644
index 0000000..cacf676
--- /dev/null
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.MessageQueue;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * Lmkd connection to communicate with lowmemorykiller daemon.
+ */
+public class LmkdConnection {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;
+
+    // lmkd reply max size in bytes
+    private static final int LMKD_REPLY_MAX_SIZE = 12;
+
+    // connection listener interface
+    interface LmkdConnectionListener {
+        boolean onConnect(OutputStream ostream);
+        void onDisconnect();
+        /**
+         * Check if received reply was expected (reply to an earlier request)
+         *
+         * @param replyBuf The buffer provided in exchange() to receive the reply.
+         *                 It can be used by exchange() caller to store reply-specific
+         *                 tags for later use in isReplyExpected() to verify if
+         *                 received packet is the expected reply.
+         * @param dataReceived The buffer holding received data
+         * @param receivedLen Size of the data received
+         */
+        boolean isReplyExpected(ByteBuffer replyBuf, ByteBuffer dataReceived,
+                int receivedLen);
+
+        /**
+         * Handle the received message if it's unsolicited.
+         *
+         * @param dataReceived The buffer holding received data
+         * @param receivedLen Size of the data received
+         * @return True if the message has been handled correctly, false otherwise.
+         */
+        boolean handleUnsolicitedMessage(ByteBuffer dataReceived, int receivedLen);
+    }
+
+    private final MessageQueue mMsgQueue;
+
+    // lmkd connection listener
+    private final LmkdConnectionListener mListener;
+
+    // mutex to synchronize access to the socket
+    private final Object mLmkdSocketLock = new Object();
+
+    // socket to communicate with lmkd
+    @GuardedBy("mLmkdSocketLock")
+    private LocalSocket mLmkdSocket = null;
+
+    // socket I/O streams
+    @GuardedBy("mLmkdSocketLock")
+    private OutputStream mLmkdOutputStream = null;
+    @GuardedBy("mLmkdSocketLock")
+    private InputStream mLmkdInputStream = null;
+
+    // buffer to store incoming data
+    private final ByteBuffer mInputBuf =
+            ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
+
+    // object to protect mReplyBuf and to wait/notify when reply is received
+    private final Object mReplyBufLock = new Object();
+
+    // reply buffer
+    @GuardedBy("mReplyBufLock")
+    private ByteBuffer mReplyBuf = null;
+
+    ////////////////////  END FIELDS  ////////////////////
+
+    LmkdConnection(MessageQueue msgQueue, LmkdConnectionListener listener) {
+        mMsgQueue = msgQueue;
+        mListener = listener;
+    }
+
+    boolean connect() {
+        synchronized (mLmkdSocketLock) {
+            if (mLmkdSocket != null) {
+                return true;
+            }
+            // temporary sockets and I/O streams
+            final LocalSocket socket = openSocket();
+
+            if (socket == null) {
+                Slog.w(TAG, "Failed to connect to lowmemorykiller, retry later");
+                return false;
+            }
+
+            final OutputStream ostream;
+            final InputStream istream;
+            try {
+                ostream = socket.getOutputStream();
+                istream = socket.getInputStream();
+            } catch (IOException ex) {
+                IoUtils.closeQuietly(socket);
+                return false;
+            }
+            // execute onConnect callback
+            if (mListener != null && !mListener.onConnect(ostream)) {
+                Slog.w(TAG, "Failed to communicate with lowmemorykiller, retry later");
+                IoUtils.closeQuietly(socket);
+                return false;
+            }
+            // connection established
+            mLmkdSocket = socket;
+            mLmkdOutputStream = ostream;
+            mLmkdInputStream = istream;
+            mMsgQueue.addOnFileDescriptorEventListener(mLmkdSocket.getFileDescriptor(),
+                    EVENT_INPUT | EVENT_ERROR,
+                    new MessageQueue.OnFileDescriptorEventListener() {
+                        public int onFileDescriptorEvents(FileDescriptor fd, int events) {
+                            return fileDescriptorEventHandler(fd, events);
+                        }
+                    }
+            );
+            mLmkdSocketLock.notifyAll();
+        }
+        return true;
+    }
+
+    private int fileDescriptorEventHandler(FileDescriptor fd, int events) {
+        if (mListener == null) {
+            return 0;
+        }
+        if ((events & EVENT_INPUT) != 0) {
+            processIncomingData();
+        }
+        if ((events & EVENT_ERROR) != 0) {
+            synchronized (mLmkdSocketLock) {
+                // stop listening on this socket
+                mMsgQueue.removeOnFileDescriptorEventListener(
+                        mLmkdSocket.getFileDescriptor());
+                IoUtils.closeQuietly(mLmkdSocket);
+                mLmkdSocket = null;
+            }
+            // wake up reply waiters if any
+            synchronized (mReplyBufLock) {
+                if (mReplyBuf != null) {
+                    mReplyBuf = null;
+                    mReplyBufLock.notifyAll();
+                }
+            }
+            // notify listener
+            mListener.onDisconnect();
+            return 0;
+        }
+        return (EVENT_INPUT | EVENT_ERROR);
+    }
+
+    private void processIncomingData() {
+        int len = read(mInputBuf);
+        if (len > 0) {
+            synchronized (mReplyBufLock) {
+                if (mReplyBuf != null) {
+                    if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
+                        // copy into reply buffer
+                        mReplyBuf.put(mInputBuf.array(), 0, len);
+                        mReplyBuf.rewind();
+                        // wakeup the waiting thread
+                        mReplyBufLock.notifyAll();
+                    } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
+                        // received unexpected packet
+                        // treat this as an error
+                        mReplyBuf = null;
+                        mReplyBufLock.notifyAll();
+                        Slog.e(TAG, "Received an unexpected packet from lmkd");
+                    }
+                } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
+                    // received asynchronous communication from lmkd
+                    // but we don't recognize it.
+                    Slog.w(TAG, "Received an unexpected packet from lmkd");
+                }
+            }
+        }
+    }
+
+    boolean isConnected() {
+        synchronized (mLmkdSocketLock) {
+            return (mLmkdSocket != null);
+        }
+    }
+
+    boolean waitForConnection(long timeoutMs) {
+        synchronized (mLmkdSocketLock) {
+            if (mLmkdSocket != null) {
+                return true;
+            }
+            try {
+                mLmkdSocketLock.wait(timeoutMs);
+                return (mLmkdSocket != null);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+    }
+
+    private LocalSocket openSocket() {
+        final LocalSocket socket;
+
+        try {
+            socket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
+            socket.connect(
+                    new LocalSocketAddress("lmkd",
+                        LocalSocketAddress.Namespace.RESERVED));
+        } catch (IOException ex) {
+            Slog.e(TAG, "Connection failed: " + ex.toString());
+            return null;
+        }
+        return socket;
+    }
+
+    private boolean write(ByteBuffer buf) {
+        synchronized (mLmkdSocketLock) {
+            try {
+                mLmkdOutputStream.write(buf.array(), 0, buf.position());
+            } catch (IOException ex) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private int read(ByteBuffer buf) {
+        synchronized (mLmkdSocketLock) {
+            try {
+                return mLmkdInputStream.read(buf.array(), 0, buf.array().length);
+            } catch (IOException ex) {
+            }
+            return -1;
+        }
+    }
+
+    /**
+     * Exchange a request/reply packets with lmkd
+     *
+     * @param req The buffer holding the request data to be sent
+     * @param repl The buffer to receive the reply
+     */
+    public boolean exchange(ByteBuffer req, ByteBuffer repl) {
+        if (repl == null) {
+            return write(req);
+        }
+
+        boolean result = false;
+        // set reply buffer to user-defined one to fill it
+        synchronized (mReplyBufLock) {
+            mReplyBuf = repl;
+
+            if (write(req)) {
+                try {
+                    // wait for the reply
+                    mReplyBufLock.wait();
+                    result = (mReplyBuf != null);
+                } catch (InterruptedException ie) {
+                    result = false;
+                }
+            }
+
+            // reset reply buffer
+            mReplyBuf = null;
+        }
+        return result;
+    }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a2670d8..f557976 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -57,8 +57,6 @@
 import android.content.pm.IPackageManager;
 import android.content.res.Resources;
 import android.graphics.Point;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
 import android.os.AppZygote;
 import android.os.Binder;
 import android.os.Build;
@@ -96,17 +94,15 @@
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.Watchdog;
+import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.wm.ActivityServiceConnectionsHolder;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.VMRuntime;
 
-import libcore.io.IoUtils;
-
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.nio.ByteBuffer;
@@ -117,11 +113,6 @@
 
 /**
  * Activity manager code dealing with processes.
- *
- * Method naming convention:
- * <ul>
- * <li> Methods suffixed with "LS" should be called within the {@link #sLmkdSocketLock} lock.
- * </ul>
  */
 public final class ProcessList {
     static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
@@ -255,18 +246,30 @@
             "persist.device_config.runtime_native.use_app_image_startup_cache";
 
     // Low Memory Killer Daemon command codes.
-    // These must be kept in sync with the definitions in lmkd.c
+    // These must be kept in sync with lmk_cmd definitions in lmkd.h
     //
     // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
     // LMK_PROCPRIO <pid> <uid> <prio>
     // LMK_PROCREMOVE <pid>
     // LMK_PROCPURGE
     // LMK_GETKILLCNT
+    // LMK_SUBSCRIBE
+    // LMK_PROCKILL
     static final byte LMK_TARGET = 0;
     static final byte LMK_PROCPRIO = 1;
     static final byte LMK_PROCREMOVE = 2;
     static final byte LMK_PROCPURGE = 3;
     static final byte LMK_GETKILLCNT = 4;
+    static final byte LMK_SUBSCRIBE = 5;
+    static final byte LMK_PROCKILL = 6; // Note: this is an unsolicated command
+
+    // Low Memory Killer Daemon command codes.
+    // These must be kept in sync with async_event_type definitions in lmkd.h
+    //
+    static final int LMK_ASYNC_EVENT_KILL = 0;
+
+    // lmkd reconnect delay in msecs
+    private static final long LMKD_RECONNECT_DELAY_MS = 1000;
 
     ActivityManagerService mService = null;
 
@@ -302,16 +305,9 @@
 
     private boolean mHaveDisplaySize;
 
-    private static Object sLmkdSocketLock = new Object();
+    private static LmkdConnection sLmkdConnection = null;
 
-    @GuardedBy("sLmkdSocketLock")
-    private static LocalSocket sLmkdSocket;
-
-    @GuardedBy("sLmkdSocketLock")
-    private static OutputStream sLmkdOutputStream;
-
-    @GuardedBy("sLmkdSocketLock")
-    private static InputStream sLmkdInputStream;
+    private boolean mOomLevelsSet = false;
 
     /**
      * Temporary to avoid allocations.  Protected by main lock.
@@ -369,6 +365,12 @@
     ActiveUids mActiveUids;
 
     /**
+     * The listener who is intereted with the lmkd kills.
+     */
+    @GuardedBy("mService")
+    private LmkdKillListener mLmkdKillListener = null;
+
+    /**
      * The currently running isolated processes.
      */
     final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
@@ -384,6 +386,15 @@
     final ArrayMap<AppZygote, ArrayList<ProcessRecord>> mAppZygoteProcesses =
             new ArrayMap<AppZygote, ArrayList<ProcessRecord>>();
 
+    private PlatformCompat mPlatformCompat = null;
+
+    interface LmkdKillListener {
+        /**
+         * Called when there is a process kill by lmkd.
+         */
+        void onLmkdKillOccurred(int pid, int uid);
+    }
+
     final class IsolatedUidRange {
         @VisibleForTesting
         public final int mFirstUid;
@@ -536,6 +547,8 @@
 
     final class KillHandler extends Handler {
         static final int KILL_PROCESS_GROUP_MSG = 4000;
+        static final int LMKD_RECONNECT_MSG = 4001;
+        static final int LMKD_PROC_KILLED_MSG = 4002;
 
         public KillHandler(Looper looper) {
             super(looper, null, true);
@@ -549,6 +562,18 @@
                     Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
+                case LMKD_RECONNECT_MSG:
+                    if (!sLmkdConnection.connect()) {
+                        Slog.i(TAG, "Failed to connect to lmkd, retry after "
+                                + LMKD_RECONNECT_DELAY_MS + " ms");
+                        // retry after LMKD_RECONNECT_DELAY_MS
+                        sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+                                KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
+                    }
+                    break;
+                case LMKD_PROC_KILLED_MSG:
+                    handleLmkdProcKilled(msg.arg1 /* pid */, msg.arg2 /* uid */);
+                    break;
 
                 default:
                     super.handleMessage(msg);
@@ -565,15 +590,61 @@
         updateOomLevels(0, 0, false);
     }
 
-    void init(ActivityManagerService service, ActiveUids activeUids) {
+    void init(ActivityManagerService service, ActiveUids activeUids,
+            PlatformCompat platformCompat) {
         mService = service;
         mActiveUids = activeUids;
+        mPlatformCompat = platformCompat;
 
         if (sKillHandler == null) {
             sKillThread = new ServiceThread(TAG + ":kill",
                     THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
             sKillThread.start();
             sKillHandler = new KillHandler(sKillThread.getLooper());
+            sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
+                    new LmkdConnection.LmkdConnectionListener() {
+                        @Override
+                        public boolean onConnect(OutputStream ostream) {
+                            Slog.i(TAG, "Connection with lmkd established");
+                            return onLmkdConnect(ostream);
+                        }
+                        @Override
+                        public void onDisconnect() {
+                            Slog.w(TAG, "Lost connection to lmkd");
+                            // start reconnection after delay to let lmkd restart
+                            sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+                                    KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
+                        }
+                        @Override
+                        public boolean isReplyExpected(ByteBuffer replyBuf,
+                                ByteBuffer dataReceived, int receivedLen) {
+                            // compare the preambule (currently one integer) to check if
+                            // this is the reply packet we are waiting for
+                            return (receivedLen == replyBuf.array().length
+                                    && dataReceived.getInt(0) == replyBuf.getInt(0));
+                        }
+
+                        @Override
+                        public boolean handleUnsolicitedMessage(ByteBuffer dataReceived,
+                                int receivedLen) {
+                            if (receivedLen < 4) {
+                                return false;
+                            }
+                            switch (dataReceived.getInt(0)) {
+                                case LMK_PROCKILL:
+                                    if (receivedLen != 12) {
+                                        return false;
+                                    }
+                                    sKillHandler.obtainMessage(KillHandler.LMKD_PROC_KILLED_MSG,
+                                            dataReceived.getInt(4), dataReceived.getInt(8))
+                                            .sendToTarget();
+                                    return true;
+                                default:
+                                    return false;
+                            }
+                        }
+                    }
+            );
         }
     }
 
@@ -679,6 +750,7 @@
 
             writeLmkd(buf, null);
             SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
+            mOomLevelsSet = true;
         }
         // GB: 2048,3072,4096,6144,7168,8192
         // HC: 8192,10240,12288,14336,16384,20480
@@ -1218,93 +1290,55 @@
         buf.putInt(LMK_GETKILLCNT);
         buf.putInt(min_oom_adj);
         buf.putInt(max_oom_adj);
-        if (writeLmkd(buf, repl)) {
-            int i = repl.getInt();
-            if (i != LMK_GETKILLCNT) {
-                Slog.e("ActivityManager", "Failed to get kill count, code mismatch");
-                return null;
-            }
+        // indicate what we are waiting for
+        repl.putInt(LMK_GETKILLCNT);
+        repl.rewind();
+        if (writeLmkd(buf, repl) && repl.getInt() == LMK_GETKILLCNT) {
             return new Integer(repl.getInt());
         }
         return null;
     }
 
-    @GuardedBy("sLmkdSocketLock")
-    private static boolean openLmkdSocketLS() {
+    boolean onLmkdConnect(OutputStream ostream) {
         try {
-            sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
-            sLmkdSocket.connect(
-                new LocalSocketAddress("lmkd",
-                        LocalSocketAddress.Namespace.RESERVED));
-            sLmkdOutputStream = sLmkdSocket.getOutputStream();
-            sLmkdInputStream = sLmkdSocket.getInputStream();
-        } catch (IOException ex) {
-            Slog.w(TAG, "lowmemorykiller daemon socket open failed");
-            sLmkdSocket = null;
-            return false;
-        }
-
-        return true;
-    }
-
-    // Never call directly, use writeLmkd() instead
-    @GuardedBy("sLmkdSocketLock")
-    private static boolean writeLmkdCommandLS(ByteBuffer buf) {
-        try {
-            sLmkdOutputStream.write(buf.array(), 0, buf.position());
-        } catch (IOException ex) {
-            Slog.w(TAG, "Error writing to lowmemorykiller socket");
-            IoUtils.closeQuietly(sLmkdSocket);
-            sLmkdSocket = null;
-            return false;
-        }
-        return true;
-    }
-
-    // Never call directly, use writeLmkd() instead
-    @GuardedBy("sLmkdSocketLock")
-    private static boolean readLmkdReplyLS(ByteBuffer buf) {
-        int len;
-        try {
-            len = sLmkdInputStream.read(buf.array(), 0, buf.array().length);
-            if (len == buf.array().length) {
-                return true;
+            // Purge any previously registered pids
+            ByteBuffer buf = ByteBuffer.allocate(4);
+            buf.putInt(LMK_PROCPURGE);
+            ostream.write(buf.array(), 0, buf.position());
+            if (mOomLevelsSet) {
+                // Reset oom_adj levels
+                buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
+                buf.putInt(LMK_TARGET);
+                for (int i = 0; i < mOomAdj.length; i++) {
+                    buf.putInt((mOomMinFree[i] * 1024) / PAGE_SIZE);
+                    buf.putInt(mOomAdj[i]);
+                }
+                ostream.write(buf.array(), 0, buf.position());
             }
+            // Subscribe for kill event notifications
+            buf = ByteBuffer.allocate(4 * 2);
+            buf.putInt(LMK_SUBSCRIBE);
+            buf.putInt(LMK_ASYNC_EVENT_KILL);
+            ostream.write(buf.array(), 0, buf.position());
         } catch (IOException ex) {
-            Slog.w(TAG, "Error reading from lowmemorykiller socket");
+            return false;
         }
-
-        IoUtils.closeQuietly(sLmkdSocket);
-        sLmkdSocket = null;
-        return false;
+        return true;
     }
 
     private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
-        synchronized (sLmkdSocketLock) {
-            for (int i = 0; i < 3; i++) {
-                if (sLmkdSocket == null) {
-                    if (openLmkdSocketLS() == false) {
-                        try {
-                            Thread.sleep(1000);
-                        } catch (InterruptedException ie) {
-                        }
-                        continue;
-                    }
+        if (!sLmkdConnection.isConnected()) {
+            // try to connect immediately and then keep retrying
+            sKillHandler.sendMessage(
+                    sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG));
 
-                    // Purge any previously registered pids
-                    ByteBuffer purge_buf = ByteBuffer.allocate(4);
-                    purge_buf.putInt(LMK_PROCPURGE);
-                    if (writeLmkdCommandLS(purge_buf) == false) {
-                        // Write failed, skip the rest and retry
-                        continue;
-                    }
-                }
-                if (writeLmkdCommandLS(buf) && (repl == null || readLmkdReplyLS(repl))) {
-                    return true;
-                }
+            // wait for connection retrying 3 times (up to 3 seconds)
+            if (!sLmkdConnection.waitForConnection(3 * LMKD_RECONNECT_DELAY_MS)) {
+                return false;
             }
         }
-        return false;
+
+        return sLmkdConnection.exchange(buf, repl);
     }
 
     static void killProcessGroup(int uid, int pid) {
@@ -1657,6 +1691,10 @@
             Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
                     + " with non-zero pid:" + app.pid);
         }
+        app.mDisabledCompatChanges = null;
+        if (mPlatformCompat != null) {
+            app.mDisabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
+        }
         final long startSeq = app.startSeq = ++mProcStartSeqCounter;
         app.setStartParams(uid, hostingRecord, seInfo, startTime);
         app.setUsingWrapper(invokeWith != null
@@ -1811,8 +1849,8 @@
                 startResult = startWebView(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
-                        app.info.dataDir, null, app.info.packageName,
-                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+                        app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
+                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             } else if (hostingRecord.usesAppZygote()) {
                 final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
 
@@ -1820,14 +1858,15 @@
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
-                        /*useUsapPool=*/ false,
-                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+                        /*useUsapPool=*/ false, app.mDisabledCompatChanges,
+                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, app.info.packageName,
-                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
+                        app.mDisabledCompatChanges,
+                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkSlow(startTime, "startProcess: returned from zygote!");
             return startResult;
@@ -3204,4 +3243,28 @@
             mService.doStopUidLocked(uidRec.uid, uidRec);
         }
     }
+
+    void setLmkdKillListener(final LmkdKillListener listener) {
+        synchronized (mService) {
+            mLmkdKillListener = listener;
+        }
+    }
+
+    private void handleLmkdProcKilled(final int pid, final int uid) {
+        // Log only now
+        if (DEBUG_PROCESSES) {
+            Slog.i(TAG, "lmkd kill: pid=" + pid + " uid=" + uid);
+        }
+
+        if (mService == null) {
+            return;
+        }
+        // Notify any interesed party regarding the lmkd kills
+        synchronized (mService) {
+            final LmkdKillListener listener = mLmkdKillListener;
+            if (listener != null) {
+                mService.mHandler.post(()-> listener.onLmkdKillOccurred(pid, uid));
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index ea30842..8c1a0d3 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -307,6 +307,8 @@
     long startTime;
     // This will be same as {@link #uid} usually except for some apps used during factory testing.
     int startUid;
+    // set of disabled compat changes for the process (all others are enabled)
+    long[] mDisabledCompatChanges;
 
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startTime) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 90973a8..4a5a212 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -35,7 +35,6 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.text.TextUtils;
-import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
@@ -44,6 +43,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Set;
 
 /**
  * Class to manage the inventory of all connected devices.
@@ -56,13 +58,10 @@
 
     // Actual list of connected devices
     // Key for map created from DeviceInfo.makeDeviceListKey()
-    private final ArrayMap<String, DeviceInfo> mConnectedDevices = new ArrayMap<>();
+    private final LinkedHashMap<String, DeviceInfo> mConnectedDevices = new LinkedHashMap<>();
 
     private @NonNull AudioDeviceBroker mDeviceBroker;
 
-    // cache of the address of the last dock the device was connected to
-    private String mDockAddress;
-
     // Monitoring of audio routes.  Protected by mAudioRoutes.
     final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers =
@@ -146,8 +145,7 @@
      */
     /*package*/ void onRestoreDevices() {
         synchronized (mConnectedDevices) {
-            for (int i = 0; i < mConnectedDevices.size(); i++) {
-                DeviceInfo di = mConnectedDevices.valueAt(i);
+            for (DeviceInfo di : mConnectedDevices.values()) {
                 AudioSystem.setDeviceConnectionState(
                         di.mDeviceType,
                         AudioSystem.DEVICE_STATE_AVAILABLE,
@@ -167,7 +165,7 @@
         int a2dpVolume = btInfo.getVolume();
         if (AudioService.DEBUG_DEVICES) {
             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice + " state="
-                    + state + " is dock=" + btDevice.isBluetoothDock() + " vol=" + a2dpVolume);
+                    + state + " vol=" + a2dpVolume);
         }
         String address = btDevice.getAddress();
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
@@ -195,33 +193,10 @@
                         mDeviceBroker.postBluetoothA2dpDeviceConfigChange(btDevice);
                     }
                 } else {
-                    if (btDevice.isBluetoothDock()) {
-                        if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                            // introduction of a delay for transient disconnections of docks when
-                            // power is rapidly turned off/on, this message will be canceled if
-                            // we reconnect the dock under a preset delay
-                            makeA2dpDeviceUnavailableLater(address,
-                                    AudioDeviceBroker.BTA2DP_DOCK_TIMEOUT_MS);
-                            // the next time isConnected is evaluated, it will be false for the dock
-                        }
-                    } else {
-                        makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
-                    }
+                    makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
                 }
-            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                if (btDevice.isBluetoothDock()) {
-                    // this could be a reconnection after a transient disconnection
-                    mDeviceBroker.cancelA2dpDockTimeout();
-                    mDockAddress = address;
-                } else {
-                    // this could be a connection of another A2DP device before the timeout of
-                    // a dock: cancel the dock timeout, and make the dock unavailable now
-                    if (mDeviceBroker.hasScheduledA2dpDockTimeout() && mDockAddress != null) {
-                        mDeviceBroker.cancelA2dpDockTimeout();
-                        makeA2dpDeviceUnavailableNow(mDockAddress,
-                                AudioSystem.AUDIO_FORMAT_DEFAULT);
-                    }
-                }
+            } else if (state == BluetoothProfile.STATE_CONNECTED) {
+                // device is not already connected
                 if (a2dpVolume != -1) {
                     mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
                             // convert index to internal representation in VolumeStreamState
@@ -372,9 +347,14 @@
         mDeviceBroker.postObserveDevicesForAllStreams();
     }
 
-    private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
-            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
-                    | AudioSystem.DEVICE_OUT_LINE | AudioSystem.DEVICE_OUT_ALL_USB;
+    private static final Set<Integer> DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET;
+    static {
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET = new HashSet<>();
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+    }
 
     /*package*/ void onSetWiredDeviceConnectionState(
                             AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
@@ -382,7 +362,7 @@
 
         synchronized (mConnectedDevices) {
             if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
-                    && ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
+                    && DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
                 mDeviceBroker.setBluetoothA2dpOnInt(true,
                         "onSetWiredDeviceConnectionState state DISCONNECTED");
             }
@@ -393,7 +373,7 @@
                 return;
             }
             if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
-                if ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
+                if (DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET.contains(wdcs.mType)) {
                     mDeviceBroker.setBluetoothA2dpOnInt(false,
                             "onSetWiredDeviceConnectionState state not DISCONNECTED");
                 }
@@ -666,9 +646,6 @@
                 DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
         // Remove A2DP routes as well
         setCurrentAudioRouteNameIfPossible(null);
-        if (mDockAddress == address) {
-            mDockAddress = null;
-        }
     }
 
     @GuardedBy("mConnectedDevices")
@@ -764,13 +741,19 @@
     // - none of these devices are connected anymore after one is disconnected AND
     // - the device being disconnected is actually used for music.
     // Access synchronized on mConnectedDevices
-    private int mBecomingNoisyIntentDevices =
-            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
-                    | AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI
-                    | AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET
-                    | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET
-                    | AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE
-                    | AudioSystem.DEVICE_OUT_HEARING_AID;
+    private static final Set<Integer> BECOMING_NOISY_INTENT_DEVICES_SET;
+    static {
+        BECOMING_NOISY_INTENT_DEVICES_SET = new HashSet<>();
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HDMI);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
+        BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+        BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+    }
 
     // must be called before removing the device from mConnectedDevices
     // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
@@ -781,16 +764,15 @@
         if (state != AudioService.CONNECTION_STATE_DISCONNECTED) {
             return 0;
         }
-        if ((device & mBecomingNoisyIntentDevices) == 0) {
+        if (!BECOMING_NOISY_INTENT_DEVICES_SET.contains(device)) {
             return 0;
         }
         int delay = 0;
-        int devices = 0;
-        for (int i = 0; i < mConnectedDevices.size(); i++) {
-            int dev = mConnectedDevices.valueAt(i).mDeviceType;
-            if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
-                    && ((dev & mBecomingNoisyIntentDevices) != 0)) {
-                devices |= dev;
+        Set<Integer> devices = new HashSet<>();
+        for (DeviceInfo di : mConnectedDevices.values()) {
+            if (((di.mDeviceType & AudioSystem.DEVICE_BIT_IN) == 0)
+                    && BECOMING_NOISY_INTENT_DEVICES_SET.contains(di.mDeviceType)) {
+                devices.add(di.mDeviceType);
             }
         }
         if (musicDevice == AudioSystem.DEVICE_NONE) {
@@ -801,8 +783,9 @@
         // because music routing is altered in this case.
         // also checks whether media routing if affected by a dynamic policy or mirroring
         if (((device == musicDevice) || mDeviceBroker.isInCommunication())
-                && (device == devices) && !mDeviceBroker.hasMediaDynamicPolicy()
-                        && ((musicDevice & AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) == 0)) {
+                && AudioSystem.isSingleAudioDeviceType(devices, device)
+                && !mDeviceBroker.hasMediaDynamicPolicy()
+                && (musicDevice != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)) {
             if (!AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0 /*not looking in past*/)
                     && !mDeviceBroker.hasAudioFocusUsers()) {
                 // no media playback, not a "becoming noisy" situation, otherwise it could cause
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bae9680..25fdf64 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -147,6 +147,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -501,18 +502,20 @@
     private volatile IRingtonePlayer mRingtonePlayer;
 
     // Devices for which the volume is fixed (volume is either max or muted)
-    int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
-            AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
-            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
-            AudioSystem.DEVICE_OUT_HDMI_ARC |
-            AudioSystem.DEVICE_OUT_SPDIF |
-            AudioSystem.DEVICE_OUT_AUX_LINE;
+    Set<Integer> mFixedVolumeDevices = new HashSet<>(Arrays.asList(
+            AudioSystem.DEVICE_OUT_HDMI,
+            AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
+            AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
+            AudioSystem.DEVICE_OUT_HDMI_ARC,
+            AudioSystem.DEVICE_OUT_SPDIF,
+            AudioSystem.DEVICE_OUT_AUX_LINE));
     // Devices for which the volume is always max, no volume panel
-    int mFullVolumeDevices = 0;
+    Set<Integer> mFullVolumeDevices = new HashSet<>();
     // Devices for the which use the "absolute volume" concept (framework sends audio signal
     // full scale, and volume control separately) and can be used for multiple use cases reflected
     // by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
-    int mAbsVolumeMultiModeCaseDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
+    Set<Integer> mAbsVolumeMultiModeCaseDevices = new HashSet<>(
+            Arrays.asList(AudioSystem.DEVICE_OUT_HEARING_AID));
 
     private final boolean mMonitorRotation;
 
@@ -863,13 +866,14 @@
                 }
                 mHdmiTvClient = mHdmiManager.getTvClient();
                 if (mHdmiTvClient != null) {
-                    mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
+                    mFixedVolumeDevices.removeAll(
+                            AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET);
                 }
                 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
                 if (mHdmiPlaybackClient != null) {
                     // not a television: HDMI output will be always at max
-                    mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
-                    mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+                    mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
+                    mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
                 }
                 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
             }
@@ -1126,7 +1130,7 @@
             @AudioService.ConnectionState int state, String caller) {
         if (state == AudioService.CONNECTION_STATE_CONNECTED) {
             // DEVICE_OUT_HDMI is now connected
-            if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
+            if (mSafeMediaVolumeDevices.contains(AudioSystem.DEVICE_OUT_HDMI)) {
                 sendMsg(mAudioHandler,
                         MSG_CHECK_MUSIC_ACTIVE,
                         SENDMSG_REPLACE,
@@ -1757,8 +1761,8 @@
 
         // skip a2dp absolute volume control request when the device
         // is not an a2dp device
-        if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
-            (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
 
@@ -1779,14 +1783,14 @@
 
         flags &= ~AudioManager.FLAG_FIXED_VOLUME;
         if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
-                ((device & mFixedVolumeDevices) != 0)) {
+                mFixedVolumeDevices.contains(device)) {
             flags |= AudioManager.FLAG_FIXED_VOLUME;
 
             // Always toggle between max safe volume and 0 for fixed volume devices where safe
             // volume is enforced, and max and 0 for the others.
             // This is simulated by stepping by the full allowed volume range
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
-                    (device & mSafeMediaVolumeDevices) != 0) {
+                    mSafeMediaVolumeDevices.contains(device)) {
                 step = safeMediaVolumeIndex(device);
             } else {
                 step = streamState.getMaxIndex();
@@ -1856,7 +1860,7 @@
                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
                 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
                 mVolumeController.postDisplaySafeVolumeWarning(flags);
-            } else if (((device & mFullVolumeDevices) == 0)
+            } else if (!mFullVolumeDevices.contains(device)
                     && (streamState.adjustIndex(direction * step, device, caller)
                             || streamState.mIsMuted)) {
                 // Post message to set system volume (it in turn will post a
@@ -1885,9 +1889,9 @@
             int newIndex = mStreamStates[streamType].getIndex(device);
 
             // Check if volume update should be send to AVRCP
-            if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
-                (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
-                (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
+            if (streamTypeAlias == AudioSystem.STREAM_MUSIC
+                    && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
                     Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
                             + newIndex + "stream=" + streamType);
@@ -1896,7 +1900,7 @@
             }
 
             // Check if volume update should be send to Hearing Aid
-            if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+            if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 // only modify the hearing aid attenuation when the stream to modify matches
                 // the one expected by the hearing aid
                 if (streamType == getHearingAidStreamType()) {
@@ -1918,7 +1922,7 @@
                     if (mHdmiCecSink
                             && streamTypeAlias == AudioSystem.STREAM_MUSIC
                             // vol change on a full volume device
-                            && ((device & mFullVolumeDevices) != 0)) {
+                            && mFullVolumeDevices.contains(device)) {
                         int keyCode = KeyEvent.KEYCODE_UNKNOWN;
                         switch (direction) {
                             case AudioManager.ADJUST_RAISE:
@@ -2286,13 +2290,17 @@
 
         int streamType = getHearingAidStreamType(newMode);
 
-        final int device = AudioSystem.getDevicesForStream(streamType);
-        if ((device & mAbsVolumeMultiModeCaseDevices) == 0) {
+        final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
+                AudioSystem.getDevicesForStream(streamType));
+        final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes(
+                mAbsVolumeMultiModeCaseDevices, deviceTypes);
+        if (absVolumeMultiModeCaseDevices.isEmpty()) {
             return;
         }
 
         // handling of specific interfaces goes here:
-        if ((device & mAbsVolumeMultiModeCaseDevices) == AudioSystem.DEVICE_OUT_HEARING_AID) {
+        if (AudioSystem.isSingleAudioDeviceType(
+                absVolumeMultiModeCaseDevices, AudioSystem.DEVICE_OUT_HEARING_AID)) {
             final int index = getStreamVolume(streamType);
             sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_MODE_CHANGE_HEARING_AID,
                     newMode, streamType, index));
@@ -2319,8 +2327,8 @@
 
         // skip a2dp absolute volume control request when the device
         // is not an a2dp device
-        if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
-            (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
+        if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
             return;
         }
         // If we are being called by the system (e.g. hardware keys) check for current user
@@ -2352,7 +2360,7 @@
             index = rescaleIndex(index * 10, streamType, streamTypeAlias);
 
             if (streamTypeAlias == AudioSystem.STREAM_MUSIC
-                    && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
+                    && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                     && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                 if (DEBUG_VOL) {
                     Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
@@ -2361,7 +2369,7 @@
                 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
             }
 
-            if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0
+            if (device == AudioSystem.DEVICE_OUT_HEARING_AID
                     && streamType == getHearingAidStreamType()) {
                 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
                         + " stream=" + streamType);
@@ -2374,13 +2382,13 @@
 
             flags &= ~AudioManager.FLAG_FIXED_VOLUME;
             if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
-                    ((device & mFixedVolumeDevices) != 0)) {
+                    mFixedVolumeDevices.contains(device)) {
                 flags |= AudioManager.FLAG_FIXED_VOLUME;
 
                 // volume is either 0 or max allowed for fixed volume devices
                 if (index != 0) {
                     if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
-                            (device & mSafeMediaVolumeDevices) != 0) {
+                            mSafeMediaVolumeDevices.contains(device)) {
                         index = safeMediaVolumeIndex(device);
                     } else {
                         index = streamState.getMaxIndex();
@@ -2563,7 +2571,7 @@
 
         if (streamType == AudioSystem.STREAM_MUSIC) {
             flags = updateFlagsForTvPlatform(flags);
-            if ((device & mFullVolumeDevices) != 0) {
+            if (mFullVolumeDevices.contains(device)) {
                 flags &= ~AudioManager.FLAG_SHOW_UI;
             }
         }
@@ -2609,7 +2617,7 @@
                                     int device,
                                     boolean force,
                                     String caller) {
-        if ((device & mFullVolumeDevices) != 0) {
+        if (mFullVolumeDevices.contains(device)) {
             return;
         }
         VolumeStreamState streamState = mStreamStates[streamType];
@@ -2726,8 +2734,8 @@
                 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
                     mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
                     if (mRmtSbmxFullVolRefCount == 0) {
-                        mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
-                        mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                        mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+                        mFixedVolumeDevices.add(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
                         applyRequired = true;
                     }
                     mRmtSbmxFullVolRefCount++;
@@ -2736,8 +2744,8 @@
                 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
                     mRmtSbmxFullVolRefCount--;
                     if (mRmtSbmxFullVolRefCount == 0) {
-                        mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
-                        mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                        mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+                        mFixedVolumeDevices.remove(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
                         applyRequired = true;
                     }
                 }
@@ -2822,7 +2830,7 @@
                 index = 0;
             }
             if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
-                    (device & mFixedVolumeDevices) != 0) {
+                    mFixedVolumeDevices.contains(device)) {
                 index = mStreamStates[streamType].getMaxIndex();
             }
             return (index + 5) / 10;
@@ -3680,7 +3688,7 @@
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
                 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
 
-                if ((device & mSafeMediaVolumeDevices) != 0) {
+                if (mSafeMediaVolumeDevices.contains(device)) {
                     sendMsg(mAudioHandler,
                             MSG_CHECK_MUSIC_ACTIVE,
                             SENDMSG_REPLACE,
@@ -4221,6 +4229,8 @@
             // retain the device on the A2DP output as the other must not correspond to an active
             // selection if not the speaker.
             //  - HDMI-CEC system audio mode only output: give priority to available item in order.
+            // FIXME: Haven't applied audio device type refactor to this API
+            //  as it is going to be deprecated.
             if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
                 device = AudioSystem.DEVICE_OUT_SPEAKER;
             } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
@@ -4230,7 +4240,11 @@
             } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
                 device = AudioSystem.DEVICE_OUT_AUX_LINE;
             } else {
-                device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
+                for (int deviceType : AudioSystem.DEVICE_OUT_ALL_A2DP_SET) {
+                    if ((deviceType & device) == deviceType) {
+                        return deviceType;
+                    }
+                }
             }
         }
         return device;
@@ -4363,12 +4377,16 @@
         mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
     }
 
-    private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
-            AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
-            AudioSystem.DEVICE_OUT_LINE |
-            AudioSystem.DEVICE_OUT_ALL_A2DP |
-            AudioSystem.DEVICE_OUT_ALL_USB |
-            AudioSystem.DEVICE_OUT_HDMI;
+    private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET;
+    static {
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET = new HashSet<>();
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
+        DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI);
+    }
 
     /** only public for mocking/spying, do not call outside of AudioService */
     @VisibleForTesting
@@ -4384,7 +4402,7 @@
         }
 
         if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
-                && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
+                && DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.contains(newDevice)
                 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
                 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
                 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
@@ -4513,14 +4531,7 @@
                 }
             }
             synchronized (VolumeStreamState.class) {
-                int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
-
-                for (int i = 0; remainingDevices != 0; i++) {
-                    int device = (1 << i);
-                    if ((device & remainingDevices) == 0) {
-                        continue;
-                    }
-                    remainingDevices &= ~device;
+                for (int device : AudioSystem.DEVICE_OUT_ALL_SET) {
 
                     // retrieve current volume for device
                     // if no volume stored for current stream and device, use default volume if default
@@ -4580,11 +4591,12 @@
             int index;
             if (mIsMuted) {
                 index = 0;
-            } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
+            } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                    && isAvrcpAbsVolSupported) {
                 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
-            } else if ((device & mFullVolumeDevices) != 0) {
+            } else if (mFullVolumeDevices.contains(device)) {
                 index = (mIndexMax + 5)/10;
-            } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+            } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                 index = (mIndexMax + 5)/10;
             } else {
                 index = (getIndex(device) + 5)/10;
@@ -4602,12 +4614,12 @@
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
                         if (mIsMuted) {
                             index = 0;
-                        } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
-                                isAvrcpAbsVolSupported) {
+                        } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+                                && isAvrcpAbsVolSupported) {
                             index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
-                        } else if ((device & mFullVolumeDevices) != 0) {
+                        } else if (mFullVolumeDevices.contains(device)) {
                             index = (mIndexMax + 5)/10;
-                        } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+                        } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                             index = (mIndexMax + 5)/10;
                         } else {
                             index = (mIndexMap.valueAt(i) + 5)/10;
@@ -4668,7 +4680,7 @@
                             && device == AudioSystem.DEVICE_OUT_SPEAKER) {
                         for (int i = 0; i < mIndexMap.size(); i++) {
                             int otherDevice = mIndexMap.keyAt(i);
-                            if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
+                            if (AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(otherDevice)) {
                                 mIndexMap.put(otherDevice, index);
                             }
                         }
@@ -4806,8 +4818,8 @@
                     for (int i = 0; i < mIndexMap.size(); i++) {
                         int device = mIndexMap.keyAt(i);
                         int index = mIndexMap.valueAt(i);
-                        if (((device & mFullVolumeDevices) != 0)
-                                || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
+                        if (mFullVolumeDevices.contains(device)
+                                || (mFixedVolumeDevices.contains(device) && index != 0)) {
                             mIndexMap.put(device, mIndexMax);
                         }
                         applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
@@ -4978,7 +4990,7 @@
                     // that may have a different device selected
                     int streamDevice = getDeviceForStream(streamType);
                     if ((device != streamDevice) && isAvrcpAbsVolSupported
-                            && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
+                            && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)) {
                         mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
                                 isAvrcpAbsVolSupported);
                     }
@@ -5307,7 +5319,7 @@
     }
 
     /*package*/ void checkMusicActive(int deviceType, String caller) {
-        if ((deviceType & mSafeMediaVolumeDevices) != 0) {
+        if (mSafeMediaVolumeDevices.contains(deviceType)) {
             sendMsg(mAudioHandler,
                     MSG_CHECK_MUSIC_ACTIVE,
                     SENDMSG_REPLACE,
@@ -5753,9 +5765,9 @@
     // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
     private int mSafeUsbMediaVolumeIndex;
     // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
-    /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
-            | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
-            | AudioSystem.DEVICE_OUT_USB_HEADSET;
+    /*package*/ final Set<Integer> mSafeMediaVolumeDevices = new HashSet<>(
+            Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET));
     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
     // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
@@ -5765,7 +5777,7 @@
     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
 
     private int safeMediaVolumeIndex(int device) {
-        if ((device & mSafeMediaVolumeDevices) == 0) {
+        if (!mSafeMediaVolumeDevices.contains(device)) {
             return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
         }
         if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
@@ -5800,14 +5812,9 @@
 
     private void enforceSafeMediaVolume(String caller) {
         VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
-        int devices = mSafeMediaVolumeDevices;
-        int i = 0;
+        Set<Integer> devices = mSafeMediaVolumeDevices;
 
-        while (devices != 0) {
-            int device = 1 << i++;
-            if ((device & devices) == 0) {
-                continue;
-            }
+        for (int device : devices) {
             int index = streamState.getIndex(device);
             if (index > safeMediaVolumeIndex(device)) {
                 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
@@ -5819,16 +5826,15 @@
                         streamState,
                         0);
             }
-            devices &= ~device;
         }
     }
 
     private boolean checkSafeMediaVolume(int streamType, int index, int device) {
         synchronized (mSafeMediaVolumeStateLock) {
-            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
-                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
-                    ((device & mSafeMediaVolumeDevices) != 0) &&
-                    (index > safeMediaVolumeIndex(device))) {
+            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)
+                    && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC)
+                    && (mSafeMediaVolumeDevices.contains(device))
+                    && (index > safeMediaVolumeIndex(device))) {
                 return false;
             }
             return true;
@@ -5869,14 +5875,14 @@
             if (DEBUG_VOL) {
                 Log.d(TAG, "CEC sink: setting HDMI as full vol device");
             }
-            mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+            mFullVolumeDevices.add(AudioSystem.DEVICE_OUT_HDMI);
         } else {
             if (DEBUG_VOL) {
                 Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
             }
             // Android TV devices without CEC service apply software volume on
             // HDMI output
-            mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+            mFullVolumeDevices.remove(AudioSystem.DEVICE_OUT_HDMI);
         }
 
         checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
@@ -6097,6 +6103,19 @@
         pw.println();
     }
 
+    private String dumpDeviceTypes(@NonNull Set<Integer> deviceTypes) {
+        Iterator<Integer> it = deviceTypes.iterator();
+        if (!it.hasNext()) {
+            return "";
+        }
+        final StringBuilder sb = new StringBuilder();
+        sb.append("0x" + Integer.toHexString(it.next()));
+        while (it.hasNext()) {
+            sb.append("," + "0x" + Integer.toHexString(it.next()));
+        }
+        return sb.toString();
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -6133,7 +6152,7 @@
         pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
         pw.print("  mIsSingleVolume="); pw.println(mIsSingleVolume);
         pw.print("  mUseFixedVolume="); pw.println(mUseFixedVolume);
-        pw.print("  mFixedVolumeDevices=0x"); pw.println(Integer.toHexString(mFixedVolumeDevices));
+        pw.print("  mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
         pw.print("  mHdmiCecSink="); pw.println(mHdmiCecSink);
         pw.print("  mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
         pw.print("  mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 9f1a6bd..36332c0 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -295,6 +295,7 @@
                             && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
                         mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
                     }
+                    broadcast = false;
                     break;
                 default:
                     // do not broadcast CONNECTING or invalid state
diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS
new file mode 100644
index 0000000..8765c9a
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+kchyn@google.com
+jaggies@google.com
+curtislb@google.com
+ilyamaty@google.com
+joshmccloskey@google.com
diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
index 27f11ff..1b1c546 100644
--- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java
+++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
@@ -31,8 +31,6 @@
 import android.util.Log;
 
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.server.am.BatteryStatsService;
 
 public class DataConnectionStats extends BroadcastReceiver {
@@ -44,7 +42,7 @@
     private final Handler mListenerHandler;
     private final PhoneStateListener mPhoneStateListener;
 
-    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    private int mSimState = TelephonyManager.SIM_STATE_READY;
     private SignalStrength mSignalStrength;
     private ServiceState mServiceState;
     private int mDataState = TelephonyManager.DATA_DISCONNECTED;
@@ -66,7 +64,7 @@
               | PhoneStateListener.LISTEN_DATA_ACTIVITY);
 
         IntentFilter filter = new IntentFilter();
-        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
         mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
@@ -75,7 +73,7 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
-        if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+        if (action.equals(Intent.ACTION_SIM_STATE_CHANGED)) {
             updateSimState(intent);
             notePhoneDataConnectionState();
         } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
@@ -88,8 +86,8 @@
         if (mServiceState == null) {
             return;
         }
-        boolean simReadyOrUnknown = mSimState == IccCardConstants.State.READY
-                || mSimState == IccCardConstants.State.UNKNOWN;
+        boolean simReadyOrUnknown = mSimState == TelephonyManager.SIM_STATE_READY
+                || mSimState == TelephonyManager.SIM_STATE_UNKNOWN;
         boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
                 && hasService()
                 && mDataState == TelephonyManager.DATA_CONNECTED;
@@ -105,23 +103,23 @@
     }
 
     private final void updateSimState(Intent intent) {
-        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
-        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.ABSENT;
-        } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.READY;
-        } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+        String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
+        if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
+            mSimState = TelephonyManager.SIM_STATE_ABSENT;
+        } else if (Intent.SIM_STATE_READY.equals(stateExtra)) {
+            mSimState = TelephonyManager.SIM_STATE_READY;
+        } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) {
             final String lockedReason =
-                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
-            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                mSimState = IccCardConstants.State.PIN_REQUIRED;
-            } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                mSimState = IccCardConstants.State.PUK_REQUIRED;
+                    intent.getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON);
+            if (Intent.SIM_LOCKED_ON_PIN.equals(lockedReason)) {
+                mSimState = TelephonyManager.SIM_STATE_PIN_REQUIRED;
+            } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
+                mSimState = TelephonyManager.SIM_STATE_PUK_REQUIRED;
             } else {
-                mSimState = IccCardConstants.State.NETWORK_LOCKED;
+                mSimState = TelephonyManager.SIM_STATE_NETWORK_LOCKED;
             }
         } else {
-            mSimState = IccCardConstants.State.UNKNOWN;
+            mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 2321afb..5250a77 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -337,7 +337,6 @@
                               .collect(Collectors.toList()))
                 : useTls ? paramsParcel.servers  // Opportunistic
                 : new String[0];            // Off
-        paramsParcel.tlsFingerprints = new String[0];
         // Prepare to track the validation status of the DNS servers in the
         // resolver config when private DNS is in opportunistic or strict mode.
         if (useTls) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index bb7f862..5e085ca 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -291,13 +291,18 @@
      *
      * <p>If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails,
      * the exception is logged but not reported to callers.
+     *
+     * @return the old capabilities of this network.
      */
-    public void setNetworkCapabilities(NetworkCapabilities nc) {
+    public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
+            @NonNull final NetworkCapabilities nc) {
+        final NetworkCapabilities oldNc = networkCapabilities;
         networkCapabilities = nc;
         final NetworkMonitorManager nm = mNetworkMonitor;
         if (nm != null) {
             nm.notifyNetworkCapabilitiesChanged(nc);
         }
+        return oldNc;
     }
 
     public ConnectivityService connService() {
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index bc83780..2179518 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -31,7 +31,6 @@
 import android.net.StringNetworkSpecifier;
 import android.net.wifi.WifiInfo;
 import android.os.UserHandle;
-import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -105,8 +104,7 @@
         return -1;
     }
 
-    // TODO: Remove @TransportType or change it to @Transport.
-    private static String getTransportName(@TransportType int transportType) {
+    private static String getTransportName(final int transportType) {
         Resources r = Resources.getSystem();
         String[] networkTypes = r.getStringArray(R.array.network_switch_type_name);
         try {
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
index a91fe77..1cf27ff 100644
--- a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -231,7 +231,8 @@
                 // a Sim with a different mcc code was found
                 neededNow = false;
             }
-            String simOperator  = mTelephonyManager.getSimOperator(info.getSubscriptionId());
+            String simOperator = mTelephonyManager
+                    .createForSubscriptionId(info.getSubscriptionId()).getSimOperator();
             mcc = 0;
             if (simOperator != null && simOperator.length() >= 3) {
                 mcc = Integer.parseInt(simOperator.substring(0, 3));
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
index 52cede2..23b5c14 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecKeycode.java
@@ -250,7 +250,11 @@
             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_UP),
             // No Android keycode defined for CEC_KEYCODE_LEFT_DOWN
             new KeycodeEntry(UNSUPPORTED_KEYCODE, CEC_KEYCODE_LEFT_DOWN),
+            // Both KEYCODE_HOME and KEYCODE_MENU keys are sent as CEC_KEYCODE_ROOT_MENU
+            // NOTE that the HOME key is not usually forwarded.
+            // When CEC_KEYCODE_ROOT_MENU is received, it is translated to KEYCODE_HOME
             new KeycodeEntry(KeyEvent.KEYCODE_HOME, CEC_KEYCODE_ROOT_MENU),
+            new KeycodeEntry(KeyEvent.KEYCODE_MENU, CEC_KEYCODE_ROOT_MENU),
             new KeycodeEntry(KeyEvent.KEYCODE_SETTINGS, CEC_KEYCODE_SETUP_MENU),
             new KeycodeEntry(KeyEvent.KEYCODE_TV_CONTENTS_MENU, CEC_KEYCODE_CONTENTS_MENU, false),
             // No Android keycode defined for CEC_KEYCODE_FAVORITE_MENU
diff --git a/services/core/java/com/android/server/integrity/OWNERS b/services/core/java/com/android/server/integrity/OWNERS
index 019aa4f..55a4e40 100644
--- a/services/core/java/com/android/server/integrity/OWNERS
+++ b/services/core/java/com/android/server/integrity/OWNERS
@@ -3,4 +3,3 @@
 mdchurchill@google.com
 sturla@google.com
 songpan@google.com
-bjy@google.com
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 181a435..3fc8438 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -508,8 +508,10 @@
         CarrierConfigManager configManager = (CarrierConfigManager)
                 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
-        String mccMnc = SubscriptionManager.isValidSubscriptionId(ddSubId)
-                ? phone.getSimOperator(ddSubId) : phone.getSimOperator();
+        if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+            phone = phone.createForSubscriptionId(ddSubId);
+        }
+        String mccMnc = phone.getSimOperator();
         boolean isKeepLppProfile = false;
         if (!TextUtils.isEmpty(mccMnc)) {
             if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
@@ -1903,24 +1905,17 @@
         String setId = null;
 
         int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+        if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+            phone = phone.createForSubscriptionId(ddSubId);
+        }
         if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
-            if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
-                setId = phone.getSubscriberId(ddSubId);
-            }
-            if (setId == null) {
-                setId = phone.getSubscriberId();
-            }
+            setId = phone.getSubscriberId();
             if (setId != null) {
                 // This means the framework has the SIM card.
                 type = AGPS_SETID_TYPE_IMSI;
             }
         } else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
-            if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
-                setId = phone.getLine1Number(ddSubId);
-            }
-            if (setId == null) {
-                setId = phone.getLine1Number();
-            }
+            setId = phone.getLine1Number();
             if (setId != null) {
                 // This means the framework has the SIM card.
                 type = AGPS_SETID_TYPE_MSISDN;
diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
index eb706d7..1d39177 100644
--- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
@@ -240,8 +240,7 @@
                     if (!mPrevActiveAudioPlaybackConfigs.containsKey(
                             config.getPlayerInterfaceId())) {
                         if (DEBUG) {
-                            Log.d(TAG, "Found a new active media playback. "
-                                    + AudioPlaybackConfiguration.toLogFriendlyString(config));
+                            Log.d(TAG, "Found a new active media playback. " + config);
                         }
                         // New active audio playback.
                         int index = mSortedAudioPlaybackClientUids.indexOf(uid);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 5bd4b20..49398b9 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -47,7 +47,8 @@
 import android.media.Session2CommandGroup;
 import android.media.Session2Token;
 import android.media.session.IActiveSessionsListener;
-import android.media.session.ICallback;
+import android.media.session.IOnMediaKeyEventDispatchedListener;
+import android.media.session.IOnMediaKeyEventSessionChangedListener;
 import android.media.session.IOnMediaKeyListener;
 import android.media.session.IOnVolumeKeyLongPressListener;
 import android.media.session.ISession;
@@ -92,6 +93,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -748,6 +750,11 @@
 
         private final int mFullUserId;
         private final MediaSessionStack mPriorityStack;
+        private final HashMap<IBinder, OnMediaKeyEventDispatchedListenerRecord>
+                mOnMediaKeyEventDispatchedListeners = new HashMap<>();
+        private final HashMap<IBinder, OnMediaKeyEventSessionChangedListenerRecord>
+                mOnMediaKeyEventSessionChangedListeners = new HashMap<>();
+
         private PendingIntent mLastMediaButtonReceiver;
         private ComponentName mRestoredMediaButtonReceiver;
         private int mRestoredMediaButtonReceiverComponentType;
@@ -761,7 +768,6 @@
 
         private IOnMediaKeyListener mOnMediaKeyListener;
         private int mOnMediaKeyListenerUid;
-        private ICallback mCallback;
 
         FullUserRecord(int fullUserId) {
             mFullUserId = fullUserId;
@@ -793,6 +799,50 @@
             }
         }
 
+        public void addOnMediaKeyEventDispatchedListenerLocked(
+                IOnMediaKeyEventDispatchedListener listener, int uid) {
+            IBinder cbBinder = listener.asBinder();
+            OnMediaKeyEventDispatchedListenerRecord cr =
+                    new OnMediaKeyEventDispatchedListenerRecord(listener, uid);
+            mOnMediaKeyEventDispatchedListeners.put(cbBinder, cr);
+            try {
+                cbBinder.linkToDeath(cr, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to register listener", e);
+                mOnMediaKeyEventDispatchedListeners.remove(cbBinder);
+            }
+        }
+
+        public void removeOnMediaKeyEventDispatchedListenerLocked(
+                IOnMediaKeyEventDispatchedListener listener) {
+            IBinder cbBinder = listener.asBinder();
+            OnMediaKeyEventDispatchedListenerRecord cr =
+                    mOnMediaKeyEventDispatchedListeners.remove(cbBinder);
+            cbBinder.unlinkToDeath(cr, 0);
+        }
+
+        public void addOnMediaKeyEventSessionChangedListenerLocked(
+                IOnMediaKeyEventSessionChangedListener listener, int uid) {
+            IBinder cbBinder = listener.asBinder();
+            OnMediaKeyEventSessionChangedListenerRecord cr =
+                    new OnMediaKeyEventSessionChangedListenerRecord(listener, uid);
+            mOnMediaKeyEventSessionChangedListeners.put(cbBinder, cr);
+            try {
+                cbBinder.linkToDeath(cr, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to register callback", e);
+                mOnMediaKeyEventSessionChangedListeners.remove(cbBinder);
+            }
+        }
+
+        public void removeOnMediaKeyEventSessionChangedListener(
+                IOnMediaKeyEventSessionChangedListener listener) {
+            IBinder cbBinder = listener.asBinder();
+            OnMediaKeyEventSessionChangedListenerRecord cr =
+                    mOnMediaKeyEventSessionChangedListeners.remove(cbBinder);
+            cbBinder.unlinkToDeath(cr, 0);
+        }
+
         public void dumpLocked(PrintWriter pw, String prefix) {
             pw.print(prefix + "Record for full_user=" + mFullUserId);
             // Dump managed profile user ids associated with this user.
@@ -811,7 +861,18 @@
             pw.println(indent + "Media key listener: " + mOnMediaKeyListener);
             pw.println(indent + "Media key listener package: "
                     + getCallingPackageName(mOnMediaKeyListenerUid));
-            pw.println(indent + "Callback: " + mCallback);
+            pw.println(indent + "OnMediaKeyEventDispatchedListener: added "
+                    + mOnMediaKeyEventDispatchedListeners.size() + " listener(s)");
+            for (OnMediaKeyEventDispatchedListenerRecord cr
+                    : mOnMediaKeyEventDispatchedListeners.values()) {
+                pw.println(indent + "  from " + getCallingPackageName(cr.uid));
+            }
+            pw.println(indent + "OnMediaKeyEventSessionChangedListener: added "
+                    + mOnMediaKeyEventSessionChangedListeners.size() + " listener(s)");
+            for (OnMediaKeyEventSessionChangedListenerRecord cr
+                    : mOnMediaKeyEventSessionChangedListeners.values()) {
+                pw.println(indent + "  from " + getCallingPackageName(cr.uid));
+            }
             pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
             pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
             pw.println(indent + "Restored MediaButtonReceiverComponentType: "
@@ -871,28 +932,35 @@
                     mFullUserId);
         }
 
-        private void pushAddressedPlayerChangedLocked() {
-            if (mCallback == null) {
-                return;
-            }
+        private void pushAddressedPlayerChangedLocked(
+                IOnMediaKeyEventSessionChangedListener callback) {
             try {
                 MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
                 if (mediaButtonSession != null) {
-                    mCallback.onAddressedPlayerChangedToMediaSession(
+                    callback.onMediaKeyEventSessionChanged(mediaButtonSession.getPackageName(),
                             mediaButtonSession.getSessionToken());
                 } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
-                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+                    callback.onMediaKeyEventSessionChanged(
                             mCurrentFullUserRecord.mLastMediaButtonReceiver
-                                    .getIntent().getComponent());
+                                    .getIntent().getComponent().getPackageName(),
+                            null);
                 } else if (mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
-                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
-                            mCurrentFullUserRecord.mRestoredMediaButtonReceiver);
+                    callback.onMediaKeyEventSessionChanged(
+                            mCurrentFullUserRecord.mRestoredMediaButtonReceiver.getPackageName(),
+                            null);
                 }
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
             }
         }
 
+        private void pushAddressedPlayerChangedLocked() {
+            for (OnMediaKeyEventSessionChangedListenerRecord cr
+                    : mOnMediaKeyEventSessionChangedListeners.values()) {
+                pushAddressedPlayerChangedLocked(cr.callback);
+            }
+        }
+
         private MediaSessionRecord getMediaButtonSessionLocked() {
             return isGlobalPriorityActiveLocked()
                     ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
@@ -926,6 +994,42 @@
             // Pick legacy behavior for BroadcastReceiver or unknown.
             return COMPONENT_TYPE_BROADCAST;
         }
+
+        final class OnMediaKeyEventDispatchedListenerRecord implements IBinder.DeathRecipient {
+            public final IOnMediaKeyEventDispatchedListener callback;
+            public final int uid;
+
+            OnMediaKeyEventDispatchedListenerRecord(IOnMediaKeyEventDispatchedListener callback,
+                    int uid) {
+                this.callback = callback;
+                this.uid = uid;
+            }
+
+            @Override
+            public void binderDied() {
+                synchronized (mLock) {
+                    mOnMediaKeyEventDispatchedListeners.remove(callback.asBinder());
+                }
+            }
+        }
+
+        final class OnMediaKeyEventSessionChangedListenerRecord implements IBinder.DeathRecipient {
+            public final IOnMediaKeyEventSessionChangedListener callback;
+            public final int uid;
+
+            OnMediaKeyEventSessionChangedListenerRecord(
+                    IOnMediaKeyEventSessionChangedListener callback, int uid) {
+                this.callback = callback;
+                this.uid = uid;
+            }
+
+            @Override
+            public void binderDied() {
+                synchronized (mLock) {
+                    mOnMediaKeyEventSessionChangedListeners.remove(callback.asBinder());
+                }
+            }
+        }
     }
 
     final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -1305,44 +1409,111 @@
         }
 
         @Override
-        public void setCallback(ICallback callback) {
+        public void addOnMediaKeyEventDispatchedListener(
+                final IOnMediaKeyEventDispatchedListener callback) {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
-                    throw new SecurityException("Only Bluetooth service processes can set"
-                            + " Callback");
+                if (!hasMediaControlPermission(pid, uid)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
+                            + "  register MediaKeyEventDispatchedCallback");
                 }
                 synchronized (mLock) {
-                    int userId = UserHandle.getUserId(uid);
                     FullUserRecord user = getFullUserRecordLocked(userId);
                     if (user == null || user.mFullUserId != userId) {
-                        Log.w(TAG, "Only the full user can set the callback"
+                        Log.w(TAG, "Only the full user can register the callback"
                                 + ", userId=" + userId);
                         return;
                     }
-                    user.mCallback = callback;
-                    Log.d(TAG, "The callback " + user.mCallback
-                            + " is set by " + getCallingPackageName(uid));
-                    if (user.mCallback == null) {
+                    user.addOnMediaKeyEventDispatchedListenerLocked(callback, uid);
+                    Log.d(TAG, "The MediaKeyEventDispatchedCallback (" + callback.asBinder()
+                            + ") is registered by " + getCallingPackageName(uid));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void removeOnMediaKeyEventDispatchedListener(
+                final IOnMediaKeyEventDispatchedListener callback) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (!hasMediaControlPermission(pid, uid)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
+                            + "  unregister MediaKeyEventDispatchedCallback");
+                }
+                synchronized (mLock) {
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can unregister the callback"
+                                + ", userId=" + userId);
                         return;
                     }
-                    try {
-                        user.mCallback.asBinder().linkToDeath(
-                                new IBinder.DeathRecipient() {
-                                    @Override
-                                    public void binderDied() {
-                                        synchronized (mLock) {
-                                            user.mCallback = null;
-                                        }
-                                    }
-                                }, 0);
-                        user.pushAddressedPlayerChangedLocked();
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to set callback", e);
-                        user.mCallback = null;
+                    user.removeOnMediaKeyEventDispatchedListenerLocked(callback);
+                    Log.d(TAG, "The MediaKeyEventDispatchedCallback (" + callback.asBinder()
+                            + ") is unregistered by " + getCallingPackageName(uid));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void addOnMediaKeyEventSessionChangedListener(
+                final IOnMediaKeyEventSessionChangedListener listener) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (!hasMediaControlPermission(pid, uid)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
+                            + "  register MediaKeyEventSessionChangedListener");
+                }
+                synchronized (mLock) {
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can register the listener"
+                                + ", userId=" + userId);
+                        return;
                     }
+                    user.addOnMediaKeyEventSessionChangedListenerLocked(listener, uid);
+                    Log.d(TAG, "The MediaKeyEventSessionChangedListener (" + listener.asBinder()
+                            + ") is registered by " + getCallingPackageName(uid));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void removeOnMediaKeyEventSessionChangedListener(
+                final IOnMediaKeyEventSessionChangedListener callback) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (!hasMediaControlPermission(pid, uid)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
+                            + "  unregister MediaKeyEventSessionChangedListener");
+                }
+                synchronized (mLock) {
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can unregister the listener"
+                                + ", userId=" + userId);
+                        return;
+                    }
+                    user.removeOnMediaKeyEventSessionChangedListener(callback);
+                    Log.d(TAG, "The MediaKeyEventSessionChangedListener (" + callback.asBinder()
+                            + ") is unregistered by " + getCallingPackageName(uid));
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -1771,6 +1942,7 @@
         public boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid)
                 throws RemoteException {
             final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
             final long token = Binder.clearCallingIdentity();
             try {
                 // Don't perform sanity check between controllerPackageName and controllerUid.
@@ -1781,8 +1953,8 @@
                 // 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(UserHandle.getUserId(uid), controllerPackageName,
-                        controllerPid, controllerUid);
+                return hasMediaControlPermission(controllerPid, controllerUid)
+                        || hasEnabledNotificationListener(userId, controllerPackageName);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1808,13 +1980,7 @@
             return resolvedUserId;
         }
 
-        private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
-                int pid, int uid) throws RemoteException {
-            // Allow API calls from the System UI and Settings
-            if (hasStatusBarServicePermission(pid, uid)) {
-                return true;
-            }
-
+        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.
@@ -1823,11 +1989,15 @@
                     == PackageManager.PERMISSION_GRANTED) {
                 return true;
             } else if (DEBUG) {
-                Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
+                Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
             }
+            return false;
+        }
 
+        private boolean hasEnabledNotificationListener(int resolvedUserId, String packageName)
+                throws RemoteException {
             // You may not access another user's content as an enabled listener.
-            final int userId = UserHandle.getUserId(uid);
+            final int userId = UserHandle.getUserId(resolvedUserId);
             if (resolvedUserId != userId) {
                 return false;
             }
@@ -1845,7 +2015,7 @@
                 }
             }
             if (DEBUG) {
-                Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
+                Log.d(TAG, packageName + " (uid=" + resolvedUserId + ") doesn't have an enabled "
                         + "notification listener");
             }
             return false;
@@ -1950,13 +2120,14 @@
                 session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
                         needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                         mKeyEventReceiver);
-                if (mCurrentFullUserRecord.mCallback != null) {
-                    try {
-                        mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
-                                keyEvent, session.getSessionToken());
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to send callback", e);
+                try {
+                    for (FullUserRecord.OnMediaKeyEventDispatchedListenerRecord cr
+                            : mCurrentFullUserRecord.mOnMediaKeyEventDispatchedListeners.values()) {
+                        cr.callback.onMediaKeyEventDispatched(
+                                keyEvent, session.getPackageName(), session.getSessionToken());
                     }
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Failed to send callback", e);
                 }
             } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null
                     || mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
@@ -1980,13 +2151,14 @@
                         receiver.send(mContext,
                                 needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                                 mediaButtonIntent, mKeyEventReceiver, mHandler);
-                        if (mCurrentFullUserRecord.mCallback != null) {
-                            ComponentName componentName = mCurrentFullUserRecord
-                                    .mLastMediaButtonReceiver.getIntent().getComponent();
-                            if (componentName != null) {
-                                mCurrentFullUserRecord.mCallback
-                                        .onMediaKeyEventDispatchedToMediaButtonReceiver(
-                                                keyEvent, componentName);
+                        ComponentName componentName = mCurrentFullUserRecord
+                                .mLastMediaButtonReceiver.getIntent().getComponent();
+                        if (componentName != null) {
+                            for (FullUserRecord.OnMediaKeyEventDispatchedListenerRecord cr
+                                    : mCurrentFullUserRecord
+                                    .mOnMediaKeyEventDispatchedListeners.values()) {
+                                cr.callback.onMediaKeyEventDispatched(keyEvent,
+                                        componentName.getPackageName(), null);
                             }
                         }
                     } else {
@@ -2018,10 +2190,11 @@
                             Log.w(TAG, "Error sending media button to the restored intent "
                                     + receiver + ", type=" + componentType, e);
                         }
-                        if (mCurrentFullUserRecord.mCallback != null) {
-                            mCurrentFullUserRecord.mCallback
-                                    .onMediaKeyEventDispatchedToMediaButtonReceiver(
-                                            keyEvent, receiver);
+                        for (FullUserRecord.OnMediaKeyEventDispatchedListenerRecord cr
+                                : mCurrentFullUserRecord
+                                .mOnMediaKeyEventDispatchedListeners.values()) {
+                            cr.callback.onMediaKeyEventDispatched(keyEvent,
+                                    receiver.getPackageName(), null);
                         }
                     }
                 } catch (CanceledException e) {
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 4cb41da..ef8f647 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -45,12 +45,12 @@
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnProfile;
 import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.util.Preconditions;
 import com.android.server.ConnectivityService;
 import com.android.server.EventLogTags;
 import com.android.server.connectivity.Vpn;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be
@@ -90,11 +90,11 @@
             @NonNull Handler handler,
             @NonNull Vpn vpn,
             @NonNull VpnProfile profile) {
-        mContext = Preconditions.checkNotNull(context);
-        mConnService = Preconditions.checkNotNull(connService);
-        mHandler = Preconditions.checkNotNull(handler);
-        mVpn = Preconditions.checkNotNull(vpn);
-        mProfile = Preconditions.checkNotNull(profile);
+        mContext = Objects.requireNonNull(context);
+        mConnService = Objects.requireNonNull(connService);
+        mHandler = Objects.requireNonNull(handler);
+        mVpn = Objects.requireNonNull(vpn);
+        mProfile = Objects.requireNonNull(profile);
 
         final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
         mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 327b685..e3e6d9d 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -91,7 +91,6 @@
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import static com.android.internal.util.ArrayUtils.appendInt;
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -223,7 +222,6 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.RoSystemProperties;
-import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.DumpUtils;
@@ -609,12 +607,12 @@
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkManagementService networkManagement, IPackageManager pm, Clock clock,
             File systemDir, boolean suppressDefaultPolicy) {
-        mContext = checkNotNull(context, "missing context");
-        mActivityManager = checkNotNull(activityManager, "missing activityManager");
-        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
+        mContext = Objects.requireNonNull(context, "missing context");
+        mActivityManager = Objects.requireNonNull(activityManager, "missing activityManager");
+        mNetworkManager = Objects.requireNonNull(networkManagement, "missing networkManagement");
         mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
                 Context.DEVICE_IDLE_CONTROLLER));
-        mClock = checkNotNull(clock, "missing Clock");
+        mClock = Objects.requireNonNull(clock, "missing Clock");
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
         mIPm = pm;
@@ -641,7 +639,7 @@
     }
 
     public void bindConnectivityManager(IConnectivityManager connManager) {
-        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
+        mConnManager = Objects.requireNonNull(connManager, "missing IConnectivityManager");
     }
 
     @GuardedBy("mUidRulesFirstLock")
@@ -1027,6 +1025,7 @@
             // READ_NETWORK_USAGE_HISTORY permission above.
 
             synchronized (mNetworkPoliciesSecondLock) {
+                updateNetworkRulesNL();
                 updateNetworkEnabledNL();
                 updateNotificationsNL();
             }
@@ -1650,10 +1649,10 @@
             // No need to do a permission check, because the ACTION_CARRIER_CONFIG_CHANGED
             // broadcast is protected and can't be spoofed. Runs on a background handler thread.
 
-            if (!intent.hasExtra(PhoneConstants.SUBSCRIPTION_KEY)) {
+            if (!intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX)) {
                 return;
             }
-            final int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, -1);
+            final int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1);
 
             // Get all of our cross-process communication with telephony out of
             // the way before we acquire internal locks.
@@ -3258,7 +3257,7 @@
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
 
         for (SubscriptionPlan plan : plans) {
-            Preconditions.checkNotNull(plan);
+            Objects.requireNonNull(plan);
         }
 
         final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 06ec341..a94a2f7 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -21,8 +21,6 @@
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
 import android.net.NetworkStatsHistory;
@@ -54,6 +52,7 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Logic to record deltas between periodic {@link NetworkStats} snapshots into
@@ -116,9 +115,9 @@
      */
     public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
             DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) {
-        mRotator = checkNotNull(rotator, "missing FileRotator");
-        mObserver = checkNotNull(observer, "missing NonMonotonicObserver");
-        mDropBox = checkNotNull(dropBox, "missing DropBoxManager");
+        mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
+        mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
+        mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
         mCookie = cookie;
 
         mBucketDuration = bucketDuration;
@@ -165,7 +164,7 @@
      * as reference is valid.
      */
     public NetworkStatsCollection getOrLoadCompleteLocked() {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
         if (res == null) {
             res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
@@ -175,7 +174,7 @@
     }
 
     public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
         if (res == null) {
             res = loadLocked(start, end);
@@ -280,7 +279,7 @@
      * {@link #mPersistThresholdBytes}.
      */
     public void maybePersistLocked(long currentTimeMillis) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         final long pendingBytes = mPending.getTotalBytes();
         if (pendingBytes >= mPersistThresholdBytes) {
             forcePersistLocked(currentTimeMillis);
@@ -293,7 +292,7 @@
      * Force persisting any pending deltas.
      */
     public void forcePersistLocked(long currentTimeMillis) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         if (mPending.isDirty()) {
             if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie);
             try {
@@ -356,7 +355,7 @@
         private final NetworkStatsCollection mCollection;
 
         public CombiningRewriter(NetworkStatsCollection collection) {
-            mCollection = checkNotNull(collection, "missing NetworkStatsCollection");
+            mCollection = Objects.requireNonNull(collection, "missing NetworkStatsCollection");
         }
 
         @Override
@@ -418,7 +417,7 @@
     }
 
     public void importLegacyNetworkLocked(File file) throws IOException {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
 
         // legacy file still exists; start empty to avoid double importing
         mRotator.deleteAll();
@@ -438,7 +437,7 @@
     }
 
     public void importLegacyUidLocked(File file) throws IOException {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
 
         // legacy file still exists; start empty to avoid double importing
         mRotator.deleteAll();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 16424f2..a41fb7d 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -65,7 +65,6 @@
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -148,6 +147,7 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Collect and persist detailed network statistics, and provide this data to
@@ -357,17 +357,18 @@
             TelephonyManager teleManager, NetworkStatsSettings settings,
             NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
             File baseDir) {
-        mContext = checkNotNull(context, "missing Context");
-        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
-        mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
-        mClock = checkNotNull(clock, "missing Clock");
-        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
-        mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
-        mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
-        mStatsFactory = checkNotNull(factory, "missing factory");
-        mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
-        mSystemDir = checkNotNull(systemDir, "missing systemDir");
-        mBaseDir = checkNotNull(baseDir, "missing baseDir");
+        mContext = Objects.requireNonNull(context, "missing Context");
+        mNetworkManager = Objects.requireNonNull(networkManager,
+            "missing INetworkManagementService");
+        mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
+        mClock = Objects.requireNonNull(clock, "missing Clock");
+        mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
+        mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager");
+        mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
+        mStatsFactory = Objects.requireNonNull(factory, "missing factory");
+        mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
+        mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
+        mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
         mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
     }
 
@@ -873,6 +874,8 @@
                     + mPersistThreshold);
         }
 
+        final long oldGlobalAlertBytes = mGlobalAlertBytes;
+
         // update and persist if beyond new thresholds
         final long currentTime = mClock.millis();
         synchronized (mStatsLock) {
@@ -886,18 +889,19 @@
             mUidTagRecorder.maybePersistLocked(currentTime);
         }
 
-        // re-arm global alert
-        registerGlobalAlert();
+        if (oldGlobalAlertBytes != mGlobalAlertBytes) {
+            registerGlobalAlert();
+        }
     }
 
     @Override
     public DataUsageRequest registerUsageCallback(String callingPackage,
                 DataUsageRequest request, Messenger messenger, IBinder binder) {
-        checkNotNull(callingPackage, "calling package is null");
-        checkNotNull(request, "DataUsageRequest is null");
-        checkNotNull(request.template, "NetworkTemplate is null");
-        checkNotNull(messenger, "messenger is null");
-        checkNotNull(binder, "binder is null");
+        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");
 
         int callingUid = Binder.getCallingUid();
         @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
@@ -918,7 +922,7 @@
 
     @Override
     public void unregisterUsageRequest(DataUsageRequest request) {
-        checkNotNull(request, "DataUsageRequest is null");
+        Objects.requireNonNull(request, "DataUsageRequest is null");
 
         int callingUid = Binder.getCallingUid();
         final long token = Binder.clearCallingIdentity();
@@ -1792,7 +1796,7 @@
         private final ContentResolver mResolver;
 
         public DefaultNetworkStatsSettings(Context context) {
-            mResolver = checkNotNull(context.getContentResolver());
+            mResolver = Objects.requireNonNull(context.getContentResolver());
             // TODO: adjust these timings for production builds
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 9b9f4de..f295ed3 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.provider.Settings;
 import android.telecom.TelecomManager;
 
 import com.android.internal.util.NotificationMessagingUtil;
@@ -55,14 +54,9 @@
         final boolean isLeftHighImportance = leftImportance >= IMPORTANCE_DEFAULT;
         final boolean isRightHighImportance = rightImportance >= IMPORTANCE_DEFAULT;
 
-        // With new interruption model, prefer importance bucket above all other criteria
-        // (to ensure buckets are contiguous)
-        if (Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) == 1) {
-            if (isLeftHighImportance != isRightHighImportance) {
-                // by importance bucket, high importance higher than low importance
-                return -1 * Boolean.compare(isLeftHighImportance, isRightHighImportance);
-            }
+        if (isLeftHighImportance != isRightHighImportance) {
+            // by importance bucket, high importance higher than low importance
+            return -1 * Boolean.compare(isLeftHighImportance, isRightHighImportance);
         }
 
         // first all colorized notifications
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/services/core/java/com/android/server/package-info.java
similarity index 75%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to services/core/java/com/android/server/package-info.java
index d502088..dd94edd 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/services/core/java/com/android/server/package-info.java
@@ -14,15 +14,9 @@
  * limitations under the License.
  */
 
-package android.net;
-
-import android.net.Network;
-
 /**
- * Callback class for receiving tethering changed events
  * @hide
+ * TODO(b/146466118) remove this javadoc tag
  */
-oneway interface ITetheringEventCallback
-{
-    void onUpstreamChanged(in Network network);
-}
+@android.annotation.Hide
+package com.android.server;
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 12e8069..cf5ec05 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -22,6 +22,7 @@
 import android.apex.ApexInfo;
 import android.apex.ApexInfoList;
 import android.apex.ApexSessionInfo;
+import android.apex.ApexSessionParams;
 import android.apex.IApexService;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -439,7 +440,10 @@
                 throws PackageManagerException {
             try {
                 final ApexInfoList apexInfoList = new ApexInfoList();
-                mApexService.submitStagedSession(sessionId, childSessionIds, apexInfoList);
+                ApexSessionParams params = new ApexSessionParams();
+                params.sessionId = sessionId;
+                params.childSessionIds = childSessionIds;
+                mApexService.submitStagedSession(params, apexInfoList);
                 return apexInfoList;
             } catch (RemoteException re) {
                 Slog.e(TAG, "Unable to contact apexservice", re);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index adcd19e..b3b0029 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -85,6 +85,9 @@
     public static final int FLAG_USE_QUOTA = IInstalld.FLAG_USE_QUOTA;
     public static final int FLAG_FORCE = IInstalld.FLAG_FORCE;
 
+    public static final int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES =
+            IInstalld.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
+
     private final boolean mIsolated;
 
     private volatile IInstalld mInstalld;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cec5c6d..7e7822c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3136,7 +3136,8 @@
                         // No apps are running this early, so no need to freeze
                         clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                 FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
-                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
+                                        | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
                     }
                 }
                 ver.fingerprint = Build.FINGERPRINT;
@@ -10222,7 +10223,9 @@
             clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
         }
 
-        clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+        if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
+            clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+        }
     }
 
     private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
@@ -17471,8 +17474,7 @@
                 if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
                     try {
                         VerityUtils.setUpFsverity(filePath, signaturePath);
-                    } catch (IOException | DigestException | NoSuchAlgorithmException
-                            | SecurityException e) {
+                    } catch (IOException e) {
                         throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
                                 "Failed to enable fs-verity: " + e);
                     }
@@ -22047,7 +22049,8 @@
 
                 if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
                     clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
-                            | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                            | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
+                            | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 204f186..31960e4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2257,14 +2257,14 @@
         return mContext.getResources().getString(com.android.internal.R.string.owner_name);
     }
 
-    private void scheduleWriteUser(UserData UserData) {
+    private void scheduleWriteUser(UserData userData) {
         if (DBG) {
             debug("scheduleWriteUser");
         }
         // No need to wrap it within a lock -- worst case, we'll just post the same message
         // twice.
-        if (!mHandler.hasMessages(WRITE_USER_MSG, UserData)) {
-            Message msg = mHandler.obtainMessage(WRITE_USER_MSG, UserData);
+        if (!mHandler.hasMessages(WRITE_USER_MSG, userData)) {
+            Message msg = mHandler.obtainMessage(WRITE_USER_MSG, userData);
             mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
         }
     }
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 9cb2441..68ba8a4 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -16,24 +16,6 @@
 
 package com.android.server.policy;
 
-import com.android.internal.app.AlertController;
-import com.android.internal.globalactions.Action;
-import com.android.internal.globalactions.ActionsAdapter;
-import com.android.internal.globalactions.ActionsDialog;
-import com.android.internal.globalactions.LongPressAction;
-import com.android.internal.globalactions.SinglePressAction;
-import com.android.internal.globalactions.ToggleAction;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.R;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-import com.android.internal.util.EmergencyAffordanceManager;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.policy.PowerAction;
-import com.android.server.policy.RestartAction;
-import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
-
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -57,6 +39,7 @@
 import android.provider.Settings;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
+import android.sysprop.TelephonyProperties;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
@@ -69,6 +52,21 @@
 import android.view.WindowManagerGlobal;
 import android.widget.AdapterView;
 
+import com.android.internal.R;
+import com.android.internal.app.AlertController;
+import com.android.internal.globalactions.Action;
+import com.android.internal.globalactions.ActionsAdapter;
+import com.android.internal.globalactions.ActionsDialog;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.globalactions.ToggleAction;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -229,8 +227,7 @@
 
             @Override
             public void onToggle(boolean on) {
-                if (mHasTelephony && Boolean.parseBoolean(
-                        SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
+                if (mHasTelephony && TelephonyProperties.in_ecm_mode().orElse(false)) {
                     mIsWaitingForEcmExit = true;
                     // Launch ECM exit dialog
                     Intent ecmDialogIntent =
@@ -247,8 +244,7 @@
                 if (!mHasTelephony) return;
 
                 // In ECM mode airplane state cannot be changed
-                if (!(Boolean.parseBoolean(
-                        SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {
+                if (!TelephonyProperties.in_ecm_mode().orElse(false)) {
                     mState = buttonOn ? State.TurningOn : State.TurningOff;
                     mAirplaneState = mState;
                 }
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 0a6b38f..d81728d 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -41,12 +41,12 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
+import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.TimingsTraceLog;
 import android.view.WindowManager;
 
-import com.android.internal.telephony.ITelephony;
 import com.android.server.RescueParty;
 import com.android.server.LocalServices;
 import com.android.server.pm.PackageManagerService;
@@ -584,19 +584,15 @@
                 TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
                 boolean radioOff;
 
-                final ITelephony phone =
-                        ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+                TelephonyManager telephonyManager = mContext.getSystemService(
+                        TelephonyManager.class);
 
-                try {
-                    radioOff = phone == null || !phone.needMobileRadioShutdown();
-                    if (!radioOff) {
-                        Log.w(TAG, "Turning off cellular radios...");
-                        metricStarted(METRIC_RADIO);
-                        phone.shutdownMobileRadios();
-                    }
-                } catch (RemoteException ex) {
-                    Log.e(TAG, "RemoteException during radio shutdown", ex);
-                    radioOff = true;
+                radioOff = telephonyManager == null
+                        || !telephonyManager.isAnyRadioPoweredOn();
+                if (!radioOff) {
+                    Log.w(TAG, "Turning off cellular radios...");
+                    metricStarted(METRIC_RADIO);
+                    telephonyManager.shutdownAllRadios();
                 }
 
                 Log.i(TAG, "Waiting for Radio...");
@@ -611,12 +607,7 @@
                     }
 
                     if (!radioOff) {
-                        try {
-                            radioOff = !phone.needMobileRadioShutdown();
-                        } catch (RemoteException ex) {
-                            Log.e(TAG, "RemoteException during radio shutdown", ex);
-                            radioOff = true;
-                        }
+                        radioOff = !telephonyManager.isAnyRadioPoweredOn();
                         if (radioOff) {
                             Log.i(TAG, "Radio turned off.");
                             metricEnded(METRIC_RADIO);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index fff9ec7..0caf8f8 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -50,7 +50,6 @@
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.service.sms.FinancialSmsService;
-import android.telephony.IFinancialSmsCallback;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -675,40 +674,6 @@
             dumpOutputStream.flush();
         }
 
-        /**
-         * Get filtered SMS messages for financial app.
-         */
-        @Override
-        public void getSmsMessagesForFinancialApp(
-                String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-            int mode = PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(
-                    getContext(),
-                    AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS);
-
-            if (mode == PermissionChecker.PERMISSION_GRANTED) {
-                FinancialSmsManager financialSmsManager = new FinancialSmsManager(getContext());
-                financialSmsManager.getSmsMessages(new RemoteCallback((result) -> {
-                    CursorWindow messages = null;
-                    if (result == null) {
-                        Slog.w(LOG_TAG, "result is null.");
-                    } else {
-                        messages = result.getParcelable(FinancialSmsService.EXTRA_SMS_MSGS);
-                    }
-                    try {
-                        callback.onGetSmsMessagesForFinancialApp(messages);
-                    } catch (RemoteException e) {
-                        // do nothing
-                    }
-                }), params);
-            } else {
-                try {
-                    callback.onGetSmsMessagesForFinancialApp(null);
-                } catch (RemoteException e) {
-                    // do nothing
-                }
-            }
-        }
-
         private int getUidForPackage(String packageName) {
             long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/security/VerityUtils.java b/services/core/java/com/android/server/security/VerityUtils.java
index b1db46f..856a40f 100644
--- a/services/core/java/com/android/server/security/VerityUtils.java
+++ b/services/core/java/com/android/server/security/VerityUtils.java
@@ -26,27 +26,19 @@
 import android.util.apk.ApkSignatureVerifier;
 import android.util.apk.ByteBufferFactory;
 import android.util.apk.SignatureNotFoundException;
-import android.util.apk.VerityBuilder;
 
 import libcore.util.HexEncoding;
 
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.channels.FileChannel;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.security.DigestException;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 
-import sun.security.pkcs.PKCS7;
-
 /** Provides fsverity related operations. */
 abstract public class VerityUtils {
     private static final String TAG = "VerityUtils";
@@ -60,8 +52,6 @@
     /** The maximum size of signature file.  This is just to avoid potential abuse. */
     private static final int MAX_SIGNATURE_FILE_SIZE_BYTES = 8192;
 
-    private static final int COMMON_LINUX_PAGE_SIZE_IN_BYTES = 4096;
-
     private static final boolean DEBUG = false;
 
     /** Returns true if the given file looks like containing an fs-verity signature. */
@@ -74,42 +64,15 @@
         return filePath + FSVERITY_SIGNATURE_FILE_EXTENSION;
     }
 
-    /** Generates Merkle tree and fs-verity metadata then enables fs-verity. */
-    public static void setUpFsverity(@NonNull String filePath, String signaturePath)
-            throws IOException, DigestException, NoSuchAlgorithmException {
-        final PKCS7 pkcs7 = new PKCS7(Files.readAllBytes(Paths.get(signaturePath)));
-        final byte[] expectedMeasurement = pkcs7.getContentInfo().getContentBytes();
-        if (DEBUG) {
-            Slog.d(TAG, "Enabling fs-verity with signed fs-verity measurement "
-                    + bytesToString(expectedMeasurement));
-            Slog.d(TAG, "PKCS#7 info: " + pkcs7);
+    /** Enables fs-verity for the file with a PKCS#7 detached signature file. */
+    public static void setUpFsverity(@NonNull String filePath, @NonNull String signaturePath)
+            throws IOException {
+        if (Files.size(Paths.get(signaturePath)) > MAX_SIGNATURE_FILE_SIZE_BYTES) {
+            throw new SecurityException("Signature file is unexpectedly large: " + signaturePath);
         }
-
-        final TrackedBufferFactory bufferFactory = new TrackedBufferFactory();
-        final byte[] actualMeasurement = generateFsverityMetadata(filePath, signaturePath,
-                bufferFactory);
-        try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
-            FileChannel ch = raf.getChannel();
-            ch.position(roundUpToNextMultiple(ch.size(), COMMON_LINUX_PAGE_SIZE_IN_BYTES));
-            ByteBuffer buffer = bufferFactory.getBuffer();
-
-            long offset = buffer.position();
-            long size = buffer.limit();
-            while (offset < size) {
-                long s = ch.write(buffer);
-                offset += s;
-                size -= s;
-            }
-        }
-
-        if (!Arrays.equals(expectedMeasurement, actualMeasurement)) {
-            throw new SecurityException("fs-verity measurement mismatch: "
-                    + bytesToString(actualMeasurement) + " != "
-                    + bytesToString(expectedMeasurement));
-        }
-
-        // This can fail if the public key is not already in .fs-verity kernel keyring.
-        int errno = enableFsverityNative(filePath);
+        byte[] pkcs7Signature = Files.readAllBytes(Paths.get(signaturePath));
+        // This will fail if the public key is not already in .fs-verity kernel keyring.
+        int errno = enableFsverityNative(filePath, pkcs7Signature);
         if (errno != 0) {
             throw new IOException("Failed to enable fs-verity on " + filePath + ": "
                     + Os.strerror(errno));
@@ -131,12 +94,19 @@
         return true;
     }
 
+    private static native int enableFsverityNative(@NonNull String filePath,
+            @NonNull byte[] pkcs7Signature);
+    private static native int measureFsverityNative(@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);
@@ -173,7 +143,10 @@
 
     /**
      * {@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);
@@ -181,104 +154,16 @@
 
     /**
      * {@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);
     }
 
     /**
-     * Generates fs-verity metadata for {@code filePath} in the buffer created by {@code
-     * trackedBufferFactory}. The metadata contains the Merkle tree, fs-verity descriptor and
-     * extensions, including a PKCS#7 signature provided in {@code signaturePath}.
-     *
-     * <p>It is worthy to note that {@code trackedBufferFactory} generates a "tracked" {@code
-     * ByteBuffer}. The data will be used outside this method via the factory itself.
-     *
-     * @return fs-verity signed data (struct fsverity_digest_disk) of {@code filePath}, which
-     *         includes SHA-256 of fs-verity descriptor and authenticated extensions.
-     */
-    private static byte[] generateFsverityMetadata(String filePath, String signaturePath,
-            @NonNull ByteBufferFactory trackedBufferFactory)
-            throws IOException, DigestException, NoSuchAlgorithmException {
-        try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
-            VerityBuilder.VerityResult result = VerityBuilder.generateFsVerityTree(
-                    file, trackedBufferFactory);
-
-            ByteBuffer buffer = result.verityData;
-            buffer.position(result.merkleTreeSize);
-
-            final byte[] measurement = generateFsverityDescriptorAndMeasurement(file,
-                    result.rootHash, signaturePath, buffer);
-            buffer.flip();
-            return constructFsveritySignedDataNative(measurement);
-        }
-    }
-
-    /**
-     * Generates fs-verity descriptor including the extensions to the {@code output} and returns the
-     * fs-verity measurement.
-     *
-     * @return fs-verity measurement, which is a SHA-256 of fs-verity descriptor and authenticated
-     *         extensions.
-     */
-    private static byte[] generateFsverityDescriptorAndMeasurement(
-            @NonNull RandomAccessFile file, @NonNull byte[] rootHash,
-            @NonNull String pkcs7SignaturePath, @NonNull ByteBuffer output)
-            throws IOException, NoSuchAlgorithmException, DigestException {
-        final short kRootHashExtensionId = 1;
-        final short kPkcs7SignatureExtensionId = 3;
-        final int origPosition = output.position();
-
-        // For generating fs-verity file measurement, which consists of the descriptor and
-        // authenticated extensions (but not unauthenticated extensions and the footer).
-        MessageDigest md = MessageDigest.getInstance("SHA-256");
-
-        // 1. Generate fs-verity descriptor.
-        final byte[] desc = constructFsverityDescriptorNative(file.length());
-        output.put(desc);
-        md.update(desc);
-
-        // 2. Generate authenticated extensions.
-        final byte[] authExt =
-                constructFsverityExtensionNative(kRootHashExtensionId, rootHash.length);
-        output.put(authExt);
-        output.put(rootHash);
-        md.update(authExt);
-        md.update(rootHash);
-
-        // 3. Generate unauthenticated extensions.
-        ByteBuffer header = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
-        output.putShort((short) 1);  // number of unauthenticated extensions below
-        output.position(output.position() + 6);
-
-        // Generate PKCS#7 extension. NB: We do not verify agaist trusted certificate (should be
-        // done by the caller if needed).
-        Path path = Paths.get(pkcs7SignaturePath);
-        if (Files.size(path) > MAX_SIGNATURE_FILE_SIZE_BYTES) {
-            throw new IllegalArgumentException("Signature size is unexpectedly large: "
-                    + pkcs7SignaturePath);
-        }
-        final byte[] pkcs7Signature = Files.readAllBytes(path);
-        output.put(constructFsverityExtensionNative(kPkcs7SignatureExtensionId,
-                    pkcs7Signature.length));
-        output.put(pkcs7Signature);
-
-        // 4. Generate the footer.
-        output.put(constructFsverityFooterNative(output.position() - origPosition));
-
-        return md.digest();
-    }
-
-    private static native int enableFsverityNative(@NonNull String filePath);
-    private static native int measureFsverityNative(@NonNull String filePath);
-    private static native byte[] constructFsveritySignedDataNative(@NonNull byte[] measurement);
-    private static native byte[] constructFsverityDescriptorNative(long fileSize);
-    private static native byte[] constructFsverityExtensionNative(short extensionId,
-            int extensionDataSize);
-    private static native byte[] constructFsverityFooterNative(int offsetToDescriptorHead);
-
-    /**
      * 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
@@ -313,6 +198,11 @@
         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;
@@ -401,30 +291,4 @@
             return mBuffer == null ? -1 : mBuffer.limit();
         }
     }
-
-    /** A {@code ByteBufferFactory} that tracks the {@code ByteBuffer} it creates. */
-    private static class TrackedBufferFactory implements ByteBufferFactory {
-        private ByteBuffer mBuffer;
-
-        @Override
-        public ByteBuffer create(int capacity) {
-            if (mBuffer != null) {
-                throw new IllegalStateException("Multiple instantiation from this factory");
-            }
-            mBuffer = ByteBuffer.allocate(capacity);
-            return mBuffer;
-        }
-
-        public ByteBuffer getBuffer() {
-            return mBuffer;
-        }
-    }
-
-    /** Round up the number to the next multiple of the divisor. */
-    private static long roundUpToNextMultiple(long number, long divisor) {
-        if (number > (Long.MAX_VALUE - divisor)) {
-            throw new IllegalArgumentException("arithmetic overflow");
-        }
-        return ((number + (divisor - 1)) / divisor) * divisor;
-    }
 }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index c76bbb0..0d28b46 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -1112,13 +1112,12 @@
             e.writeLong(modemInfo.getTimestamp());
             e.writeLong(modemInfo.getSleepTimeMillis());
             e.writeLong(modemInfo.getIdleTimeMillis());
-            e.writeLong(modemInfo.getTxTimeMillis()[0]);
-            e.writeLong(modemInfo.getTxTimeMillis()[1]);
-            e.writeLong(modemInfo.getTxTimeMillis()[2]);
-            e.writeLong(modemInfo.getTxTimeMillis()[3]);
-            e.writeLong(modemInfo.getTxTimeMillis()[4]);
-            e.writeLong(modemInfo.getRxTimeMillis());
-            e.writeLong(modemInfo.getEnergyUsed());
+            e.writeLong(modemInfo.getTransmitPowerInfo().get(0).getTimeInMillis());
+            e.writeLong(modemInfo.getTransmitPowerInfo().get(1).getTimeInMillis());
+            e.writeLong(modemInfo.getTransmitPowerInfo().get(2).getTimeInMillis());
+            e.writeLong(modemInfo.getTransmitPowerInfo().get(3).getTimeInMillis());
+            e.writeLong(modemInfo.getTransmitPowerInfo().get(4).getTimeInMillis());
+            e.writeLong(modemInfo.getReceiveTimeMillis());
             pulledData.add(e);
         }
     }
diff --git a/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
deleted file mode 100644
index 0b970bf..0000000
--- a/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
+++ /dev/null
@@ -1,301 +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.timedetector;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.AlarmManager;
-import android.app.timedetector.ManualTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
-import android.util.LocalLog;
-import android.util.Slog;
-import android.util.TimestampedValue;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * An implementation of TimeDetectorStrategy that passes only NITZ suggestions to
- * {@link AlarmManager}.
- *
- * <p>Most public methods are marked synchronized to ensure thread safety around internal state.
- */
-public final class SimpleTimeDetectorStrategy implements TimeDetectorStrategy {
-
-    private static final boolean DBG = false;
-    private static final String LOG_TAG = "SimpleTimeDetectorStrategy";
-
-    @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Origin {}
-
-    /** Used when a time value originated from a telephony signal. */
-    @Origin
-    private static final int ORIGIN_PHONE = 1;
-
-    /** Used when a time value originated from a user / manual settings. */
-    @Origin
-    private static final int ORIGIN_MANUAL = 2;
-
-    /**
-     * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
-     * actual system clock time before a warning is logged. Used to help identify situations where
-     * there is something other than this class setting the system clock automatically.
-     */
-    private static final long SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS = 2 * 1000;
-
-    // A log for changes made to the system clock and why.
-    @NonNull private final LocalLog mTimeChangesLog = new LocalLog(30);
-
-    // @NonNull after initialize()
-    private Callback mCallback;
-
-    // Last phone suggestion.
-    @Nullable private PhoneTimeSuggestion mLastPhoneSuggestion;
-
-    // Information about the last time signal received: Used when toggling auto-time.
-    @Nullable private TimestampedValue<Long> mLastAutoSystemClockTime;
-    private boolean mLastAutoSystemClockTimeSendNetworkBroadcast;
-
-    // System clock state.
-    @Nullable private TimestampedValue<Long> mLastAutoSystemClockTimeSet;
-
-    @Override
-    public void initialize(@NonNull Callback callback) {
-        mCallback = callback;
-    }
-
-    @Override
-    public synchronized void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
-        // NITZ logic
-
-        // Empty suggestions are just ignored as we don't currently keep track of suggestion origin.
-        if (timeSuggestion.getUtcTime() == null) {
-            return;
-        }
-
-        boolean timeSuggestionIsValid =
-                validateNewPhoneSuggestion(timeSuggestion, mLastPhoneSuggestion);
-        if (!timeSuggestionIsValid) {
-            return;
-        }
-        // Always store the last NITZ value received, regardless of whether we go on to use it to
-        // update the system clock. This is so that we can validate future phone suggestions.
-        mLastPhoneSuggestion = timeSuggestion;
-
-        // System clock update logic.
-        final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
-        setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, timeSuggestion);
-    }
-
-    @Override
-    public synchronized void suggestManualTime(ManualTimeSuggestion timeSuggestion) {
-        final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
-        setSystemClockIfRequired(ORIGIN_MANUAL, newUtcTime, timeSuggestion);
-    }
-
-    private static boolean validateNewPhoneSuggestion(@NonNull PhoneTimeSuggestion newSuggestion,
-            @Nullable PhoneTimeSuggestion lastSuggestion) {
-
-        if (lastSuggestion != null) {
-            long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
-                    newSuggestion.getUtcTime(), lastSuggestion.getUtcTime());
-            if (referenceTimeDifference < 0 || referenceTimeDifference > Integer.MAX_VALUE) {
-                // Out of order or bogus.
-                Slog.w(LOG_TAG, "Bad NITZ signal received."
-                        + " referenceTimeDifference=" + referenceTimeDifference
-                        + " lastSuggestion=" + lastSuggestion
-                        + " newSuggestion=" + newSuggestion);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @GuardedBy("this")
-    private void setSystemClockIfRequired(
-            @Origin int origin, TimestampedValue<Long> time, Object cause) {
-        // Historically, Android has sent a TelephonyIntents.ACTION_NETWORK_SET_TIME broadcast only
-        // when setting the time using NITZ.
-        boolean sendNetworkBroadcast = origin == ORIGIN_PHONE;
-
-        boolean isOriginAutomatic = isOriginAutomatic(origin);
-        if (isOriginAutomatic) {
-            // Store the last auto time candidate we've seen in all cases so we can set the system
-            // clock when/if time detection is off but later enabled.
-            mLastAutoSystemClockTime = time;
-            mLastAutoSystemClockTimeSendNetworkBroadcast = sendNetworkBroadcast;
-
-            if (!mCallback.isAutoTimeDetectionEnabled()) {
-                if (DBG) {
-                    Slog.d(LOG_TAG, "Auto time detection is not enabled."
-                            + " time=" + time
-                            + ", cause=" + cause);
-                }
-                return;
-            }
-        } else {
-            if (mCallback.isAutoTimeDetectionEnabled()) {
-                if (DBG) {
-                    Slog.d(LOG_TAG, "Auto time detection is enabled."
-                            + " time=" + time
-                            + ", cause=" + cause);
-                }
-                return;
-            }
-        }
-
-        mCallback.acquireWakeLock();
-        try {
-            long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
-            long actualTimeMillis = mCallback.systemClockMillis();
-
-            if (isOriginAutomatic) {
-                // CLOCK_PARANOIA : Check to see if this class owns the clock or if something else
-                // may be setting the clock.
-                if (mLastAutoSystemClockTimeSet != null) {
-                    long expectedTimeMillis = TimeDetectorStrategy.getTimeAt(
-                            mLastAutoSystemClockTimeSet, elapsedRealtimeMillis);
-                    long absSystemClockDifference = Math.abs(expectedTimeMillis - actualTimeMillis);
-                    if (absSystemClockDifference > SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS) {
-                        Slog.w(LOG_TAG,
-                                "System clock has not tracked elapsed real time clock. A clock may"
-                                        + " be inaccurate or something unexpectedly set the system"
-                                        + " clock."
-                                        + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
-                                        + " expectedTimeMillis=" + expectedTimeMillis
-                                        + " actualTimeMillis=" + actualTimeMillis);
-                    }
-                }
-            }
-
-            adjustAndSetDeviceSystemClock(
-                    time, sendNetworkBroadcast, elapsedRealtimeMillis, actualTimeMillis, cause);
-        } finally {
-            mCallback.releaseWakeLock();
-        }
-    }
-
-    private static boolean isOriginAutomatic(@Origin int origin) {
-        return origin == ORIGIN_PHONE;
-    }
-
-    @Override
-    public synchronized void handleAutoTimeDetectionChanged() {
-        // If automatic time detection is enabled we update the system clock instantly if we can.
-        // Conversely, if automatic time detection is disabled we leave the clock as it is.
-        boolean enabled = mCallback.isAutoTimeDetectionEnabled();
-        if (enabled) {
-            if (mLastAutoSystemClockTime != null) {
-                // Only send the network broadcast if the last candidate would have caused one.
-                final boolean sendNetworkBroadcast = mLastAutoSystemClockTimeSendNetworkBroadcast;
-
-                mCallback.acquireWakeLock();
-                try {
-                    long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
-                    long actualTimeMillis = mCallback.systemClockMillis();
-
-                    final String reason = "Automatic time detection enabled.";
-                    adjustAndSetDeviceSystemClock(mLastAutoSystemClockTime, sendNetworkBroadcast,
-                            elapsedRealtimeMillis, actualTimeMillis, reason);
-                } finally {
-                    mCallback.releaseWakeLock();
-                }
-            }
-        } else {
-            // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
-            // it should be in future.
-            mLastAutoSystemClockTimeSet = null;
-        }
-    }
-
-    @Override
-    public synchronized void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
-        pw.println("mLastPhoneSuggestion=" + mLastPhoneSuggestion);
-        pw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
-        pw.println("mLastAutoSystemClockTime=" + mLastAutoSystemClockTime);
-        pw.println("mLastAutoSystemClockTimeSendNetworkBroadcast="
-                + mLastAutoSystemClockTimeSendNetworkBroadcast);
-
-        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
-
-        ipw.println("TimeDetectorStrategyImpl logs:");
-        ipw.increaseIndent(); // level 1
-
-        ipw.println("Time change log:");
-        ipw.increaseIndent(); // level 2
-        mTimeChangesLog.dump(ipw);
-        ipw.decreaseIndent(); // level 2
-
-        ipw.decreaseIndent(); // level 1
-    }
-
-    @GuardedBy("this")
-    private void adjustAndSetDeviceSystemClock(
-            TimestampedValue<Long> newTime, boolean sendNetworkBroadcast,
-            long elapsedRealtimeMillis, long actualSystemClockMillis, Object cause) {
-
-        // Adjust for the time that has elapsed since the signal was received.
-        long newSystemClockMillis = TimeDetectorStrategy.getTimeAt(newTime, elapsedRealtimeMillis);
-
-        // Check if the new signal would make sufficient difference to the system clock. If it's
-        // below the threshold then ignore it.
-        long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
-        long systemClockUpdateThreshold = mCallback.systemClockUpdateThresholdMillis();
-        if (absTimeDifference < systemClockUpdateThreshold) {
-            if (DBG) {
-                Slog.d(LOG_TAG, "Not setting system clock. New time and"
-                        + " system clock are close enough."
-                        + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
-                        + " newTime=" + newTime
-                        + " cause=" + cause
-                        + " systemClockUpdateThreshold=" + systemClockUpdateThreshold
-                        + " absTimeDifference=" + absTimeDifference);
-            }
-            return;
-        }
-
-        mCallback.setSystemClock(newSystemClockMillis);
-        String logMsg = "Set system clock using time=" + newTime
-                + " cause=" + cause
-                + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
-                + " newSystemClockMillis=" + newSystemClockMillis;
-        if (DBG) {
-            Slog.d(LOG_TAG, logMsg);
-        }
-        mTimeChangesLog.log(logMsg);
-
-        // CLOCK_PARANOIA : Record the last time this class set the system clock.
-        mLastAutoSystemClockTimeSet = newTime;
-
-        if (sendNetworkBroadcast) {
-            // Send a broadcast that telephony code used to send after setting the clock.
-            // TODO Remove this broadcast as soon as there are no remaining listeners.
-            Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
-            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            intent.putExtra("time", newSystemClockMillis);
-            mCallback.sendStickyBroadcast(intent);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 34400ff..668630e 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -31,7 +31,6 @@
 import com.android.internal.util.DumpUtils;
 import com.android.server.FgThread;
 import com.android.server.SystemService;
-import com.android.server.timedetector.TimeDetectorStrategy.Callback;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -58,17 +57,16 @@
 
     @NonNull private final Handler mHandler;
     @NonNull private final Context mContext;
-    @NonNull private final Callback mCallback;
     @NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
 
     private static TimeDetectorService create(@NonNull Context context) {
-        TimeDetectorStrategy timeDetector = new SimpleTimeDetectorStrategy();
+        TimeDetectorStrategy timeDetectorStrategy = new TimeDetectorStrategyImpl();
         TimeDetectorStrategyCallbackImpl callback = new TimeDetectorStrategyCallbackImpl(context);
-        timeDetector.initialize(callback);
+        timeDetectorStrategy.initialize(callback);
 
         Handler handler = FgThread.getHandler();
         TimeDetectorService timeDetectorService =
-                new TimeDetectorService(context, handler, callback, timeDetector);
+                new TimeDetectorService(context, handler, timeDetectorStrategy);
 
         // Wire up event listening.
         ContentResolver contentResolver = context.getContentResolver();
@@ -85,10 +83,9 @@
 
     @VisibleForTesting
     public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
-            @NonNull Callback callback, @NonNull TimeDetectorStrategy timeDetectorStrategy) {
+            @NonNull TimeDetectorStrategy timeDetectorStrategy) {
         mContext = Objects.requireNonNull(context);
         mHandler = Objects.requireNonNull(handler);
-        mCallback = Objects.requireNonNull(callback);
         mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
     }
 
@@ -122,10 +119,14 @@
     }
 
     private void enforceSuggestPhoneTimePermission() {
-        mContext.enforceCallingPermission(android.Manifest.permission.SET_TIME, "set time");
+        mContext.enforceCallingPermission(
+                android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE,
+                "suggest phone time and time zone");
     }
 
     private void enforceSuggestManualTimePermission() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SET_TIME, "set time");
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE,
+                "suggest manual time and time zone");
     }
 }
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 32cee2d..0a6c2e7 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -39,6 +39,12 @@
 
     /**
      * The interface used by the strategy to interact with the surrounding service.
+     *
+     * <p>Note: Because the system properties-derived value {@link #isAutoTimeDetectionEnabled()}
+     * can be modified independently and from different threads (and processes!). its use is prone
+     * to race conditions. That will be true until the responsibility for setting their values is
+     * moved to {@link TimeDetectorStrategy}. There are similar issues with
+     * {@link #systemClockMillis()} while any process can modify the system clock.
      */
     interface Callback {
 
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
new file mode 100644
index 0000000..e30ac8a
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -0,0 +1,517 @@
+/*
+ * 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.timedetector;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AlarmManager;
+import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.PhoneTimeSuggestion;
+import android.content.Intent;
+import android.telephony.TelephonyManager;
+import android.util.LocalLog;
+import android.util.Slog;
+import android.util.TimestampedValue;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ArrayMapWithHistory;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An implementation of TimeDetectorStrategy that passes phone and manual suggestions to
+ * {@link AlarmManager}. When there are multiple phone sources, the one with the lowest ID is used
+ * unless the data becomes too stale.
+ *
+ * <p>Most public methods are marked synchronized to ensure thread safety around internal state.
+ */
+public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
+
+    private static final boolean DBG = false;
+    private static final String LOG_TAG = "SimpleTimeDetectorStrategy";
+
+    /** A score value used to indicate "no score", either due to validation failure or age. */
+    private static final int PHONE_INVALID_SCORE = -1;
+    /** The number of buckets phone suggestions can be put in by age. */
+    private static final int PHONE_BUCKET_COUNT = 24;
+    /** Each bucket is this size. All buckets are equally sized. */
+    @VisibleForTesting
+    static final int PHONE_BUCKET_SIZE_MILLIS = 60 * 60 * 1000;
+    /** Phone suggestions older than this value are considered too old. */
+    @VisibleForTesting
+    static final long PHONE_MAX_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
+
+    @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Origin {}
+
+    /** Used when a time value originated from a telephony signal. */
+    @Origin
+    private static final int ORIGIN_PHONE = 1;
+
+    /** Used when a time value originated from a user / manual settings. */
+    @Origin
+    private static final int ORIGIN_MANUAL = 2;
+
+    /**
+     * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
+     * actual system clock time before a warning is logged. Used to help identify situations where
+     * there is something other than this class setting the system clock.
+     */
+    private static final long SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS = 2 * 1000;
+
+    /** The number of previous phone suggestions to keep for each ID (for use during debugging). */
+    private static final int KEEP_SUGGESTION_HISTORY_SIZE = 30;
+
+    // A log for changes made to the system clock and why.
+    @NonNull
+    private final LocalLog mTimeChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
+
+    // @NonNull after initialize()
+    private Callback mCallback;
+
+    // Used to store the last time the system clock state was set automatically. It is used to
+    // detect (and log) issues with the realtime clock or whether the clock is being set without
+    // going through this strategy code.
+    @GuardedBy("this")
+    @Nullable
+    private TimestampedValue<Long> mLastAutoSystemClockTimeSet;
+
+    /**
+     * A mapping from phoneId to a time suggestion. We typically expect one or two mappings: devices
+     * will have a small number of telephony devices and phoneIds are assumed to be stable.
+     */
+    @GuardedBy("this")
+    private ArrayMapWithHistory<Integer, PhoneTimeSuggestion> mSuggestionByPhoneId =
+            new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+
+    @Override
+    public void initialize(@NonNull Callback callback) {
+        mCallback = callback;
+    }
+
+    @Override
+    public synchronized void suggestManualTime(@NonNull ManualTimeSuggestion suggestion) {
+        final TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
+
+        if (!validateSuggestionTime(newUtcTime, suggestion)) {
+            return;
+        }
+
+        String cause = "Manual time suggestion received: suggestion=" + suggestion;
+        setSystemClockIfRequired(ORIGIN_MANUAL, newUtcTime, cause);
+    }
+
+    @Override
+    public synchronized void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
+        // Empty time suggestion means that telephony network connectivity has been lost.
+        // The passage of time is relentless, and we don't expect our users to use a time machine,
+        // so we can continue relying on previous suggestions when we lose connectivity. This is
+        // unlike time zone, where a user may lose connectivity when boarding a flight and where we
+        // do want to "forget" old signals. Suggestions that are too old are discarded later in the
+        // detection algorithm.
+        if (timeSuggestion.getUtcTime() == null) {
+            return;
+        }
+
+        // Perform validation / input filtering and record the validated suggestion against the
+        // phoneId.
+        if (!validateAndStorePhoneSuggestion(timeSuggestion)) {
+            return;
+        }
+
+        // Now perform auto time detection. The new suggestion may be used to modify the system
+        // clock.
+        String reason = "New phone time suggested. timeSuggestion=" + timeSuggestion;
+        doAutoTimeDetection(reason);
+    }
+
+    @Override
+    public synchronized void handleAutoTimeDetectionChanged() {
+        boolean enabled = mCallback.isAutoTimeDetectionEnabled();
+        // When automatic time detection is enabled we update the system clock instantly if we can.
+        // Conversely, when automatic time detection is disabled we leave the clock as it is.
+        if (enabled) {
+            String reason = "Auto time zone detection setting enabled.";
+            doAutoTimeDetection(reason);
+        } else {
+            // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
+            // it should be in future.
+            mLastAutoSystemClockTimeSet = null;
+        }
+    }
+
+    @Override
+    public synchronized void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
+        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+        ipw.println("TimeDetectorStrategy:");
+        ipw.increaseIndent(); // level 1
+
+        ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
+        ipw.println("mCallback.isAutoTimeDetectionEnabled()="
+                + mCallback.isAutoTimeDetectionEnabled());
+        ipw.println("mCallback.elapsedRealtimeMillis()=" + mCallback.elapsedRealtimeMillis());
+        ipw.println("mCallback.systemClockMillis()=" + mCallback.systemClockMillis());
+        ipw.println("mCallback.systemClockUpdateThresholdMillis()="
+                + mCallback.systemClockUpdateThresholdMillis());
+
+        ipw.println("Time change log:");
+        ipw.increaseIndent(); // level 2
+        mTimeChangesLog.dump(ipw);
+        ipw.decreaseIndent(); // level 2
+
+        ipw.println("Phone suggestion history:");
+        ipw.increaseIndent(); // level 2
+        mSuggestionByPhoneId.dump(ipw);
+        ipw.decreaseIndent(); // level 2
+
+        ipw.decreaseIndent(); // level 1
+        ipw.flush();
+    }
+
+    @GuardedBy("this")
+    private boolean validateAndStorePhoneSuggestion(@NonNull PhoneTimeSuggestion suggestion) {
+        TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
+        if (!validateSuggestionTime(newUtcTime, suggestion)) {
+            // There's probably nothing useful we can do: elsewhere we assume that reference
+            // times are in the past so just stop here.
+            return false;
+        }
+
+        int phoneId = suggestion.getPhoneId();
+        PhoneTimeSuggestion previousSuggestion = mSuggestionByPhoneId.get(phoneId);
+        if (previousSuggestion != null) {
+            // We can log / discard suggestions with obvious issues with the reference time clock.
+            if (previousSuggestion.getUtcTime() == null
+                    || previousSuggestion.getUtcTime().getValue() == null) {
+                // This should be impossible given we only store validated suggestions.
+                Slog.w(LOG_TAG, "Previous suggestion is null or has a null time."
+                        + " previousSuggestion=" + previousSuggestion
+                        + ", suggestion=" + suggestion);
+                return false;
+            }
+
+            long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
+                    newUtcTime, previousSuggestion.getUtcTime());
+            if (referenceTimeDifference < 0) {
+                // The reference time is before the previously received suggestion. Ignore it.
+                Slog.w(LOG_TAG, "Out of order phone suggestion received."
+                        + " referenceTimeDifference=" + referenceTimeDifference
+                        + " previousSuggestion=" + previousSuggestion
+                        + " suggestion=" + suggestion);
+                return false;
+            }
+        }
+
+        // Store the latest suggestion.
+        mSuggestionByPhoneId.put(phoneId, suggestion);
+        return true;
+    }
+
+    private boolean validateSuggestionTime(
+            @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
+        if (newUtcTime.getValue() == null) {
+            Slog.w(LOG_TAG, "Suggested time value is null. suggestion=" + suggestion);
+            return false;
+        }
+
+        // We can validate the suggestion against the reference time clock.
+        long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
+        if (elapsedRealtimeMillis < newUtcTime.getReferenceTimeMillis()) {
+            // elapsedRealtime clock went backwards?
+            Slog.w(LOG_TAG, "New reference time is in the future? Ignoring."
+                    + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+                    + ", suggestion=" + suggestion);
+            return false;
+        }
+        return true;
+    }
+
+    @GuardedBy("this")
+    private void doAutoTimeDetection(@NonNull String detectionReason) {
+        if (!mCallback.isAutoTimeDetectionEnabled()) {
+            // Avoid doing unnecessary work with this (race-prone) check.
+            return;
+        }
+
+        PhoneTimeSuggestion bestPhoneSuggestion = findBestPhoneSuggestion();
+
+        // Work out what to do with the best suggestion.
+        if (bestPhoneSuggestion == null) {
+            // There is no good phone suggestion.
+            if (DBG) {
+                Slog.d(LOG_TAG, "Could not determine time: No best phone suggestion."
+                        + " detectionReason=" + detectionReason);
+            }
+            return;
+        }
+
+        final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
+        String cause = "Found good suggestion."
+                + ", bestPhoneSuggestion=" + bestPhoneSuggestion
+                + ", detectionReason=" + detectionReason;
+        setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
+    }
+
+    @GuardedBy("this")
+    @Nullable
+    private PhoneTimeSuggestion findBestPhoneSuggestion() {
+        long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
+
+        // Phone time suggestions are assumed to be derived from NITZ or NITZ-like signals. These
+        // have a number of limitations:
+        // 1) No guarantee of accuracy ("accuracy of the time information is in the order of
+        // minutes") [1]
+        // 2) No guarantee of regular signals ("dependent on the handset crossing radio network
+        // boundaries") [1]
+        //
+        // [1] https://en.wikipedia.org/wiki/NITZ
+        //
+        // Generally, when there are suggestions from multiple phoneIds they should usually
+        // approximately agree. In cases where signals *are* inaccurate we don't want to vacillate
+        // between signals from two phoneIds. However, it is known for NITZ signals to be incorrect
+        // occasionally, which means we also don't want to stick forever with one phoneId. Without
+        // cross-referencing across sources (e.g. the current device time, NTP), or doing some kind
+        // of statistical analysis of consistency within and across phoneIds, we can't know which
+        // suggestions are more correct.
+        //
+        // For simplicity, we try to value recency, then consistency of phoneId.
+        //
+        // The heuristic works as follows:
+        // Recency: The most recent suggestion from each phone is scored. The score is based on a
+        // discrete age bucket, i.e. so signals received around the same time will be in the same
+        // bucket, thus applying a loose reference time ordering. The suggestion with the highest
+        // score is used.
+        // Consistency: If there a multiple suggestions with the same score, the suggestion with the
+        // lowest phoneId is always taken.
+        //
+        // In the trivial case with a single ID this will just mean that the latest received
+        // suggestion is used.
+
+        PhoneTimeSuggestion bestSuggestion = null;
+        int bestScore = PHONE_INVALID_SCORE;
+        for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
+            Integer phoneId = mSuggestionByPhoneId.keyAt(i);
+            PhoneTimeSuggestion candidateSuggestion = mSuggestionByPhoneId.valueAt(i);
+            if (candidateSuggestion == null) {
+                // Unexpected - null suggestions should never be stored.
+                Slog.w(LOG_TAG, "Latest suggestion unexpectedly null for phoneId."
+                        + " phoneId=" + phoneId);
+                continue;
+            } else if (candidateSuggestion.getUtcTime() == null) {
+                // Unexpected - we do not store empty suggestions.
+                Slog.w(LOG_TAG, "Latest suggestion unexpectedly empty. "
+                        + " candidateSuggestion=" + candidateSuggestion);
+                continue;
+            }
+
+            int candidateScore = scorePhoneSuggestion(elapsedRealtimeMillis, candidateSuggestion);
+            if (candidateScore == PHONE_INVALID_SCORE) {
+                // Expected: This means the suggestion is obviously invalid or just too old.
+                continue;
+            }
+
+            // Higher scores are better.
+            if (bestSuggestion == null || bestScore < candidateScore) {
+                bestSuggestion = candidateSuggestion;
+                bestScore = candidateScore;
+            } else if (bestScore == candidateScore) {
+                // Tie! Use the suggestion with the lowest phoneId.
+                int candidatePhoneId = candidateSuggestion.getPhoneId();
+                int bestPhoneId = bestSuggestion.getPhoneId();
+                if (candidatePhoneId < bestPhoneId) {
+                    bestSuggestion = candidateSuggestion;
+                }
+            }
+        }
+        return bestSuggestion;
+    }
+
+    private static int scorePhoneSuggestion(
+            long elapsedRealtimeMillis, @NonNull PhoneTimeSuggestion timeSuggestion) {
+        // The score is based on the age since receipt. Suggestions are bucketed so two
+        // suggestions in the same bucket from different phoneIds are scored the same.
+        TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
+        long referenceTimeMillis = utcTime.getReferenceTimeMillis();
+        if (referenceTimeMillis > elapsedRealtimeMillis) {
+            // Future times are ignored. They imply the reference time was wrong, or the elapsed
+            // realtime clock has gone backwards, neither of which are supportable situations.
+            Slog.w(LOG_TAG, "Existing suggestion found to be in the future. "
+                    + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+                    + ", timeSuggestion=" + timeSuggestion);
+            return PHONE_INVALID_SCORE;
+        }
+
+        long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
+
+        // Any suggestion > MAX_AGE_MILLIS is treated as too old. Although time is relentless and
+        // predictable, the accuracy of the reference time clock may be poor over long periods which
+        // would lead to errors creeping in. Also, in edge cases where a bad suggestion has been
+        // made and never replaced, it could also mean that the time detection code remains
+        // opinionated using a bad invalid suggestion. This caps that edge case at MAX_AGE_MILLIS.
+        if (ageMillis > PHONE_MAX_AGE_MILLIS) {
+            return PHONE_INVALID_SCORE;
+        }
+
+        // Turn the age into a discrete value: 0 <= bucketIndex < MAX_AGE_HOURS.
+        int bucketIndex = (int) (ageMillis / PHONE_BUCKET_SIZE_MILLIS);
+
+        // We want the lowest bucket index to have the highest score. 0 > score >= BUCKET_COUNT.
+        return PHONE_BUCKET_COUNT - bucketIndex;
+    }
+
+    @GuardedBy("this")
+    private void setSystemClockIfRequired(
+            @Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
+
+        boolean isOriginAutomatic = isOriginAutomatic(origin);
+        if (isOriginAutomatic) {
+            if (!mCallback.isAutoTimeDetectionEnabled()) {
+                if (DBG) {
+                    Slog.d(LOG_TAG, "Auto time detection is not enabled."
+                            + " origin=" + origin
+                            + ", time=" + time
+                            + ", cause=" + cause);
+                }
+                return;
+            }
+        } else {
+            if (mCallback.isAutoTimeDetectionEnabled()) {
+                if (DBG) {
+                    Slog.d(LOG_TAG, "Auto time detection is enabled."
+                            + " origin=" + origin
+                            + ", time=" + time
+                            + ", cause=" + cause);
+                }
+                return;
+            }
+        }
+
+        mCallback.acquireWakeLock();
+        try {
+            setSystemClockUnderWakeLock(origin, time, cause);
+        } finally {
+            mCallback.releaseWakeLock();
+        }
+    }
+
+    private static boolean isOriginAutomatic(@Origin int origin) {
+        return origin == ORIGIN_PHONE;
+    }
+
+    @GuardedBy("this")
+    private void setSystemClockUnderWakeLock(
+            int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) {
+
+        long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
+        boolean isOriginAutomatic = isOriginAutomatic(origin);
+        long actualSystemClockMillis = mCallback.systemClockMillis();
+        if (isOriginAutomatic) {
+            // CLOCK_PARANOIA : Check to see if this class owns the clock or if something else
+            // may be setting the clock.
+            if (mLastAutoSystemClockTimeSet != null) {
+                long expectedTimeMillis = TimeDetectorStrategy.getTimeAt(
+                        mLastAutoSystemClockTimeSet, elapsedRealtimeMillis);
+                long absSystemClockDifference =
+                        Math.abs(expectedTimeMillis - actualSystemClockMillis);
+                if (absSystemClockDifference > SYSTEM_CLOCK_PARANOIA_THRESHOLD_MILLIS) {
+                    Slog.w(LOG_TAG,
+                            "System clock has not tracked elapsed real time clock. A clock may"
+                                    + " be inaccurate or something unexpectedly set the system"
+                                    + " clock."
+                                    + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+                                    + " expectedTimeMillis=" + expectedTimeMillis
+                                    + " actualTimeMillis=" + actualSystemClockMillis
+                                    + " cause=" + cause);
+                }
+            }
+        }
+
+        // Adjust for the time that has elapsed since the signal was received.
+        long newSystemClockMillis = TimeDetectorStrategy.getTimeAt(newTime, elapsedRealtimeMillis);
+
+        // Check if the new signal would make sufficient difference to the system clock. If it's
+        // below the threshold then ignore it.
+        long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
+        long systemClockUpdateThreshold = mCallback.systemClockUpdateThresholdMillis();
+        if (absTimeDifference < systemClockUpdateThreshold) {
+            if (DBG) {
+                Slog.d(LOG_TAG, "Not setting system clock. New time and"
+                        + " system clock are close enough."
+                        + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+                        + " newTime=" + newTime
+                        + " cause=" + cause
+                        + " systemClockUpdateThreshold=" + systemClockUpdateThreshold
+                        + " absTimeDifference=" + absTimeDifference);
+            }
+            return;
+        }
+
+        mCallback.setSystemClock(newSystemClockMillis);
+        String logMsg = "Set system clock using time=" + newTime
+                + " cause=" + cause
+                + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+                + " newSystemClockMillis=" + newSystemClockMillis;
+        if (DBG) {
+            Slog.d(LOG_TAG, logMsg);
+        }
+        mTimeChangesLog.log(logMsg);
+
+        // CLOCK_PARANOIA : Record the last time this class set the system clock due to an auto-time
+        // signal, or clear the record it is being done manually.
+        if (isOriginAutomatic(origin)) {
+            mLastAutoSystemClockTimeSet = newTime;
+        } else {
+            mLastAutoSystemClockTimeSet = null;
+        }
+
+        // Historically, Android has sent a TelephonyManager.ACTION_NETWORK_SET_TIME broadcast only
+        // when setting the time using NITZ.
+        if (origin == ORIGIN_PHONE) {
+            // Send a broadcast that telephony code used to send after setting the clock.
+            // TODO Remove this broadcast as soon as there are no remaining listeners.
+            Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_SET_TIME);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.putExtra("time", newSystemClockMillis);
+            mCallback.sendStickyBroadcast(intent);
+        }
+    }
+
+    /**
+     * Returns the current best phone suggestion. Not intended for general use: it is used during
+     * tests to check strategy behavior.
+     */
+    @VisibleForTesting
+    @Nullable
+    public synchronized PhoneTimeSuggestion findBestPhoneSuggestionForTests() {
+        return findBestPhoneSuggestion();
+    }
+
+    /**
+     * A method used to inspect state during tests. Not intended for general use.
+     */
+    @VisibleForTesting
+    @Nullable
+    public synchronized PhoneTimeSuggestion getLatestPhoneSuggestion(int phoneId) {
+        return mSuggestionByPhoneId.get(phoneId);
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java b/services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java
new file mode 100644
index 0000000..3274f0e
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ArrayMapWithHistory.java
@@ -0,0 +1,187 @@
+/*
+ * 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.timezonedetector;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+
+/**
+ * A partial decorator for {@link ArrayMap} that records historic values for each mapping for
+ * debugging later with {@link #dump(IndentingPrintWriter)}.
+ *
+ * <p>This class is only intended for use in {@link TimeZoneDetectorStrategy} and
+ * {@link com.android.server.timedetector.TimeDetectorStrategy} so only provides the parts of the
+ * {@link ArrayMap} API needed. If it is ever extended to include deletion methods like
+ * {@link ArrayMap#remove(Object)} some thought would need to be given to the correct
+ * {@link ArrayMap#containsKey(Object)} behavior for the history. Like {@link ArrayMap}, it is not
+ * thread-safe.
+ *
+ * @param <K> the type of the key
+ * @param <V> the type of the value
+ */
+public final class ArrayMapWithHistory<K, V> {
+    private static final String TAG = "ArrayMapWithHistory";
+
+    /** The size the linked list against each value is allowed to grow to. */
+    private final int mMaxHistorySize;
+
+    @Nullable
+    private ArrayMap<K, ReferenceWithHistory<V>> mMap;
+
+    /**
+     * Creates an instance that records, at most, the specified number of values against each key.
+     */
+    public ArrayMapWithHistory(@IntRange(from = 1) int maxHistorySize) {
+        if (maxHistorySize < 1) {
+            throw new IllegalArgumentException("maxHistorySize < 1: " + maxHistorySize);
+        }
+        mMaxHistorySize = maxHistorySize;
+    }
+
+    /**
+     * See {@link ArrayMap#put(K, V)}.
+     */
+    @Nullable
+    public V put(@Nullable K key, @Nullable V value) {
+        if (mMap == null) {
+            mMap = new ArrayMap<>();
+        }
+
+        ReferenceWithHistory<V> valueHolder = mMap.get(key);
+        if (valueHolder == null) {
+            valueHolder = new ReferenceWithHistory<>(mMaxHistorySize);
+            mMap.put(key, valueHolder);
+        } else if (valueHolder.getHistoryCount() == 0) {
+            Log.w(TAG, "History for \"" + key + "\" was unexpectedly empty");
+        }
+
+        return valueHolder.set(value);
+    }
+
+    /**
+     * See {@link ArrayMap#get(Object)}.
+     */
+    @Nullable
+    public V get(@Nullable Object key) {
+        if (mMap == null) {
+            return null;
+        }
+
+        ReferenceWithHistory<V> valueHolder = mMap.get(key);
+        if (valueHolder == null) {
+            return null;
+        } else if (valueHolder.getHistoryCount() == 0) {
+            Log.w(TAG, "History for \"" + key + "\" was unexpectedly empty");
+        }
+        return valueHolder.get();
+    }
+
+    /**
+     * See {@link ArrayMap#size()}.
+     */
+    public int size() {
+        return mMap == null ? 0 : mMap.size();
+    }
+
+    /**
+     * See {@link ArrayMap#keyAt(int)}.
+     */
+    @Nullable
+    public K keyAt(int index) {
+        if (mMap == null) {
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
+        return mMap.keyAt(index);
+    }
+
+    /**
+     * See {@link ArrayMap#valueAt(int)}.
+     */
+    @Nullable
+    public V valueAt(int index) {
+        if (mMap == null) {
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
+
+        ReferenceWithHistory<V> valueHolder = mMap.valueAt(index);
+        if (valueHolder == null || valueHolder.getHistoryCount() == 0) {
+            Log.w(TAG, "valueAt(" + index + ") was unexpectedly null or empty");
+            return null;
+        }
+        return valueHolder.get();
+    }
+
+    /**
+     * Dumps the content of the map, including historic values, using the supplied writer.
+     */
+    public void dump(@NonNull IndentingPrintWriter ipw) {
+        if (mMap == null) {
+            ipw.println("{Empty}");
+        } else {
+            for (int i = 0; i < mMap.size(); i++) {
+                ipw.println("key idx: " + i + "=" + mMap.keyAt(i));
+                ReferenceWithHistory<V> value = mMap.valueAt(i);
+                ipw.println("val idx: " + i + "=" +  value);
+                ipw.increaseIndent();
+
+                ipw.println("Historic values=[");
+                ipw.increaseIndent();
+                value.dump(ipw);
+                ipw.decreaseIndent();
+                ipw.println("]");
+
+                ipw.decreaseIndent();
+            }
+        }
+        ipw.flush();
+    }
+
+    /**
+     * Internal method intended for tests that returns the number of historic values associated with
+     * the supplied key currently. If there is no mapping for the key then {@code 0} is returned.
+     */
+    @VisibleForTesting
+    public int getHistoryCountForKeyForTests(@Nullable K key) {
+        if (mMap == null) {
+            return 0;
+        }
+
+        ReferenceWithHistory<V> valueHolder = mMap.get(key);
+        if (valueHolder == null) {
+            return 0;
+        } else if (valueHolder.getHistoryCount() == 0) {
+            Log.w(TAG, "getValuesSizeForKeyForTests(\"" + key + "\") was unexpectedly empty");
+            return 0;
+        } else {
+            return valueHolder.getHistoryCount();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ArrayMapWithHistory{"
+                + "mHistorySize=" + mMaxHistorySize
+                + ", mMap=" + mMap
+                + '}';
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
new file mode 100644
index 0000000..8bd1035
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezonedetector;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.util.LinkedList;
+
+/**
+ * A class that behaves like the following definition, except it stores the history of values set
+ * that can be dumped for debugging with {@link #dump(IndentingPrintWriter)}.
+ *
+ * <pre>{@code
+ *     private static class Ref<V> {
+ *         private V mValue;
+ *
+ *         public V get() {
+ *             return mValue;
+ *         }
+ *
+ *         public V set(V value) {
+ *             V previous = mValue;
+ *             mValue = value;
+ *             return previous;
+ *         }
+ *     }
+ * }</pre>
+ *
+ * <p>This class is not thread-safe.
+ *
+ * @param <V> the type of the value
+ */
+public final class ReferenceWithHistory<V> {
+
+    /** The size the history linked list is allowed to grow to. */
+    private final int mMaxHistorySize;
+
+    @Nullable
+    private LinkedList<V> mValues;
+
+    /**
+     * Creates an instance that records, at most, the specified number of values.
+     */
+    public ReferenceWithHistory(@IntRange(from = 1) int maxHistorySize) {
+        if (maxHistorySize < 1) {
+            throw new IllegalArgumentException("maxHistorySize < 1: " + maxHistorySize);
+        }
+        this.mMaxHistorySize = maxHistorySize;
+    }
+
+    /** Returns the current value, or {@code null} if it has never been set. */
+    @Nullable
+    public V get() {
+        return (mValues == null || mValues.isEmpty()) ? null : mValues.getFirst();
+    }
+
+    /** Sets the current value. Returns the previous value, or {@code null}. */
+    @Nullable
+    public V set(@Nullable V newValue) {
+        if (mValues == null) {
+            mValues = new LinkedList<>();
+        }
+
+        V previous = get();
+
+        mValues.addFirst(newValue);
+        if (mValues.size() > mMaxHistorySize) {
+            mValues.removeLast();
+        }
+        return previous;
+    }
+
+    /**
+     * Dumps the content of the reference, including historic values, using the supplied writer.
+     */
+    public void dump(@NonNull IndentingPrintWriter ipw) {
+        if (mValues == null) {
+            ipw.println("{Empty}");
+        } else {
+            int i = 0;
+            for (V value : mValues) {
+                ipw.println(i + ": " + value);
+                i++;
+            }
+        }
+        ipw.flush();
+    }
+
+    /**
+     * Returns the number of historic entries stored currently.
+     */
+    public int getHistoryCount() {
+        return mValues == null ? 0 : mValues.size();
+    }
+
+    @Override
+    public String toString() {
+        return String.valueOf(get());
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
index e034ad4..adf6d7e 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
@@ -20,13 +20,9 @@
 import android.app.AlarmManager;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.os.SystemProperties;
-import android.os.UserHandle;
 import android.provider.Settings;
 
-import com.android.internal.telephony.TelephonyIntents;
-
 /**
  * The real implementation of {@link TimeZoneDetectorStrategy.Callback}.
  */
@@ -66,16 +62,8 @@
     }
 
     @Override
-    public void setDeviceTimeZone(String zoneId, boolean sendNetworkBroadcast) {
+    public void setDeviceTimeZone(String zoneId) {
         AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
         alarmManager.setTimeZone(zoneId);
-
-        if (sendNetworkBroadcast) {
-            // TODO Nothing in the platform appears to listen for this. Remove it.
-            Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
-            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            intent.putExtra("time-zone", zoneId);
-            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-        }
     }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 5db12c7..b4a4399 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -27,7 +27,6 @@
 import android.app.timezonedetector.ManualTimeZoneSuggestion;
 import android.app.timezonedetector.PhoneTimeZoneSuggestion;
 import android.content.Context;
-import android.util.ArrayMap;
 import android.util.LocalLog;
 import android.util.Slog;
 
@@ -38,8 +37,6 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.LinkedList;
-import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -86,7 +83,7 @@
         /**
          * Sets the device's time zone.
          */
-        void setDeviceTimeZone(@NonNull String zoneId, boolean sendNetworkBroadcast);
+        void setDeviceTimeZone(@NonNull String zoneId);
     }
 
     private static final String LOG_TAG = "TimeZoneDetectorStrategy";
@@ -172,17 +169,16 @@
      * (for use during debugging).
      */
     @NonNull
-    private final LocalLog mTimeZoneChangesLog = new LocalLog(30);
+    private final LocalLog mTimeZoneChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
 
     /**
-     * A mapping from phoneId to a linked list of phone time zone suggestions (the head being the
-     * latest). We typically expect one or two entries in this Map: devices will have a small number
-     * of telephony devices and phoneIds are assumed to be stable. The LinkedList associated with
-     * the ID will not exceed {@link #KEEP_PHONE_SUGGESTION_HISTORY_SIZE} in size.
+     * A mapping from phoneId to a phone time zone suggestion. We typically expect one or two
+     * mappings: devices will have a small number of telephony devices and phoneIds are assumed to
+     * be stable.
      */
     @GuardedBy("this")
-    private ArrayMap<Integer, LinkedList<QualifiedPhoneTimeZoneSuggestion>> mSuggestionByPhoneId =
-            new ArrayMap<>();
+    private ArrayMapWithHistory<Integer, QualifiedPhoneTimeZoneSuggestion> mSuggestionByPhoneId =
+            new ArrayMapWithHistory<>(KEEP_PHONE_SUGGESTION_HISTORY_SIZE);
 
     /**
      * Creates a new instance of {@link TimeZoneDetectorStrategy}.
@@ -226,16 +222,7 @@
                 new QualifiedPhoneTimeZoneSuggestion(suggestion, score);
 
         // Store the suggestion against the correct phoneId.
-        LinkedList<QualifiedPhoneTimeZoneSuggestion> suggestions =
-                mSuggestionByPhoneId.get(suggestion.getPhoneId());
-        if (suggestions == null) {
-            suggestions = new LinkedList<>();
-            mSuggestionByPhoneId.put(suggestion.getPhoneId(), suggestions);
-        }
-        suggestions.addFirst(scoredSuggestion);
-        if (suggestions.size() > KEEP_PHONE_SUGGESTION_HISTORY_SIZE) {
-            suggestions.removeLast();
-        }
+        mSuggestionByPhoneId.put(suggestion.getPhoneId(), scoredSuggestion);
 
         // Now perform auto time zone detection. The new suggestion may be used to modify the time
         // zone setting.
@@ -333,7 +320,6 @@
         Objects.requireNonNull(newZoneId);
         Objects.requireNonNull(cause);
 
-        boolean sendNetworkBroadcast = (origin == ORIGIN_PHONE);
         boolean isOriginAutomatic = isOriginAutomatic(origin);
         if (isOriginAutomatic) {
             if (!mCallback.isAutoTimeZoneDetectionEnabled()) {
@@ -373,12 +359,11 @@
             return;
         }
 
-        mCallback.setDeviceTimeZone(newZoneId, sendNetworkBroadcast);
+        mCallback.setDeviceTimeZone(newZoneId);
         String msg = "Set device time zone."
                 + " origin=" + origin
                 + ", currentZoneId=" + currentZoneId
                 + ", newZoneId=" + newZoneId
-                + ", sendNetworkBroadcast" + sendNetworkBroadcast
                 + ", cause=" + cause;
         if (DBG) {
             Slog.d(LOG_TAG, msg);
@@ -387,7 +372,7 @@
     }
 
     private static boolean isOriginAutomatic(@Origin int origin) {
-        return origin == ORIGIN_PHONE;
+        return origin != ORIGIN_MANUAL;
     }
 
     @GuardedBy("this")
@@ -400,13 +385,7 @@
         // rate-limit so age is not a strong indicator of confidence. Instead, the callers are
         // expected to withdraw suggestions they no longer have confidence in.
         for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
-            LinkedList<QualifiedPhoneTimeZoneSuggestion> phoneSuggestions =
-                    mSuggestionByPhoneId.valueAt(i);
-            if (phoneSuggestions == null) {
-                // Unexpected
-                continue;
-            }
-            QualifiedPhoneTimeZoneSuggestion candidateSuggestion = phoneSuggestions.getFirst();
+            QualifiedPhoneTimeZoneSuggestion candidateSuggestion = mSuggestionByPhoneId.valueAt(i);
             if (candidateSuggestion == null) {
                 // Unexpected
                 continue;
@@ -458,15 +437,17 @@
      * Dumps internal state such as field values.
      */
     public synchronized void dumpState(PrintWriter pw, String[] args) {
-        pw.println("TimeZoneDetectorStrategy:");
-        pw.println("mCallback.isTimeZoneDetectionEnabled()="
+        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+        ipw.println("TimeZoneDetectorStrategy:");
+
+        ipw.increaseIndent(); // level 1
+        ipw.println("mCallback.isTimeZoneDetectionEnabled()="
                 + mCallback.isAutoTimeZoneDetectionEnabled());
-        pw.println("mCallback.isDeviceTimeZoneInitialized()="
+        ipw.println("mCallback.isDeviceTimeZoneInitialized()="
                 + mCallback.isDeviceTimeZoneInitialized());
-        pw.println("mCallback.getDeviceTimeZone()="
+        ipw.println("mCallback.getDeviceTimeZone()="
                 + mCallback.getDeviceTimeZone());
 
-        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
         ipw.println("Time zone change log:");
         ipw.increaseIndent(); // level 2
         mTimeZoneChangesLog.dump(ipw);
@@ -474,21 +455,10 @@
 
         ipw.println("Phone suggestion history:");
         ipw.increaseIndent(); // level 2
-        for (Map.Entry<Integer, LinkedList<QualifiedPhoneTimeZoneSuggestion>> entry
-                : mSuggestionByPhoneId.entrySet()) {
-            ipw.println("Phone " + entry.getKey());
-
-            ipw.increaseIndent(); // level 3
-            for (QualifiedPhoneTimeZoneSuggestion suggestion : entry.getValue()) {
-                ipw.println(suggestion);
-            }
-            ipw.decreaseIndent(); // level 3
-        }
+        mSuggestionByPhoneId.dump(ipw);
         ipw.decreaseIndent(); // level 2
         ipw.decreaseIndent(); // level 1
         ipw.flush();
-
-        pw.flush();
     }
 
     /**
@@ -496,12 +466,7 @@
      */
     @VisibleForTesting
     public synchronized QualifiedPhoneTimeZoneSuggestion getLatestPhoneSuggestion(int phoneId) {
-        LinkedList<QualifiedPhoneTimeZoneSuggestion> suggestions =
-                mSuggestionByPhoneId.get(phoneId);
-        if (suggestions == null) {
-            return null;
-        }
-        return suggestions.getFirst();
+        return mSuggestionByPhoneId.get(phoneId);
     }
 
     /**
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
old mode 100644
new mode 100755
index 8e66b14..5b58199
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1814,8 +1814,8 @@
         }
 
         @Override
-        public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device)
-                throws RemoteException {
+        public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info,
+                @TvInputManager.DvbDeviceType int deviceType)  throws RemoteException {
             if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE)
                     != PackageManager.PERMISSION_GRANTED) {
                 throw new SecurityException("Requires DVB_DEVICE permission");
@@ -1852,7 +1852,7 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 String deviceFileName;
-                switch (device) {
+                switch (deviceType) {
                     case TvInputManager.DVB_DEVICE_DEMUX:
                         deviceFileName = String.format(dvbDeviceFound
                                 ? "/dev/dvb/adapter%d/demux%d" : "/dev/dvb%d.demux%d",
@@ -1869,14 +1869,14 @@
                                 info.getAdapterId(), info.getDeviceId());
                         break;
                     default:
-                        throw new IllegalArgumentException("Invalid DVB device: " + device);
+                        throw new IllegalArgumentException("Invalid DVB device: " + deviceType);
                 }
                 try {
                     // The DVB frontend device only needs to be opened in read/write mode, which
                     // allows performing tuning operations. The DVB demux and DVR device are enough
                     // to be opened in read only mode.
                     return ParcelFileDescriptor.open(new File(deviceFileName),
-                            TvInputManager.DVB_DEVICE_FRONTEND == device
+                            TvInputManager.DVB_DEVICE_FRONTEND == deviceType
                                     ? ParcelFileDescriptor.MODE_READ_WRITE
                                     : ParcelFileDescriptor.MODE_READ_ONLY);
                 } catch (FileNotFoundException e) {
@@ -2943,6 +2943,16 @@
                 if (state != null) {
                     setStateLocked(inputId, state, mCurrentUserId);
                 }
+                UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
+                // Broadcast the event to all hardware inputs.
+                for (ServiceState serviceState : userState.serviceStateMap.values()) {
+                    if (!serviceState.isHardware || serviceState.service == null) continue;
+                    try {
+                        serviceState.service.notifyHdmiDeviceUpdated(deviceInfo);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in notifyHdmiDeviceUpdated", e);
+                    }
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3e7fea2..54ab906e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4807,7 +4807,11 @@
         // Re-parent IME's SurfaceControl when MagnificationSpec changed.
         updateImeParent();
 
-        applyMagnificationSpec(getPendingTransaction(), spec);
+        if (spec.scale != 1.0) {
+            applyMagnificationSpec(getPendingTransaction(), spec);
+        } else {
+            clearMagnificationSpec(getPendingTransaction());
+        }
         getPendingTransaction().apply();
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index bbef261..1a3704e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -137,6 +137,8 @@
      */
     private boolean mCommittedReparentToAnimationLeash;
 
+    private MagnificationSpec mLastMagnificationSpec;
+
     WindowContainer(WindowManagerService wms) {
         mWmService = wms;
         mPendingTransaction = wms.mTransactionFactory.make();
@@ -1186,13 +1188,26 @@
         if (shouldMagnify()) {
             t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
                     .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
+            mLastMagnificationSpec = spec;
         } else {
+            clearMagnificationSpec(t);
             for (int i = 0; i < mChildren.size(); i++) {
                 mChildren.get(i).applyMagnificationSpec(t, spec);
             }
         }
     }
 
+    void clearMagnificationSpec(Transaction t) {
+        if (mLastMagnificationSpec != null) {
+            t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
+                .setPosition(mSurfaceControl, 0, 0);
+        }
+        mLastMagnificationSpec = null;
+        for (int i = 0; i < mChildren.size(); i++) {
+            mChildren.get(i).clearMagnificationSpec(t);
+        }
+    }
+
     void prepareSurfaces() {
         // If a leash has been set when the transaction was committed, then the leash reparent has
         // been committed.
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index dcff5a1..6811e6d 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -410,6 +410,21 @@
     return 0;
 }
 
+static void vibratorAlwaysOnEnable(JNIEnv* env, jclass, jlong id, jlong effect, jlong strength) {
+    auto status = halCall(&aidl::IVibrator::alwaysOnEnable, id,
+            static_cast<aidl::Effect>(effect), static_cast<aidl::EffectStrength>(strength));
+    if (!status.isOk()) {
+        ALOGE("vibratortAlwaysOnEnable command failed (%s).", status.toString8().string());
+    }
+}
+
+static void vibratorAlwaysOnDisable(JNIEnv* env, jclass, jlong id) {
+    auto status = halCall(&aidl::IVibrator::alwaysOnDisable, id);
+    if (!status.isOk()) {
+        ALOGE("vibratorAlwaysOnDisable command failed (%s).", status.toString8().string());
+    }
+}
+
 static const JNINativeMethod method_table[] = {
     { "vibratorExists", "()Z", (void*)vibratorExists },
     { "vibratorInit", "()V", (void*)vibratorInit },
@@ -422,6 +437,8 @@
     { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
     { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
     { "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
+    { "vibratorAlwaysOnEnable", "(JJJ)V", (void*)vibratorAlwaysOnEnable},
+    { "vibratorAlwaysOnDisable", "(J)V", (void*)vibratorAlwaysOnDisable},
 };
 
 int register_android_server_VibratorService(JNIEnv *env)
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 4d4a7b4..4696dd0 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -54,7 +54,7 @@
     TCP_TX_PACKETS = 5
 };
 
-static uint64_t getStatsType(struct Stats* stats, StatsType type) {
+static uint64_t getStatsType(Stats* stats, StatsType type) {
     switch (type) {
         case RX_BYTES:
             return stats->rxBytes;
@@ -73,7 +73,7 @@
     }
 }
 
-static int parseIfaceStats(const char* iface, struct Stats* stats) {
+static int parseIfaceStats(const char* iface, Stats* stats) {
     FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
     if (fp == NULL) {
         return -1;
@@ -117,7 +117,7 @@
     return 0;
 }
 
-static int parseUidStats(const uint32_t uid, struct Stats* stats) {
+static int parseUidStats(const uint32_t uid, Stats* stats) {
     FILE *fp = fopen(QTAGUID_UID_STATS, "r");
     if (fp == NULL) {
         return -1;
@@ -150,8 +150,7 @@
 }
 
 static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
-    struct Stats stats;
-    memset(&stats, 0, sizeof(Stats));
+    Stats stats = {};
 
     if (useBpfStats) {
         if (bpfGetIfaceStats(NULL, &stats) == 0) {
@@ -175,8 +174,7 @@
         return UNKNOWN;
     }
 
-    struct Stats stats;
-    memset(&stats, 0, sizeof(Stats));
+    Stats stats = {};
 
     if (useBpfStats) {
         if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
@@ -194,8 +192,7 @@
 }
 
 static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
-    struct Stats stats;
-    memset(&stats, 0, sizeof(Stats));
+    Stats stats = {};
 
     if (useBpfStats) {
         if (bpfGetUidStats(uid, &stats) == 0) {
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index 6cd9f2c..76977a5 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -22,6 +22,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/fsverity.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
@@ -31,120 +32,30 @@
 
 #include <android-base/unique_fd.h>
 
-// TODO(112037636): Always include once fsverity.h is upstreamed.
-#if __has_include(<linux/fsverity.h>)
-#include <linux/fsverity.h>
-#else
-
-// Before fs-verity is upstreamed, use the current snapshot for development.
-// https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git/tree/include/uapi/linux/fsverity.h?h=fsverity
-
-#include <linux/limits.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-struct fsverity_digest {
-    __u16 digest_algorithm;
-    __u16 digest_size; /* input/output */
-    __u8 digest[];
-};
-
-#define FS_IOC_ENABLE_VERITY	_IO('f', 133)
-#define FS_IOC_MEASURE_VERITY	_IOWR('f', 134, struct fsverity_digest)
-
-#define FS_VERITY_MAGIC		"FSVerity"
-
-#define FS_VERITY_ALG_SHA256	1
-
-struct fsverity_descriptor {
-    __u8 magic[8];		/* must be FS_VERITY_MAGIC */
-    __u8 major_version;	/* must be 1 */
-    __u8 minor_version;	/* must be 0 */
-    __u8 log_data_blocksize;/* log2(data-bytes-per-hash), e.g. 12 for 4KB */
-    __u8 log_tree_blocksize;/* log2(tree-bytes-per-hash), e.g. 12 for 4KB */
-    __le16 data_algorithm;	/* hash algorithm for data blocks */
-    __le16 tree_algorithm;	/* hash algorithm for tree blocks */
-    __le32 flags;		/* flags */
-    __le32 __reserved1;	/* must be 0 */
-    __le64 orig_file_size;	/* size of the original file data */
-    __le16 auth_ext_count;	/* number of authenticated extensions */
-    __u8 __reserved2[30];	/* must be 0 */
-};
-
-#define FS_VERITY_EXT_ROOT_HASH		1
-#define FS_VERITY_EXT_PKCS7_SIGNATURE	3
-
-struct fsverity_extension {
-    __le32 length;
-    __le16 type;		/* Type of this extension (see codes above) */
-    __le16 __reserved;	/* Reserved, must be 0 */
-};
-
-struct fsverity_digest_disk {
-    __le16 digest_algorithm;
-    __le16 digest_size;
-    __u8 digest[];
-};
-
-struct fsverity_footer {
-    __le32 desc_reverse_offset;	/* distance to fsverity_descriptor */
-    __u8 magic[8];			/* FS_VERITY_MAGIC */
-} __packed;
-
-#endif
-
 const int kSha256Bytes = 32;
 
 namespace android {
 
 namespace {
 
-class JavaByteArrayHolder {
-  public:
-    JavaByteArrayHolder(const JavaByteArrayHolder &other) = delete;
-    JavaByteArrayHolder(JavaByteArrayHolder &&other)
-          : mEnv(other.mEnv), mBytes(other.mBytes), mElements(other.mElements) {
-        other.mElements = nullptr;
-    }
-
-    static JavaByteArrayHolder newArray(JNIEnv* env, jsize size) {
-        return JavaByteArrayHolder(env, size);
-    }
-
-    jbyte* getRaw() {
-        return mElements;
-    }
-
-    jbyteArray release() {
-        mEnv->ReleaseByteArrayElements(mBytes, mElements, 0);
-        mElements = nullptr;
-        return mBytes;
-    }
-
-    ~JavaByteArrayHolder() {
-        LOG_ALWAYS_FATAL_IF(mElements != nullptr, "Elements are not released");
-    }
-
-  private:
-    JavaByteArrayHolder(JNIEnv* env, jsize size) {
-        mEnv = env;
-        mBytes = mEnv->NewByteArray(size);
-        mElements = mEnv->GetByteArrayElements(mBytes, nullptr);
-        memset(mElements, 0, size);
-    }
-
-    JNIEnv* mEnv;
-    jbyteArray mBytes;
-    jbyte* mElements;
-};
-
-int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
+int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath, jbyteArray signature) {
     const char* path = env->GetStringUTFChars(filePath, nullptr);
     ::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
+    env->ReleaseStringUTFChars(filePath, path);
     if (rfd.get() < 0) {
       return errno;
     }
-    if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, nullptr) < 0) {
+
+    fsverity_enable_arg arg = {};
+    arg.version = 1;
+    arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
+    arg.block_size = 4096;
+    arg.salt_size = 0;
+    arg.salt_ptr = reinterpret_cast<uintptr_t>(nullptr);
+    arg.sig_size = env->GetArrayLength(signature);
+    arg.sig_ptr = reinterpret_cast<uintptr_t>(signature);
+
+    if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, &arg) < 0) {
       return errno;
     }
     return 0;
@@ -159,6 +70,7 @@
 
     const char* path = env->GetStringUTFChars(filePath, nullptr);
     ::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
+    env->ReleaseStringUTFChars(filePath, path);
     if (rfd.get() < 0) {
       return errno;
     }
@@ -168,71 +80,9 @@
     return 0;
 }
 
-jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteArray digest) {
-    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest_disk) + kSha256Bytes);
-    fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii.getRaw());
-
-    data->digest_algorithm = FS_VERITY_ALG_SHA256;
-    data->digest_size = kSha256Bytes;
-    if (env->GetArrayLength(digest) != kSha256Bytes) {
-        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid hash size of %d",
-                          env->GetArrayLength(digest));
-        return 0;
-    }
-    const jbyte* src = env->GetByteArrayElements(digest, nullptr);
-    memcpy(data->digest, src, kSha256Bytes);
-
-    return raii.release();
-}
-
-
-jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong fileSize) {
-    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_descriptor));
-    fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii.getRaw());
-
-    memcpy(desc->magic, FS_VERITY_MAGIC, sizeof(desc->magic));
-    desc->major_version = 1;
-    desc->minor_version = 0;
-    desc->log_data_blocksize = 12;
-    desc->log_tree_blocksize = 12;
-    desc->data_algorithm = FS_VERITY_ALG_SHA256;
-    desc->tree_algorithm = FS_VERITY_ALG_SHA256;
-    desc->flags = 0;
-    desc->orig_file_size = fileSize;
-    desc->auth_ext_count = 1;
-
-    return raii.release();
-}
-
-jbyteArray constructFsverityExtension(JNIEnv* env, jobject /* clazz */, jshort extensionId,
-        jint extensionDataSize) {
-    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_extension));
-    fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii.getRaw());
-
-    ext->length = sizeof(fsverity_extension) + extensionDataSize;
-    ext->type = extensionId;
-
-    return raii.release();
-}
-
-jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */,
-        jint offsetToDescriptorHead) {
-    auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_footer));
-    fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii.getRaw());
-
-    footer->desc_reverse_offset = offsetToDescriptorHead + sizeof(fsverity_footer);
-    memcpy(footer->magic, FS_VERITY_MAGIC, sizeof(footer->magic));
-
-    return raii.release();
-}
-
 const JNINativeMethod sMethods[] = {
-    { "enableFsverityNative", "(Ljava/lang/String;)I", (void *)enableFsverity },
+    { "enableFsverityNative", "(Ljava/lang/String;[B)I", (void *)enableFsverity },
     { "measureFsverityNative", "(Ljava/lang/String;)I", (void *)measureFsverity },
-    { "constructFsveritySignedDataNative", "([B)[B", (void *)constructFsveritySignedData },
-    { "constructFsverityDescriptorNative", "(J)[B", (void *)constructFsverityDescriptor },
-    { "constructFsverityExtensionNative", "(SI)[B", (void *)constructFsverityExtension },
-    { "constructFsverityFooterNative", "(I)[B", (void *)constructFsverityFooter },
 };
 
 }  // namespace
diff --git a/services/coverage/Android.bp b/services/coverage/Android.bp
index 16c9c1b..e4f5464 100644
--- a/services/coverage/Android.bp
+++ b/services/coverage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.coverage-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.coverage",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.coverage-sources"],
     libs: ["jacocoagent"],
 }
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index dbe0d81..2f6592b 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+    name: "services.devicepolicy-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.devicepolicy",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.devicepolicy-sources"],
 
     libs: [
         "services.core",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 127b8e0..952a64c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -206,6 +206,7 @@
 import android.provider.ContactsInternal;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.provider.Telephony;
 import android.security.IKeyChainAliasCallback;
 import android.security.IKeyChainService;
 import android.security.KeyChain;
@@ -246,6 +247,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.StatLogger;
@@ -2061,6 +2063,10 @@
              Binder.withCleanCallingIdentity(action);
         }
 
+        final <T> T binderWithCleanCallingIdentity(@NonNull ThrowingSupplier<T> action) {
+            return Binder.withCleanCallingIdentity(action);
+        }
+
         final int userHandleGetCallingUserId() {
             return UserHandle.getUserId(binderGetCallingUid());
         }
@@ -13936,23 +13942,14 @@
         Preconditions.checkNotNull(apnSetting, "ApnSetting is null in addOverrideApn");
         enforceDeviceOwner(who);
 
-        int operatedId = -1;
-        Uri resultUri;
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            resultUri = mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
+        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+        if (tm != null) {
+            return mInjector.binderWithCleanCallingIdentity(
+                    () -> tm.addDevicePolicyOverrideApn(mContext, apnSetting));
+        } else {
+            Log.w(LOG_TAG, "TelephonyManager is null when trying to add override apn");
+            return Telephony.Carriers.INVALID_APN_ID;
         }
-        if (resultUri != null) {
-            try {
-                operatedId = Integer.parseInt(resultUri.getLastPathSegment());
-            } catch (NumberFormatException e) {
-                Slog.e(LOG_TAG, "Failed to parse inserted override APN id.", e);
-            }
-        }
-
-        return operatedId;
     }
 
     @Override
@@ -13968,13 +13965,13 @@
         if (apnId < 0) {
             return false;
         }
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            return mContext.getContentResolver().update(
-                    Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
-                    apnSetting.toContentValues(), null, null) > 0;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
+        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+        if (tm != null) {
+            return mInjector.binderWithCleanCallingIdentity(
+                    () -> tm.modifyDevicePolicyOverrideApn(mContext, apnId, apnSetting));
+        } else {
+            Log.w(LOG_TAG, "TelephonyManager is null when trying to modify override apn");
+            return false;
         }
     }
 
@@ -14016,28 +14013,13 @@
     }
 
     private List<ApnSetting> getOverrideApnsUnchecked() {
-        final Cursor cursor;
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            cursor = mContext.getContentResolver().query(DPC_URI, null, null, null, null);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
+        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+        if (tm != null) {
+            return mInjector.binderWithCleanCallingIdentity(
+                    () -> tm.getDevicePolicyOverrideApns(mContext));
         }
-
-        if (cursor == null) {
-            return Collections.emptyList();
-        }
-        try {
-            List<ApnSetting> apnList = new ArrayList<ApnSetting>();
-            cursor.moveToPosition(-1);
-            while (cursor.moveToNext()) {
-                ApnSetting apn = ApnSetting.makeApnSetting(cursor);
-                apnList.add(apn);
-            }
-            return apnList;
-        } finally {
-            cursor.close();
-        }
+        Log.w(LOG_TAG, "TelephonyManager is null when trying to get override apns");
+        return Collections.emptyList();
     }
 
     @Override
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e09e88f..b5b21f4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
@@ -40,12 +41,12 @@
 import android.database.sqlite.SQLiteGlobal;
 import android.hardware.display.DisplayManagerInternal;
 import android.net.ConnectivityModuleConnector;
-import android.net.Network;
+import android.net.ITetheringConnector;
 import android.net.NetworkStackClient;
-import android.net.TetheringManager;
 import android.os.BaseBundle;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Debug;
 import android.os.Environment;
 import android.os.FactoryTest;
 import android.os.FileUtils;
@@ -446,10 +447,6 @@
             // Mmmmmm... more memory!
             VMRuntime.getRuntime().clearGrowthLimit();
 
-            // The system server has to run all of the time, so it needs to be
-            // as efficient as possible with its memory usage.
-            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
             // Some devices rely on runtime fingerprint generation, so make sure
             // we've defined it before booting further.
             Build.ensureFingerprintProperty();
@@ -501,6 +498,24 @@
             LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
             // Prepare the thread pool for init tasks that can be parallelized
             SystemServerInitThreadPool.get();
+            // Attach JVMTI agent if this is a debuggable build and the system property is set.
+            if (Build.IS_DEBUGGABLE) {
+                // Property is of the form "library_path=parameters".
+                String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
+                if (!jvmtiAgent.isEmpty()) {
+                    int equalIndex = jvmtiAgent.indexOf('=');
+                    String libraryPath = jvmtiAgent.substring(0, equalIndex);
+                    String parameterList =
+                            jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
+                    // Attach the agent.
+                    try {
+                        Debug.attachJvmtiAgent(libraryPath, parameterList, null);
+                    } catch (Exception e) {
+                        Slog.e("System", "*************************************************");
+                        Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
+                    }
+                }
+            }
         } finally {
             traceEnd();  // InitBeforeStartServices
         }
@@ -2198,8 +2213,14 @@
 
             traceBeginAndSlog("StartTethering");
             try {
-                // Tethering must start after ConnectivityService and NetworkStack.
-                TetheringManager.getInstance().start();
+                // TODO: hide implementation details, b/146312721.
+                ConnectivityModuleConnector.getInstance().startModuleService(
+                        ITetheringConnector.class.getName(),
+                        PERMISSION_MAINLINE_NETWORK_STACK, service -> {
+                            ServiceManager.addService(Context.TETHERING_SERVICE, service,
+                                    false /* allowIsolated */,
+                                    DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+                        });
             } catch (Throwable e) {
                 reportWtf("starting Tethering", e);
             }
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
index 3745e89..20e0083 100644
--- a/services/midi/Android.bp
+++ b/services/midi/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.midi-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.midi",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.midi-sources"],
     libs: ["services.core"],
 }
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 2dabdb7..9c7cfc1 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,16 +1,21 @@
+filegroup {
+    name: "services.net-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.net",
     srcs: [
         ":net-module-utils-srcs",
-        "java/**/*.java",
-        ":tethering-manager",
+        ":services.net-sources",
     ],
     static_libs: [
         "dnsresolver_aidl_interface-V2-java",
         "netd_aidl_interface-unstable-java",
         "netlink-client",
         "networkstack-client",
-        "tethering-client",
     ],
 }
 
@@ -18,9 +23,8 @@
     name: "services-tethering-shared-srcs",
     srcs: [
         ":framework-annotations",
-        "java/android/net/ConnectivityModuleConnector.java",
-        "java/android/net/NetworkStackClient.java",
         "java/android/net/util/NetdService.java",
         "java/android/net/util/NetworkConstants.java",
     ],
+    visibility: ["//frameworks/base/packages/Tethering"],
 }
diff --git a/services/net/java/android/net/NetworkMonitorManager.java b/services/net/java/android/net/NetworkMonitorManager.java
index 0f41302..0f66981 100644
--- a/services/net/java/android/net/NetworkMonitorManager.java
+++ b/services/net/java/android/net/NetworkMonitorManager.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.Hide;
 import android.annotation.NonNull;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -33,6 +34,7 @@
  * wrapper methods in this class return a boolean that callers can use to determine whether
  * RemoteException was thrown.
  */
+@Hide
 public class NetworkMonitorManager {
 
     @NonNull private final INetworkMonitor mNetworkMonitor;
diff --git a/services/net/java/android/net/ip/IpClientManager.java b/services/net/java/android/net/ip/IpClientManager.java
index 4b7ed3c..09e333e 100644
--- a/services/net/java/android/net/ip/IpClientManager.java
+++ b/services/net/java/android/net/ip/IpClientManager.java
@@ -16,6 +16,7 @@
 
 package android.net.ip;
 
+import android.annotation.Hide;
 import android.annotation.NonNull;
 import android.net.NattKeepalivePacketData;
 import android.net.ProxyInfo;
@@ -38,6 +39,7 @@
  * wrapper methods in this class return a boolean that callers can use to determine whether
  * RemoteException was thrown.
  */
+@Hide
 public class IpClientManager {
     @NonNull private final IIpClient mIpClient;
     @NonNull private final String mTag;
diff --git a/services/print/Android.bp b/services/print/Android.bp
index 80a8c75..aad24d7 100644
--- a/services/print/Android.bp
+++ b/services/print/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.print-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.print",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.print-sources"],
     libs: ["services.core"],
 }
diff --git a/services/restrictions/Android.bp b/services/restrictions/Android.bp
index 979e891..805858f 100644
--- a/services/restrictions/Android.bp
+++ b/services/restrictions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.restrictions-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.restrictions",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.restrictions-sources"],
     libs: ["services.core"],
 }
diff --git a/services/systemcaptions/Android.bp b/services/systemcaptions/Android.bp
index 4e190b6..1ce3e66 100644
--- a/services/systemcaptions/Android.bp
+++ b/services/systemcaptions/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.systemcaptions-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.systemcaptions",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.systemcaptions-sources"],
     libs: ["services.core"],
 }
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index eecdeed..d4dd245 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -39,7 +39,6 @@
         "platformprotosnano",
         "hamcrest-library",
         "servicestests-utils",
-        "xml-writer-device-lib",
     ],
 
     aidl: {
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 32aa6e1..61fe01f 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -40,6 +40,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java
index eaa9c45..d54aa3b 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/FileUtilsTest.java
@@ -27,7 +27,6 @@
 
 import org.junit.AfterClass;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -41,11 +40,6 @@
     private static File sTemporaryDir;
     private File mTemporaryFile;
 
-    @BeforeClass
-    public static void setUpClass() {
-        sTemporaryDir = Files.createTempDir();
-    }
-
     @AfterClass
     public static void tearDownClass() {
         if (sTemporaryDir != null) {
@@ -55,17 +49,21 @@
 
     @Before
     public void setUp() throws Exception {
+        if (sTemporaryDir != null) {
+            sTemporaryDir.delete();
+        }
+        sTemporaryDir = Files.createTempDir();
         mTemporaryFile = new File(sTemporaryDir, "fileutilstest.txt");
     }
 
     /** Test that if file does not exist, {@link FileUtils#createNewFile()} creates the file. */
     @Test
     public void testEnsureFileExists_fileDoesNotAlreadyExist_getsCreated() {
-        assertThat(!mTemporaryFile.exists());
+        assertThat(mTemporaryFile.exists()).isFalse();
 
         FileUtils.createNewFile(mTemporaryFile);
 
-        assertThat(mTemporaryFile.exists());
+        assertThat(mTemporaryFile.exists()).isTrue();
     }
 
     /** Test that if file does exist, {@link FileUtils#createNewFile()} does not error out. */
@@ -75,6 +73,6 @@
 
         FileUtils.createNewFile(mTemporaryFile);
 
-        assertThat(mTemporaryFile.exists());
+        assertThat(mTemporaryFile.exists()).isTrue();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/OWNERS b/services/tests/servicestests/src/com/android/server/biometrics/OWNERS
new file mode 100644
index 0000000..8765c9a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+kchyn@google.com
+jaggies@google.com
+curtislb@google.com
+ilyamaty@google.com
+joshmccloskey@google.com
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 7267976..cb99c11 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -22,15 +22,13 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.compat.annotation.Change;
-import com.android.compat.annotation.XmlWriter;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.UUID;
 
 @RunWith(AndroidJUnit4.class)
@@ -50,18 +48,10 @@
         return dir;
     }
 
-    private void writeChangesToFile(Change[] changes, File f) {
-        XmlWriter writer = new XmlWriter();
-        for (Change change: changes) {
-            writer.addChange(change);
-        }
-        try {
-            f.createNewFile();
-            writer.write(new FileOutputStream(f));
-        } catch (IOException e) {
-            throw new RuntimeException(
-                    "Encountered an error while writing compat config file", e);
-        }
+    private void writeToFile(File dir, String filename, String content) throws IOException {
+        OutputStream os = new FileOutputStream(new File(dir, filename));
+        os.write(content.getBytes());
+        os.close();
     }
 
     @Test
@@ -173,13 +163,15 @@
     }
 
     @Test
-    public void testReadConfig() {
-        Change[] changes = {new Change(1234L, "MY_CHANGE1", false, 2, null), new Change(1235L,
-                "MY_CHANGE2", true, null, "description"), new Change(1236L, "MY_CHANGE3", false,
-                null, "")};
+    public void testReadConfig() throws IOException {
+        String configXml = "<config>"
+                + "<compat-change id=\"1234\" name=\"MY_CHANGE1\" enableAfterTargetSdk=\"2\" />"
+                + "<compat-change id=\"1235\" name=\"MY_CHANGE2\" disabled=\"true\" />"
+                + "<compat-change id=\"1236\" name=\"MY_CHANGE3\" />"
+                + "</config>";
 
         File dir = createTempDir();
-        writeChangesToFile(changes, new File(dir.getPath() + "/platform_compat_config.xml"));
+        writeToFile(dir, "platform_compat_config.xml", configXml);
 
         CompatConfig pc = new CompatConfig();
         pc.initConfigFromLib(dir);
@@ -191,17 +183,18 @@
     }
 
     @Test
-    public void testReadConfigMultipleFiles() {
-        Change[] changes1 = {new Change(1234L, "MY_CHANGE1", false, 2, null)};
-        Change[] changes2 = {new Change(1235L, "MY_CHANGE2", true, null, ""), new Change(1236L,
-                "MY_CHANGE3", false, null, null)};
+    public void testReadConfigMultipleFiles() throws IOException {
+        String configXml1 = "<config>"
+                + "<compat-change id=\"1234\" name=\"MY_CHANGE1\" enableAfterTargetSdk=\"2\" />"
+                + "</config>";
+        String configXml2 = "<config>"
+                + "<compat-change id=\"1235\" name=\"MY_CHANGE2\" disabled=\"true\" />"
+                + "<compat-change id=\"1236\" name=\"MY_CHANGE3\" />"
+                + "</config>";
 
         File dir = createTempDir();
-        writeChangesToFile(changes1,
-                new File(dir.getPath() + "/libcore_platform_compat_config.xml"));
-        writeChangesToFile(changes2,
-                new File(dir.getPath() + "/frameworks_platform_compat_config.xml"));
-
+        writeToFile(dir, "libcore_platform_compat_config.xml", configXml1);
+        writeToFile(dir, "frameworks_platform_compat_config.xml", configXml2);
 
         CompatConfig pc = new CompatConfig();
         pc.initConfigFromLib(dir);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 1a67576..960f670 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -217,6 +217,8 @@
                 return mMockSystemServices.wifiManager;
             case Context.ACCOUNT_SERVICE:
                 return mMockSystemServices.accountManager;
+            case Context.TELEPHONY_SERVICE:
+                return mMockSystemServices.telephonyManager;
         }
         throw new UnsupportedOperationException();
     }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index a89198a..1638329 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -530,6 +530,7 @@
         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
     }
 
+    @Test
     public void handleSystemAudioModeRequest_fromNonTV_tVNotSupport() {
         HdmiCecMessage message =
                 HdmiCecMessageBuilder.buildSystemAudioModeRequest(
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index a1f423e..ab9b39c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -477,6 +477,7 @@
         assertEquals(2, PersistentData.TYPE_SP_WEAVER);
     }
 
+    @Test
     public void testCredentialHash_serializeUnserialize() {
         byte[] serialized = CredentialHash.create(
                 PAYLOAD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD).toBytes();
@@ -488,6 +489,7 @@
         assertFalse(deserialized.isBaseZeroPattern);
     }
 
+    @Test
     public void testCredentialHash_unserialize_versionGatekeeper() {
         // This test ensures that we can read serialized VERSION_GATEKEEPER CredentialHashes
         // even if we change the wire format in the future.
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 49c22a3..7e08d95 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -137,7 +137,6 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
 import com.android.server.DeviceIdleController;
@@ -1408,7 +1407,7 @@
         // smoke test to make sure no errors are raised
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
         assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
                 true);
@@ -1423,7 +1422,7 @@
         bundle.putLong(CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG, -100);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
 
         assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
@@ -1442,7 +1441,7 @@
                 DATA_CYCLE_USE_PLATFORM_DEFAULT);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
 
         assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
@@ -1464,7 +1463,7 @@
                 DATA_CYCLE_THRESHOLD_DISABLED);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
 
         // The policy still shouldn't change, because we don't want to overwrite user settings.
@@ -1481,7 +1480,7 @@
         bundle.putLong(CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG, 9999);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
 
         assertNetworkPolicyEquals(31, 9999, 9999, true);
@@ -1498,7 +1497,7 @@
                 DATA_CYCLE_THRESHOLD_DISABLED);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
 
         assertNetworkPolicyEquals(31, WARNING_DISABLED, LIMIT_DISABLED, true);
@@ -1515,7 +1514,7 @@
                 DATA_CYCLE_THRESHOLD_DISABLED);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
         assertNetworkPolicyEquals(31, WARNING_DISABLED, LIMIT_DISABLED, true);
 
@@ -1530,7 +1529,7 @@
                 DATA_CYCLE_USE_PLATFORM_DEFAULT);
         mServiceContext.sendBroadcast(
                 new Intent(ACTION_CARRIER_CONFIG_CHANGED)
-                        .putExtra(PhoneConstants.SUBSCRIPTION_KEY, FAKE_SUB_ID)
+                        .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, FAKE_SUB_ID)
         );
 
         assertNetworkPolicyEquals(31, mDefaultWarningBytes, mDefaultLimitBytes,
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 6bb4202..143dc28 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -183,7 +183,7 @@
     public void testSubmitStagedSession_throwPackageManagerException() throws RemoteException {
         doAnswer(invocation -> {
             throw new Exception();
-        }).when(mApexService).submitStagedSession(anyInt(), any(), any());
+        }).when(mApexService).submitStagedSession(any(), any());
 
         assertThrows(PackageManagerException.class,
                 () -> mApexManager.submitStagedSession(TEST_SESSION_ID, TEST_CHILD_SESSION_ID));
@@ -191,8 +191,7 @@
 
     @Test
     public void testSubmitStagedSession_throwRunTimeException() throws RemoteException {
-        doThrow(RemoteException.class).when(mApexService).submitStagedSession(anyInt(), any(),
-                any());
+        doThrow(RemoteException.class).when(mApexService).submitStagedSession(any(), any());
 
         assertThrows(RuntimeException.class,
                 () -> mApexManager.submitStagedSession(TEST_SESSION_ID, TEST_CHILD_SESSION_ID));
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java
new file mode 100644
index 0000000..b6eea46
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ArrayMapWithHistoryTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.util.ArrayMap;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ArrayMapWithHistory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.StringWriter;
+import java.util.concurrent.Callable;
+
+@RunWith(AndroidJUnit4.class)
+public class ArrayMapWithHistoryTest {
+
+    @Test
+    public void testValueHistoryBehavior() {
+        // Create a map that will retain 2 values per key.
+        ArrayMapWithHistory<String, String> historyMap = new ArrayMapWithHistory<>(2 /* history */);
+        ArrayMap<String, String> arrayMap = new ArrayMap<>();
+
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", null));
+
+        assertEquals(0, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertToStringAndDumpNotNull(historyMap);
+
+        putAndCompareReturnValue(historyMap, arrayMap, "K1", "V1");
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V1"));
+        compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+
+        assertEquals(1, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertToStringAndDumpNotNull(historyMap);
+
+        // put() a new value for the same key.
+        putAndCompareReturnValue(historyMap, arrayMap, "K1", "V2");
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V2"));
+        compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+
+        assertEquals(2, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertToStringAndDumpNotNull(historyMap);
+
+        // put() a new value for the same key. We should have hit the limit of "2 values retained
+        // per key".
+        putAndCompareReturnValue(historyMap, arrayMap, "K1", "V3");
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V3"));
+        compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+
+        assertEquals(2, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertToStringAndDumpNotNull(historyMap);
+    }
+
+    @Test
+    public void testMapBehavior() throws Exception {
+        ArrayMapWithHistory<String, String> historyMap = new ArrayMapWithHistory<>(2);
+        ArrayMap<String, String> arrayMap = new ArrayMap<>();
+
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", null), entry("K2", null));
+        assertIndexAccessThrowsException(0, historyMap, arrayMap);
+
+        assertEquals(0, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertEquals(0, historyMap.getHistoryCountForKeyForTests("K2"));
+
+        putAndCompareReturnValue(historyMap, arrayMap, "K1", "V1");
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V1"), entry("K2", null));
+        compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+        // TODO Restore after http://b/146563025 is fixed and ArrayMap behaves properly in tests.
+        // assertIndexAccessThrowsException(1, historyMap, arrayMap);
+
+        assertEquals(1, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertToStringAndDumpNotNull(historyMap);
+
+        putAndCompareReturnValue(historyMap, arrayMap, "K2", "V2");
+        compareGetAndSizeForKeys(historyMap, arrayMap, entry("K1", "V1"), entry("K2", "V2"));
+        compareKeyAtAndValueAtForIndex(0, historyMap, arrayMap);
+        compareKeyAtAndValueAtForIndex(1, historyMap, arrayMap);
+        // TODO Restore after http://b/146563025 is fixed and ArrayMap behaves properly in tests.
+        // assertIndexAccessThrowsException(2, historyMap, arrayMap);
+
+        assertEquals(1, historyMap.getHistoryCountForKeyForTests("K1"));
+        assertEquals(1, historyMap.getHistoryCountForKeyForTests("K2"));
+        assertToStringAndDumpNotNull(historyMap);
+    }
+
+    private static String dumpHistoryMap(ArrayMapWithHistory<?, ?> historyMap) {
+        StringWriter stringWriter = new StringWriter();
+        try (IndentingPrintWriter ipw = new IndentingPrintWriter(stringWriter, " ")) {
+            historyMap.dump(ipw);
+            return stringWriter.toString();
+        }
+    }
+
+    private static <K, V> void putAndCompareReturnValue(ArrayMapWithHistory<K, V> historyMap,
+            ArrayMap<K, V> arrayMap, K key, V value) {
+        assertEquals(arrayMap.put(key, value), historyMap.put(key, value));
+    }
+
+    private static class Entry<K, V> {
+        public final K key;
+        public final V value;
+
+        Entry(K key, V value) {
+            this.key = key;
+            this.value = value;
+        }
+    }
+
+    private static <K, V> Entry<K, V> entry(K key, V value) {
+        return new Entry<>(key, value);
+    }
+
+    @SafeVarargs
+    private static <K, V> void compareGetAndSizeForKeys(ArrayMapWithHistory<K, V> historyMap,
+            ArrayMap<K, V> arrayMap, Entry<K, V>... expectedEntries) {
+        for (Entry<K, V> expectedEntry : expectedEntries) {
+            assertEquals(arrayMap.get(expectedEntry.key), historyMap.get(expectedEntry.key));
+            assertEquals(expectedEntry.value, historyMap.get(expectedEntry.key));
+        }
+        assertEquals(arrayMap.size(), historyMap.size());
+    }
+
+    private static void compareKeyAtAndValueAtForIndex(
+            int index, ArrayMapWithHistory<?, ?> historyMap, ArrayMap<?, ?> arrayMap) {
+        assertEquals(arrayMap.keyAt(index), historyMap.keyAt(index));
+        assertEquals(arrayMap.valueAt(index), historyMap.valueAt(index));
+    }
+
+    private static void assertIndexAccessThrowsException(
+            int index, ArrayMapWithHistory<?, ?> historyMap, ArrayMap<?, ?> arrayMap)
+            throws Exception {
+        assertThrowsArrayIndexOutOfBoundsException(
+                "ArrayMap.keyAt(" + index + ")", () -> arrayMap.keyAt(index));
+        assertThrowsArrayIndexOutOfBoundsException(
+                "ArrayMapWithHistory.keyAt(" + index + ")", () -> historyMap.keyAt(index));
+        assertThrowsArrayIndexOutOfBoundsException(
+                "ArrayMap.keyAt(" + index + ")", () -> arrayMap.valueAt(index));
+        assertThrowsArrayIndexOutOfBoundsException(
+                "ArrayMapWithHistory.keyAt(" + index + ")", () -> historyMap.valueAt(index));
+    }
+
+    private static void assertThrowsArrayIndexOutOfBoundsException(
+            String description, Callable<?> callable) throws Exception {
+        try {
+            callable.call();
+            fail("Expected exception for " + description);
+        } catch (ArrayIndexOutOfBoundsException expected) {
+            // This is fine.
+        } catch (Exception e) {
+            // Any other exception is just rethrown.
+            throw e;
+        }
+    }
+
+    private static void assertToStringAndDumpNotNull(ArrayMapWithHistory<?, ?> historyMap) {
+        assertNotNull(historyMap.toString());
+        assertNotNull(dumpHistoryMap(historyMap));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
new file mode 100644
index 0000000..ce72499
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ReferenceWithHistory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.StringWriter;
+
+@RunWith(AndroidJUnit4.class)
+public class ReferenceWithHistoryTest {
+
+    @Test
+    public void testBasicReferenceBehavior() {
+        // Create a reference that will retain 2 history values.
+        ReferenceWithHistory<String> referenceWithHistory =
+                new ReferenceWithHistory<>(2 /* history */);
+        TestRef<String> reference = new TestRef<>();
+
+        // Check unset behavior.
+        compareGet(referenceWithHistory, reference, null);
+        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        compareToString(referenceWithHistory, reference, "null");
+
+        // Try setting null.
+        setAndCompareReturnValue(referenceWithHistory, reference, null);
+        compareGet(referenceWithHistory, reference, null);
+        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        compareToString(referenceWithHistory, reference, "null");
+
+        // Try setting a non-null value.
+        setAndCompareReturnValue(referenceWithHistory, reference, "Foo");
+        compareGet(referenceWithHistory, reference, "Foo");
+        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        compareToString(referenceWithHistory, reference, "Foo");
+
+        // Try setting null again.
+        setAndCompareReturnValue(referenceWithHistory, reference, "Foo");
+        compareGet(referenceWithHistory, reference, "Foo");
+        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        compareToString(referenceWithHistory, reference, "Foo");
+
+        // Try a non-null value again.
+        setAndCompareReturnValue(referenceWithHistory, reference, "Bar");
+        compareGet(referenceWithHistory, reference, "Bar");
+        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        compareToString(referenceWithHistory, reference, "Bar");
+    }
+
+    @Test
+    public void testValueHistoryBehavior() {
+        // Create a reference that will retain 2 history values.
+        ReferenceWithHistory<String> referenceWithHistory =
+                new ReferenceWithHistory<>(2 /* history */);
+        TestRef<String> reference = new TestRef<>();
+
+        // Assert behavior before anything is set.
+        assertEquals(0, referenceWithHistory.getHistoryCount());
+
+        // Set a value (1).
+        setAndCompareReturnValue(referenceWithHistory, reference, "V1");
+        assertEquals(1, referenceWithHistory.getHistoryCount());
+
+        // Set a value (2).
+        setAndCompareReturnValue(referenceWithHistory, reference, "V2");
+        assertEquals(2, referenceWithHistory.getHistoryCount());
+
+        // Set a value (3).
+        // We should have hit the limit of "2 history values retained per key".
+        setAndCompareReturnValue(referenceWithHistory, reference, "V3");
+        assertEquals(2, referenceWithHistory.getHistoryCount());
+    }
+
+    /**
+     * A simple class that has the same behavior as ReferenceWithHistory without the history. Used
+     * in tests for comparison.
+     */
+    private static class TestRef<V> {
+        private V mValue;
+
+        public V get() {
+            return mValue;
+        }
+
+        public V set(V value) {
+            V previous = mValue;
+            mValue = value;
+            return previous;
+        }
+
+        public String toString() {
+            return String.valueOf(mValue);
+        }
+    }
+
+    private static void compareGet(
+            ReferenceWithHistory<?> referenceWithHistory, TestRef<?> reference, Object value) {
+        assertEquals(reference.get(), referenceWithHistory.get());
+        assertEquals(value, reference.get());
+    }
+
+    private static <T> void setAndCompareReturnValue(
+            ReferenceWithHistory<T> referenceWithHistory, TestRef<T> reference, T newValue) {
+        assertEquals(reference.set(newValue), referenceWithHistory.set(newValue));
+    }
+
+    private static void compareToString(
+            ReferenceWithHistory<?> referenceWithHistory, TestRef<?> reference, String expected) {
+        assertEquals(reference.toString(), referenceWithHistory.toString());
+        assertEquals(expected, referenceWithHistory.toString());
+    }
+
+    private static String dumpReferenceWithHistory(ReferenceWithHistory<?> referenceWithHistory) {
+        StringWriter stringWriter = new StringWriter();
+        try (IndentingPrintWriter ipw = new IndentingPrintWriter(stringWriter, " ")) {
+            referenceWithHistory.dump(ipw);
+            return stringWriter.toString();
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeDetectorStrategyTest.java
deleted file mode 100644
index 8a7edf7..0000000
--- a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeDetectorStrategyTest.java
+++ /dev/null
@@ -1,661 +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.timedetector;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.app.timedetector.ManualTimeSuggestion;
-import android.app.timedetector.PhoneTimeSuggestion;
-import android.content.Intent;
-import android.icu.util.Calendar;
-import android.icu.util.GregorianCalendar;
-import android.icu.util.TimeZone;
-import android.util.TimestampedValue;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.time.Duration;
-
-@RunWith(AndroidJUnit4.class)
-public class SimpleTimeDetectorStrategyTest {
-
-    private static final Scenario SCENARIO_1 = new Scenario.Builder()
-            .setInitialDeviceSystemClockUtc(1977, 1, 1, 12, 0, 0)
-            .setInitialDeviceRealtimeMillis(123456789L)
-            .setActualTimeUtc(2018, 1, 1, 12, 0, 0)
-            .build();
-
-    private static final int ARBITRARY_PHONE_ID = 123456;
-
-    private static final long ONE_DAY_MILLIS = Duration.ofDays(1).toMillis();
-
-    private Script mScript;
-
-    @Before
-    public void setUp() {
-        mScript = new Script();
-    }
-
-    @Test
-    public void testSuggestPhoneTime_autoTimeEnabled() {
-        Scenario scenario = SCENARIO_1;
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(true);
-
-        PhoneTimeSuggestion timeSuggestion =
-                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
-        final int clockIncrement = 1000;
-        long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
-
-        mScript.simulateTimePassing(clockIncrement)
-                .simulatePhoneTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectSystemClockMillis, true /* expectNetworkBroadcast */);
-    }
-
-    @Test
-    public void testSuggestPhoneTime_emptySuggestionIgnored() {
-        Scenario scenario = SCENARIO_1;
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(true);
-
-        PhoneTimeSuggestion timeSuggestion = createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, null);
-
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
-    @Test
-    public void testSuggestPhoneTime_systemClockThreshold() {
-        Scenario scenario = SCENARIO_1;
-        final int systemClockUpdateThresholdMillis = 1000;
-        mScript.pokeFakeClocks(scenario)
-                .pokeThresholds(systemClockUpdateThresholdMillis)
-                .pokeTimeDetectionEnabled(true);
-
-        PhoneTimeSuggestion timeSuggestion1 =
-                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
-        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
-
-        final int clockIncrement = 100;
-        // Increment the the device clocks to simulate the passage of time.
-        mScript.simulateTimePassing(clockIncrement);
-
-        long expectSystemClockMillis1 =
-                TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
-
-        // Send the first time signal. It should be used.
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectSystemClockMillis1, true /* expectNetworkBroadcast */);
-
-        // Now send another time signal, but one that is too similar to the last one and should be
-        // ignored.
-        int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
-        TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
-                mScript.peekElapsedRealtimeMillis(),
-                mScript.peekSystemClockMillis() + underThresholdMillis);
-        PhoneTimeSuggestion timeSuggestion2 =
-                createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
-        mScript.simulateTimePassing(clockIncrement)
-                .simulatePhoneTimeSuggestion(timeSuggestion2)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Now send another time signal, but one that is on the threshold and so should be used.
-        TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
-                mScript.peekElapsedRealtimeMillis(),
-                mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
-
-        PhoneTimeSuggestion timeSuggestion3 =
-                createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
-        mScript.simulateTimePassing(clockIncrement);
-
-        long expectSystemClockMillis3 =
-                TimeDetectorStrategy.getTimeAt(utcTime3, mScript.peekElapsedRealtimeMillis());
-
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectSystemClockMillis3, true /* expectNetworkBroadcast */);
-    }
-
-    @Test
-    public void testSuggestPhoneTime_autoTimeDisabled() {
-        Scenario scenario = SCENARIO_1;
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(false);
-
-        PhoneTimeSuggestion timeSuggestion =
-                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
-    @Test
-    public void testSuggestPhoneTime_invalidNitzReferenceTimesIgnored() {
-        Scenario scenario = SCENARIO_1;
-        final int systemClockUpdateThreshold = 2000;
-        mScript.pokeFakeClocks(scenario)
-                .pokeThresholds(systemClockUpdateThreshold)
-                .pokeTimeDetectionEnabled(true);
-        PhoneTimeSuggestion timeSuggestion1 =
-                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
-        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
-
-        // Initialize the strategy / device with a time set from NITZ.
-        mScript.simulateTimePassing(100);
-        long expectedSystemClockMillis1 =
-                TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectedSystemClockMillis1, true /* expectNetworkBroadcast */);
-
-        // The UTC time increment should be larger than the system clock update threshold so we
-        // know it shouldn't be ignored for other reasons.
-        long validUtcTimeMillis = utcTime1.getValue() + (2 * systemClockUpdateThreshold);
-
-        // Now supply a new signal that has an obviously bogus reference time : older than the last
-        // one.
-        long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
-        TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
-                referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
-        PhoneTimeSuggestion timeSuggestion2 =
-                createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Now supply a new signal that has an obviously bogus reference time : substantially in the
-        // future.
-        long referenceTimeInFutureMillis =
-                utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
-        TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
-                referenceTimeInFutureMillis, validUtcTimeMillis);
-        PhoneTimeSuggestion timeSuggestion3 =
-                createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Just to prove validUtcTimeMillis is valid.
-        long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
-        TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
-                validReferenceTimeMillis, validUtcTimeMillis);
-        long expectedSystemClockMillis4 =
-                TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
-        PhoneTimeSuggestion timeSuggestion4 =
-                createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime4);
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectedSystemClockMillis4, true /* expectNetworkBroadcast */);
-    }
-
-    @Test
-    public void testSuggestPhoneTime_timeDetectionToggled() {
-        Scenario scenario = SCENARIO_1;
-        final int clockIncrementMillis = 100;
-        final int systemClockUpdateThreshold = 2000;
-        mScript.pokeFakeClocks(scenario)
-                .pokeThresholds(systemClockUpdateThreshold)
-                .pokeTimeDetectionEnabled(false);
-
-        PhoneTimeSuggestion timeSuggestion1 =
-                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
-        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
-
-        // Simulate time passing.
-        mScript.simulateTimePassing(clockIncrementMillis);
-
-        // Simulate the time signal being received. It should not be used because auto time
-        // detection is off but it should be recorded.
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Simulate more time passing.
-        mScript.simulateTimePassing(clockIncrementMillis);
-
-        long expectedSystemClockMillis1 =
-                TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
-
-        // Turn on auto time detection.
-        mScript.simulateAutoTimeDetectionToggle()
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectedSystemClockMillis1, true /* expectNetworkBroadcast */);
-
-        // Turn off auto time detection.
-        mScript.simulateAutoTimeDetectionToggle()
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Receive another valid time signal.
-        // It should be on the threshold and accounting for the clock increments.
-        TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
-                mScript.peekElapsedRealtimeMillis(),
-                mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
-        PhoneTimeSuggestion timeSuggestion2 =
-                createPhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
-
-        // Simulate more time passing.
-        mScript.simulateTimePassing(clockIncrementMillis);
-
-        long expectedSystemClockMillis2 =
-                TimeDetectorStrategy.getTimeAt(utcTime2, mScript.peekElapsedRealtimeMillis());
-
-        // The new time, though valid, should not be set in the system clock because auto time is
-        // disabled.
-        mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Turn on auto time detection.
-        mScript.simulateAutoTimeDetectionToggle()
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectedSystemClockMillis2, true /* expectNetworkBroadcast */);
-    }
-
-    @Test
-    public void testSuggestManualTime_autoTimeDisabled() {
-        Scenario scenario = SCENARIO_1;
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(false);
-
-        ManualTimeSuggestion timeSuggestion = scenario.createManualTimeSuggestionForActual();
-        final int clockIncrement = 1000;
-        long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
-
-        mScript.simulateTimePassing(clockIncrement)
-                .simulateManualTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectSystemClockMillis, false /* expectNetworkBroadcast */);
-    }
-
-    @Test
-    public void testSuggestManualTime_retainsAutoSignal() {
-        Scenario scenario = SCENARIO_1;
-
-        // Configure the start state.
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(true);
-
-        // Simulate a phone suggestion.
-        PhoneTimeSuggestion phoneTimeSuggestion =
-                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
-        long expectedAutoClockMillis = phoneTimeSuggestion.getUtcTime().getValue();
-        final int clockIncrement = 1000;
-
-        // Simulate the passage of time.
-        mScript.simulateTimePassing(clockIncrement);
-        expectedAutoClockMillis += clockIncrement;
-
-        mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectedAutoClockMillis, true /* expectNetworkBroadcast */);
-
-        // Simulate the passage of time.
-        mScript.simulateTimePassing(clockIncrement);
-        expectedAutoClockMillis += clockIncrement;
-
-        // Switch to manual.
-        mScript.simulateAutoTimeDetectionToggle()
-                .verifySystemClockWasNotSetAndResetCallTracking();
-
-        // Simulate the passage of time.
-        mScript.simulateTimePassing(clockIncrement);
-        expectedAutoClockMillis += clockIncrement;
-
-
-        // Simulate a manual suggestion 1 day different from the auto suggestion.
-        long manualTimeMillis = SCENARIO_1.getActualTimeMillis() + ONE_DAY_MILLIS;
-        long expectedManualClockMillis = manualTimeMillis;
-        ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion(manualTimeMillis);
-        mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
-                .verifySystemClockWasSetAndResetCallTracking(
-                        expectedManualClockMillis, false /* expectNetworkBroadcast */);
-
-        // Simulate the passage of time.
-        mScript.simulateTimePassing(clockIncrement);
-        expectedAutoClockMillis += clockIncrement;
-
-        // Switch back to auto.
-        mScript.simulateAutoTimeDetectionToggle();
-
-        mScript.verifySystemClockWasSetAndResetCallTracking(
-                        expectedAutoClockMillis, true /* expectNetworkBroadcast */);
-
-        // Switch back to manual - nothing should happen to the clock.
-        mScript.simulateAutoTimeDetectionToggle()
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
-    /**
-     * Manual suggestions should be ignored if auto time is enabled.
-     */
-    @Test
-    public void testSuggestManualTime_autoTimeEnabled() {
-        Scenario scenario = SCENARIO_1;
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(true);
-
-        ManualTimeSuggestion timeSuggestion = scenario.createManualTimeSuggestionForActual();
-        final int clockIncrement = 1000;
-
-        mScript.simulateTimePassing(clockIncrement)
-                .simulateManualTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
-    /**
-     * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
-     * like the real thing should, it also asserts preconditions.
-     */
-    private static class FakeCallback implements TimeDetectorStrategy.Callback {
-        private boolean mTimeDetectionEnabled;
-        private boolean mWakeLockAcquired;
-        private long mElapsedRealtimeMillis;
-        private long mSystemClockMillis;
-        private int mSystemClockUpdateThresholdMillis = 2000;
-
-        // Tracking operations.
-        private boolean mSystemClockWasSet;
-        private Intent mBroadcastSent;
-
-        @Override
-        public int systemClockUpdateThresholdMillis() {
-            return mSystemClockUpdateThresholdMillis;
-        }
-
-        @Override
-        public boolean isAutoTimeDetectionEnabled() {
-            return mTimeDetectionEnabled;
-        }
-
-        @Override
-        public void acquireWakeLock() {
-            if (mWakeLockAcquired) {
-                fail("Wake lock already acquired");
-            }
-            mWakeLockAcquired = true;
-        }
-
-        @Override
-        public long elapsedRealtimeMillis() {
-            assertWakeLockAcquired();
-            return mElapsedRealtimeMillis;
-        }
-
-        @Override
-        public long systemClockMillis() {
-            assertWakeLockAcquired();
-            return mSystemClockMillis;
-        }
-
-        @Override
-        public void setSystemClock(long newTimeMillis) {
-            assertWakeLockAcquired();
-            mSystemClockWasSet = true;
-            mSystemClockMillis = newTimeMillis;
-        }
-
-        @Override
-        public void releaseWakeLock() {
-            assertWakeLockAcquired();
-            mWakeLockAcquired = false;
-        }
-
-        @Override
-        public void sendStickyBroadcast(Intent intent) {
-            assertNotNull(intent);
-            mBroadcastSent = intent;
-        }
-
-        // Methods below are for managing the fake's behavior.
-
-        public void pokeSystemClockUpdateThreshold(int thresholdMillis) {
-            mSystemClockUpdateThresholdMillis = thresholdMillis;
-        }
-
-        public void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
-            mElapsedRealtimeMillis = elapsedRealtimeMillis;
-        }
-
-        public void pokeSystemClockMillis(long systemClockMillis) {
-            mSystemClockMillis = systemClockMillis;
-        }
-
-        public void pokeAutoTimeDetectionEnabled(boolean enabled) {
-            mTimeDetectionEnabled = enabled;
-        }
-
-        public long peekElapsedRealtimeMillis() {
-            return mElapsedRealtimeMillis;
-        }
-
-        public long peekSystemClockMillis() {
-            return mSystemClockMillis;
-        }
-
-        public void simulateTimePassing(int incrementMillis) {
-            mElapsedRealtimeMillis += incrementMillis;
-            mSystemClockMillis += incrementMillis;
-        }
-
-        public void simulateAutoTimeZoneDetectionToggle() {
-            mTimeDetectionEnabled = !mTimeDetectionEnabled;
-        }
-
-        public void verifySystemClockNotSet() {
-            assertFalse(mSystemClockWasSet);
-        }
-
-        public void verifySystemClockWasSet(long expectSystemClockMillis) {
-            assertTrue(mSystemClockWasSet);
-            assertEquals(expectSystemClockMillis, mSystemClockMillis);
-        }
-
-        public void verifyIntentWasBroadcast() {
-            assertTrue(mBroadcastSent != null);
-        }
-
-        public void verifyIntentWasNotBroadcast() {
-            assertNull(mBroadcastSent);
-        }
-
-        public void resetCallTracking() {
-            mSystemClockWasSet = false;
-            mBroadcastSent = null;
-        }
-
-        private void assertWakeLockAcquired() {
-            assertTrue("The operation must be performed only after acquiring the wakelock",
-                    mWakeLockAcquired);
-        }
-    }
-
-    /**
-     * A fluent helper class for tests.
-     */
-    private class Script {
-
-        private final FakeCallback mFakeCallback;
-        private final SimpleTimeDetectorStrategy mSimpleTimeDetectorStrategy;
-
-        Script() {
-            mFakeCallback = new FakeCallback();
-            mSimpleTimeDetectorStrategy = new SimpleTimeDetectorStrategy();
-            mSimpleTimeDetectorStrategy.initialize(mFakeCallback);
-
-        }
-
-        Script pokeTimeDetectionEnabled(boolean enabled) {
-            mFakeCallback.pokeAutoTimeDetectionEnabled(enabled);
-            return this;
-        }
-
-        Script pokeFakeClocks(Scenario scenario) {
-            mFakeCallback.pokeElapsedRealtimeMillis(scenario.getInitialRealTimeMillis());
-            mFakeCallback.pokeSystemClockMillis(scenario.getInitialSystemClockMillis());
-            return this;
-        }
-
-        Script pokeThresholds(int systemClockUpdateThreshold) {
-            mFakeCallback.pokeSystemClockUpdateThreshold(systemClockUpdateThreshold);
-            return this;
-        }
-
-        long peekElapsedRealtimeMillis() {
-            return mFakeCallback.peekElapsedRealtimeMillis();
-        }
-
-        long peekSystemClockMillis() {
-            return mFakeCallback.peekSystemClockMillis();
-        }
-
-        Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
-            mSimpleTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
-            return this;
-        }
-
-        Script simulateManualTimeSuggestion(ManualTimeSuggestion timeSuggestion) {
-            mSimpleTimeDetectorStrategy.suggestManualTime(timeSuggestion);
-            return this;
-        }
-
-        Script simulateAutoTimeDetectionToggle() {
-            mFakeCallback.simulateAutoTimeZoneDetectionToggle();
-            mSimpleTimeDetectorStrategy.handleAutoTimeDetectionChanged();
-            return this;
-        }
-
-        Script simulateTimePassing(int clockIncrement) {
-            mFakeCallback.simulateTimePassing(clockIncrement);
-            return this;
-        }
-
-        Script verifySystemClockWasNotSetAndResetCallTracking() {
-            mFakeCallback.verifySystemClockNotSet();
-            mFakeCallback.verifyIntentWasNotBroadcast();
-            mFakeCallback.resetCallTracking();
-            return this;
-        }
-
-        Script verifySystemClockWasSetAndResetCallTracking(
-                long expectSystemClockMillis, boolean expectNetworkBroadcast) {
-            mFakeCallback.verifySystemClockWasSet(expectSystemClockMillis);
-            if (expectNetworkBroadcast) {
-                mFakeCallback.verifyIntentWasBroadcast();
-            }
-            mFakeCallback.resetCallTracking();
-            return this;
-        }
-    }
-
-    /**
-     * A starting scenario used during tests. Describes a fictional "physical" reality.
-     */
-    private static class Scenario {
-
-        private final long mInitialDeviceSystemClockMillis;
-        private final long mInitialDeviceRealtimeMillis;
-        private final long mActualTimeMillis;
-
-        Scenario(long initialDeviceSystemClock, long elapsedRealtime, long timeMillis) {
-            mInitialDeviceSystemClockMillis = initialDeviceSystemClock;
-            mActualTimeMillis = timeMillis;
-            mInitialDeviceRealtimeMillis = elapsedRealtime;
-        }
-
-        long getInitialRealTimeMillis() {
-            return mInitialDeviceRealtimeMillis;
-        }
-
-        long getInitialSystemClockMillis() {
-            return mInitialDeviceSystemClockMillis;
-        }
-
-        long getActualTimeMillis() {
-            return mActualTimeMillis;
-        }
-
-        PhoneTimeSuggestion createPhoneTimeSuggestionForActual(int phoneId) {
-            TimestampedValue<Long> time = new TimestampedValue<>(
-                    mInitialDeviceRealtimeMillis, mActualTimeMillis);
-            return createPhoneTimeSuggestion(phoneId, time);
-        }
-
-        ManualTimeSuggestion createManualTimeSuggestionForActual() {
-            TimestampedValue<Long> time = new TimestampedValue<>(
-                    mInitialDeviceRealtimeMillis, mActualTimeMillis);
-            return new ManualTimeSuggestion(time);
-        }
-
-        static class Builder {
-
-            private long mInitialDeviceSystemClockMillis;
-            private long mInitialDeviceRealtimeMillis;
-            private long mActualTimeMillis;
-
-            Builder setInitialDeviceSystemClockUtc(int year, int monthInYear, int day,
-                    int hourOfDay, int minute, int second) {
-                mInitialDeviceSystemClockMillis = createUtcTime(year, monthInYear, day, hourOfDay,
-                        minute, second);
-                return this;
-            }
-
-            Builder setInitialDeviceRealtimeMillis(long realtimeMillis) {
-                mInitialDeviceRealtimeMillis = realtimeMillis;
-                return this;
-            }
-
-            Builder setActualTimeUtc(int year, int monthInYear, int day, int hourOfDay,
-                    int minute, int second) {
-                mActualTimeMillis =
-                        createUtcTime(year, monthInYear, day, hourOfDay, minute, second);
-                return this;
-            }
-
-            Scenario build() {
-                return new Scenario(mInitialDeviceSystemClockMillis, mInitialDeviceRealtimeMillis,
-                        mActualTimeMillis);
-            }
-        }
-    }
-
-    private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
-            TimestampedValue<Long> utcTime) {
-        PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
-        timeSuggestion.setUtcTime(utcTime);
-        return timeSuggestion;
-    }
-
-    private ManualTimeSuggestion createManualTimeSuggestion(long timeMillis) {
-        TimestampedValue<Long> utcTime =
-                new TimestampedValue<>(mScript.peekElapsedRealtimeMillis(), timeMillis);
-        return new ManualTimeSuggestion(utcTime);
-    }
-
-    private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute,
-            int second) {
-        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC"));
-        cal.clear();
-        cal.set(year, monthInYear - 1, day, hourOfDay, minute, second);
-        return cal.getTimeInMillis();
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 9951e85..3456cc3 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -18,10 +18,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -38,8 +40,6 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.server.timedetector.TimeDetectorStrategy.Callback;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -52,7 +52,6 @@
 
     private Context mMockContext;
     private StubbedTimeDetectorStrategy mStubbedTimeDetectorStrategy;
-    private Callback mMockCallback;
 
     private TimeDetectorService mTimeDetectorService;
     private HandlerThread mHandlerThread;
@@ -68,12 +67,10 @@
         mHandlerThread.start();
         mTestHandler = new TestHandler(mHandlerThread.getLooper());
 
-        mMockCallback = mock(Callback.class);
         mStubbedTimeDetectorStrategy = new StubbedTimeDetectorStrategy();
 
         mTimeDetectorService = new TimeDetectorService(
-                mMockContext, mTestHandler, mMockCallback,
-                mStubbedTimeDetectorStrategy);
+                mMockContext, mTestHandler, mStubbedTimeDetectorStrategy);
     }
 
     @After
@@ -82,6 +79,22 @@
         mHandlerThread.join();
     }
 
+    @Test(expected = SecurityException.class)
+    public void testSuggestPhoneTime_withoutPermission() {
+        doThrow(new SecurityException("Mock"))
+                .when(mMockContext).enforceCallingPermission(anyString(), any());
+        PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
+
+        try {
+            mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
+            fail();
+        } finally {
+            verify(mMockContext).enforceCallingPermission(
+                    eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
+                    anyString());
+        }
+    }
+
     @Test
     public void testSuggestPhoneTime() throws Exception {
         doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
@@ -91,23 +104,39 @@
         mTestHandler.assertTotalMessagesEnqueued(1);
 
         verify(mMockContext).enforceCallingPermission(
-                eq(android.Manifest.permission.SET_TIME),
+                eq(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE),
                 anyString());
 
         mTestHandler.waitForEmptyQueue();
         mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion);
     }
 
+    @Test(expected = SecurityException.class)
+    public void testSuggestManualTime_withoutPermission() {
+        doThrow(new SecurityException("Mock"))
+                .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+        ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
+
+        try {
+            mTimeDetectorService.suggestManualTime(manualTimeSuggestion);
+            fail();
+        } finally {
+            verify(mMockContext).enforceCallingOrSelfPermission(
+                    eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE),
+                    anyString());
+        }
+    }
+
     @Test
     public void testSuggestManualTime() throws Exception {
-        doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
+        doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
 
         ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
         mTimeDetectorService.suggestManualTime(manualTimeSuggestion);
         mTestHandler.assertTotalMessagesEnqueued(1);
 
-        verify(mMockContext).enforceCallingPermission(
-                eq(android.Manifest.permission.SET_TIME),
+        verify(mMockContext).enforceCallingOrSelfPermission(
+                eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE),
                 anyString());
 
         mTestHandler.waitForEmptyQueue();
@@ -140,10 +169,10 @@
 
     private static PhoneTimeSuggestion createPhoneTimeSuggestion() {
         int phoneId = 1234;
-        PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId);
         TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
-        suggestion.setUtcTime(timeValue);
-        return suggestion;
+        return new PhoneTimeSuggestion.Builder(phoneId)
+                .setUtcTime(timeValue)
+                .build();
     }
 
     private static ManualTimeSuggestion createManualTimeSuggestion() {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
new file mode 100644
index 0000000..1aa3d8f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -0,0 +1,758 @@
+/*
+ * 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.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.PhoneTimeSuggestion;
+import android.content.Intent;
+import android.icu.util.Calendar;
+import android.icu.util.GregorianCalendar;
+import android.icu.util.TimeZone;
+import android.util.TimestampedValue;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Duration;
+
+@RunWith(AndroidJUnit4.class)
+public class TimeDetectorStrategyImplTest {
+
+    private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO =
+            new TimestampedValue<>(
+                    123456789L /* realtimeClockMillis */,
+                    createUtcTime(1977, 1, 1, 12, 0, 0));
+
+    private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0);
+
+    private static final int ARBITRARY_PHONE_ID = 123456;
+
+    private static final long ONE_DAY_MILLIS = Duration.ofDays(1).toMillis();
+
+    private Script mScript;
+
+    @Before
+    public void setUp() {
+        mScript = new Script();
+    }
+
+    @Test
+    public void testSuggestPhoneTime_autoTimeEnabled() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        int phoneId = ARBITRARY_PHONE_ID;
+        long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        PhoneTimeSuggestion timeSuggestion =
+                mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+        int clockIncrement = 1000;
+        long expectedSystemClockMillis = testTimeMillis + clockIncrement;
+
+        mScript.simulateTimePassing(clockIncrement)
+                .simulatePhoneTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion);
+    }
+
+    @Test
+    public void testSuggestPhoneTime_emptySuggestionIgnored() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        int phoneId = ARBITRARY_PHONE_ID;
+        PhoneTimeSuggestion timeSuggestion =
+                mScript.generatePhoneTimeSuggestion(phoneId, null);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, null);
+    }
+
+    @Test
+    public void testSuggestPhoneTime_systemClockThreshold() {
+        int systemClockUpdateThresholdMillis = 1000;
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeThresholds(systemClockUpdateThresholdMillis)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        final int clockIncrement = 100;
+        int phoneId = ARBITRARY_PHONE_ID;
+
+        // Send the first time signal. It should be used.
+        {
+            long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+            PhoneTimeSuggestion timeSuggestion1 =
+                    mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+            TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+
+            // Increment the the device clocks to simulate the passage of time.
+            mScript.simulateTimePassing(clockIncrement);
+
+            long expectedSystemClockMillis1 =
+                    TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+
+            mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+                    .verifySystemClockWasSetAndResetCallTracking(
+                            expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+                    .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+        }
+
+        // Now send another time signal, but one that is too similar to the last one and should be
+        // stored, but not used to set the system clock.
+        {
+            int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
+            PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
+                    phoneId, mScript.peekSystemClockMillis() + underThresholdMillis);
+            mScript.simulateTimePassing(clockIncrement)
+                    .simulatePhoneTimeSuggestion(timeSuggestion2)
+                    .verifySystemClockWasNotSetAndResetCallTracking()
+                    .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+        }
+
+        // Now send another time signal, but one that is on the threshold and so should be used.
+        {
+            PhoneTimeSuggestion timeSuggestion3 = mScript.generatePhoneTimeSuggestion(
+                    phoneId,
+                    mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
+            mScript.simulateTimePassing(clockIncrement);
+
+            long expectedSystemClockMillis3 =
+                    TimeDetectorStrategy.getTimeAt(timeSuggestion3.getUtcTime(),
+                            mScript.peekElapsedRealtimeMillis());
+
+            mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
+                    .verifySystemClockWasSetAndResetCallTracking(
+                            expectedSystemClockMillis3, true /* expectNetworkBroadcast */)
+                    .assertLatestPhoneSuggestion(phoneId, timeSuggestion3);
+        }
+    }
+
+    @Test
+    public void testSuggestPhoneTime_multiplePhoneIdsAndBucketing() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        // There are 2 phones in this test. Phone 2 has a different idea of the current time.
+        // phone1Id < phone2Id (which is important because the strategy uses the lowest ID when
+        // multiple phone suggestions are available.
+        int phone1Id = ARBITRARY_PHONE_ID;
+        int phone2Id = ARBITRARY_PHONE_ID + 1;
+        long phone1TimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        long phone2TimeMillis = phone1TimeMillis + 60000;
+
+        final int clockIncrement = 999;
+
+        // Make a suggestion with phone2Id.
+        {
+            PhoneTimeSuggestion phone2TimeSuggestion =
+                    mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+            mScript.simulateTimePassing(clockIncrement);
+
+            long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+
+            mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+                    .verifySystemClockWasSetAndResetCallTracking(
+                            expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+                    .assertLatestPhoneSuggestion(phone1Id, null)
+                    .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+        }
+
+        mScript.simulateTimePassing(clockIncrement);
+
+        // Now make a different suggestion with phone1Id.
+        {
+            PhoneTimeSuggestion phone1TimeSuggestion =
+                    mScript.generatePhoneTimeSuggestion(phone1Id, phone1TimeMillis);
+            mScript.simulateTimePassing(clockIncrement);
+
+            long expectedSystemClockMillis = phone1TimeMillis + clockIncrement;
+
+            mScript.simulatePhoneTimeSuggestion(phone1TimeSuggestion)
+                    .verifySystemClockWasSetAndResetCallTracking(
+                            expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+                    .assertLatestPhoneSuggestion(phone1Id, phone1TimeSuggestion);
+
+        }
+
+        mScript.simulateTimePassing(clockIncrement);
+
+        // Make another suggestion with phone2Id. It should be stored but not used because the
+        // phone1Id suggestion will still "win".
+        {
+            PhoneTimeSuggestion phone2TimeSuggestion =
+                    mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+            mScript.simulateTimePassing(clockIncrement);
+
+            mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+                    .verifySystemClockWasNotSetAndResetCallTracking()
+                    .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+        }
+
+        // Let enough time pass that phone1Id's suggestion should now be too old.
+        mScript.simulateTimePassing(TimeDetectorStrategyImpl.PHONE_BUCKET_SIZE_MILLIS);
+
+        // Make another suggestion with phone2Id. It should be used because the phoneId1
+        // is in an older "bucket".
+        {
+            PhoneTimeSuggestion phone2TimeSuggestion =
+                    mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
+            mScript.simulateTimePassing(clockIncrement);
+
+            long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+
+            mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
+                    .verifySystemClockWasSetAndResetCallTracking(
+                            expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+                    .assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
+        }
+    }
+
+    @Test
+    public void testSuggestPhoneTime_autoTimeDisabled() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(false);
+
+        int phoneId = ARBITRARY_PHONE_ID;
+        PhoneTimeSuggestion timeSuggestion =
+                mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
+        mScript.simulateTimePassing(1000)
+                .simulatePhoneTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion);
+    }
+
+    @Test
+    public void testSuggestPhoneTime_invalidNitzReferenceTimesIgnored() {
+        final int systemClockUpdateThreshold = 2000;
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeThresholds(systemClockUpdateThreshold)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        int phoneId = ARBITRARY_PHONE_ID;
+
+        PhoneTimeSuggestion timeSuggestion1 =
+                mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+
+        // Initialize the strategy / device with a time set from a phone suggestion.
+        mScript.simulateTimePassing(100);
+        long expectedSystemClockMillis1 =
+                TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+        // The UTC time increment should be larger than the system clock update threshold so we
+        // know it shouldn't be ignored for other reasons.
+        long validUtcTimeMillis = utcTime1.getValue() + (2 * systemClockUpdateThreshold);
+
+        // Now supply a new signal that has an obviously bogus reference time : older than the last
+        // one.
+        long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
+        TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
+                referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
+        PhoneTimeSuggestion timeSuggestion2 =
+                createPhoneTimeSuggestion(phoneId, utcTime2);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+        // Now supply a new signal that has an obviously bogus reference time : substantially in the
+        // future.
+        long referenceTimeInFutureMillis =
+                utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
+        TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
+                referenceTimeInFutureMillis, validUtcTimeMillis);
+        PhoneTimeSuggestion timeSuggestion3 =
+                createPhoneTimeSuggestion(phoneId, utcTime3);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+        // Just to prove validUtcTimeMillis is valid.
+        long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
+        TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
+                validReferenceTimeMillis, validUtcTimeMillis);
+        long expectedSystemClockMillis4 =
+                TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
+        PhoneTimeSuggestion timeSuggestion4 =
+                createPhoneTimeSuggestion(phoneId, utcTime4);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedSystemClockMillis4, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion4);
+    }
+
+    @Test
+    public void testSuggestPhoneTime_timeDetectionToggled() {
+        final int clockIncrementMillis = 100;
+        final int systemClockUpdateThreshold = 2000;
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeThresholds(systemClockUpdateThreshold)
+                .pokeAutoTimeDetectionEnabled(false);
+
+        int phoneId = ARBITRARY_PHONE_ID;
+        long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        PhoneTimeSuggestion timeSuggestion1 =
+                mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+
+        // Simulate time passing.
+        mScript.simulateTimePassing(clockIncrementMillis);
+
+        // Simulate the time signal being received. It should not be used because auto time
+        // detection is off but it should be recorded.
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+        // Simulate more time passing.
+        mScript.simulateTimePassing(clockIncrementMillis);
+
+        long expectedSystemClockMillis1 =
+                TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+
+        // Turn on auto time detection.
+        mScript.simulateAutoTimeDetectionToggle()
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+        // Turn off auto time detection.
+        mScript.simulateAutoTimeDetectionToggle()
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion1);
+
+        // Receive another valid time signal.
+        // It should be on the threshold and accounting for the clock increments.
+        PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
+                phoneId, mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
+
+        // Simulate more time passing.
+        mScript.simulateTimePassing(clockIncrementMillis);
+
+        long expectedSystemClockMillis2 = TimeDetectorStrategy.getTimeAt(
+                timeSuggestion2.getUtcTime(), mScript.peekElapsedRealtimeMillis());
+
+        // The new time, though valid, should not be set in the system clock because auto time is
+        // disabled.
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+
+        // Turn on auto time detection.
+        mScript.simulateAutoTimeDetectionToggle()
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedSystemClockMillis2, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
+    }
+
+    @Test
+    public void testSuggestPhoneTime_maxSuggestionAge() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        int phoneId = ARBITRARY_PHONE_ID;
+        long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        PhoneTimeSuggestion phoneSuggestion =
+                mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+        int clockIncrementMillis = 1000;
+
+        mScript.simulateTimePassing(clockIncrementMillis)
+                .simulatePhoneTimeSuggestion(phoneSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        testTimeMillis + clockIncrementMillis, true /* expectedNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
+
+        // Look inside and check what the strategy considers the current best phone suggestion.
+        assertEquals(phoneSuggestion, mScript.peekBestPhoneSuggestion());
+
+        // Simulate time passing, long enough that phoneSuggestion is now too old.
+        mScript.simulateTimePassing(TimeDetectorStrategyImpl.PHONE_MAX_AGE_MILLIS);
+
+        // Look inside and check what the strategy considers the current best phone suggestion. It
+        // should still be the, it's just no longer used.
+        assertNull(mScript.peekBestPhoneSuggestion());
+        mScript.assertLatestPhoneSuggestion(phoneId, phoneSuggestion);
+    }
+
+    @Test
+    public void testSuggestManualTime_autoTimeDisabled() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(false);
+
+        long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        ManualTimeSuggestion timeSuggestion = mScript.generateManualTimeSuggestion(testTimeMillis);
+        final int clockIncrement = 1000;
+        long expectedSystemClockMillis = testTimeMillis + clockIncrement;
+
+        mScript.simulateTimePassing(clockIncrement)
+                .simulateManualTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedSystemClockMillis, false /* expectNetworkBroadcast */);
+    }
+
+    @Test
+    public void testSuggestManualTime_retainsAutoSignal() {
+        // Configure the start state.
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        int phoneId = ARBITRARY_PHONE_ID;
+
+        // Simulate a phone suggestion.
+        long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
+        PhoneTimeSuggestion phoneTimeSuggestion =
+                mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
+        long expectedAutoClockMillis = phoneTimeSuggestion.getUtcTime().getValue();
+        final int clockIncrement = 1000;
+
+        // Simulate the passage of time.
+        mScript.simulateTimePassing(clockIncrement);
+        expectedAutoClockMillis += clockIncrement;
+
+        mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedAutoClockMillis, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+        // Simulate the passage of time.
+        mScript.simulateTimePassing(clockIncrement);
+        expectedAutoClockMillis += clockIncrement;
+
+        // Switch to manual.
+        mScript.simulateAutoTimeDetectionToggle()
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+        // Simulate the passage of time.
+        mScript.simulateTimePassing(clockIncrement);
+        expectedAutoClockMillis += clockIncrement;
+
+        // Simulate a manual suggestion 1 day different from the auto suggestion.
+        long manualTimeMillis = testTimeMillis + ONE_DAY_MILLIS;
+        long expectedManualClockMillis = manualTimeMillis;
+        ManualTimeSuggestion manualTimeSuggestion =
+                mScript.generateManualTimeSuggestion(manualTimeMillis);
+        mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(
+                        expectedManualClockMillis, false /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+        // Simulate the passage of time.
+        mScript.simulateTimePassing(clockIncrement);
+        expectedAutoClockMillis += clockIncrement;
+
+        // Switch back to auto.
+        mScript.simulateAutoTimeDetectionToggle();
+
+        mScript.verifySystemClockWasSetAndResetCallTracking(
+                        expectedAutoClockMillis, true /* expectNetworkBroadcast */)
+                .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+
+        // Switch back to manual - nothing should happen to the clock.
+        mScript.simulateAutoTimeDetectionToggle()
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
+    }
+
+    /**
+     * Manual suggestions should be ignored if auto time is enabled.
+     */
+    @Test
+    public void testSuggestManualTime_autoTimeEnabled() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true);
+
+        ManualTimeSuggestion timeSuggestion =
+                mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+        final int clockIncrement = 1000;
+
+        mScript.simulateTimePassing(clockIncrement)
+                .simulateManualTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    /**
+     * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
+     * like the real thing should, it also asserts preconditions.
+     */
+    private static class FakeCallback implements TimeDetectorStrategy.Callback {
+        private boolean mAutoTimeDetectionEnabled;
+        private boolean mWakeLockAcquired;
+        private long mElapsedRealtimeMillis;
+        private long mSystemClockMillis;
+        private int mSystemClockUpdateThresholdMillis = 2000;
+
+        // Tracking operations.
+        private boolean mSystemClockWasSet;
+        private Intent mBroadcastSent;
+
+        @Override
+        public int systemClockUpdateThresholdMillis() {
+            return mSystemClockUpdateThresholdMillis;
+        }
+
+        @Override
+        public boolean isAutoTimeDetectionEnabled() {
+            return mAutoTimeDetectionEnabled;
+        }
+
+        @Override
+        public void acquireWakeLock() {
+            if (mWakeLockAcquired) {
+                fail("Wake lock already acquired");
+            }
+            mWakeLockAcquired = true;
+        }
+
+        @Override
+        public long elapsedRealtimeMillis() {
+            return mElapsedRealtimeMillis;
+        }
+
+        @Override
+        public long systemClockMillis() {
+            assertWakeLockAcquired();
+            return mSystemClockMillis;
+        }
+
+        @Override
+        public void setSystemClock(long newTimeMillis) {
+            assertWakeLockAcquired();
+            mSystemClockWasSet = true;
+            mSystemClockMillis = newTimeMillis;
+        }
+
+        @Override
+        public void releaseWakeLock() {
+            assertWakeLockAcquired();
+            mWakeLockAcquired = false;
+        }
+
+        @Override
+        public void sendStickyBroadcast(Intent intent) {
+            assertNotNull(intent);
+            mBroadcastSent = intent;
+        }
+
+        // Methods below are for managing the fake's behavior.
+
+        void pokeSystemClockUpdateThreshold(int thresholdMillis) {
+            mSystemClockUpdateThresholdMillis = thresholdMillis;
+        }
+
+        void pokeElapsedRealtimeMillis(long elapsedRealtimeMillis) {
+            mElapsedRealtimeMillis = elapsedRealtimeMillis;
+        }
+
+        void pokeSystemClockMillis(long systemClockMillis) {
+            mSystemClockMillis = systemClockMillis;
+        }
+
+        void pokeAutoTimeDetectionEnabled(boolean enabled) {
+            mAutoTimeDetectionEnabled = enabled;
+        }
+
+        long peekElapsedRealtimeMillis() {
+            return mElapsedRealtimeMillis;
+        }
+
+        long peekSystemClockMillis() {
+            return mSystemClockMillis;
+        }
+
+        void simulateTimePassing(long incrementMillis) {
+            mElapsedRealtimeMillis += incrementMillis;
+            mSystemClockMillis += incrementMillis;
+        }
+
+        void simulateAutoTimeZoneDetectionToggle() {
+            mAutoTimeDetectionEnabled = !mAutoTimeDetectionEnabled;
+        }
+
+        void verifySystemClockNotSet() {
+            assertFalse(mSystemClockWasSet);
+        }
+
+        void verifySystemClockWasSet(long expectedSystemClockMillis) {
+            assertTrue(mSystemClockWasSet);
+            assertEquals(expectedSystemClockMillis, mSystemClockMillis);
+        }
+
+        void verifyIntentWasBroadcast() {
+            assertTrue(mBroadcastSent != null);
+        }
+
+        void verifyIntentWasNotBroadcast() {
+            assertNull(mBroadcastSent);
+        }
+
+        void resetCallTracking() {
+            mSystemClockWasSet = false;
+            mBroadcastSent = null;
+        }
+
+        private void assertWakeLockAcquired() {
+            assertTrue("The operation must be performed only after acquiring the wakelock",
+                    mWakeLockAcquired);
+        }
+    }
+
+    /**
+     * A fluent helper class for tests.
+     */
+    private class Script {
+
+        private final FakeCallback mFakeCallback;
+        private final TimeDetectorStrategyImpl mTimeDetectorStrategy;
+
+        Script() {
+            mFakeCallback = new FakeCallback();
+            mTimeDetectorStrategy = new TimeDetectorStrategyImpl();
+            mTimeDetectorStrategy.initialize(mFakeCallback);
+
+        }
+
+        Script pokeAutoTimeDetectionEnabled(boolean enabled) {
+            mFakeCallback.pokeAutoTimeDetectionEnabled(enabled);
+            return this;
+        }
+
+        Script pokeFakeClocks(TimestampedValue<Long> timeInfo) {
+            mFakeCallback.pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
+            mFakeCallback.pokeSystemClockMillis(timeInfo.getValue());
+            return this;
+        }
+
+        Script pokeThresholds(int systemClockUpdateThreshold) {
+            mFakeCallback.pokeSystemClockUpdateThreshold(systemClockUpdateThreshold);
+            return this;
+        }
+
+        long peekElapsedRealtimeMillis() {
+            return mFakeCallback.peekElapsedRealtimeMillis();
+        }
+
+        long peekSystemClockMillis() {
+            return mFakeCallback.peekSystemClockMillis();
+        }
+
+        Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
+            mTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
+            return this;
+        }
+
+        Script simulateManualTimeSuggestion(ManualTimeSuggestion timeSuggestion) {
+            mTimeDetectorStrategy.suggestManualTime(timeSuggestion);
+            return this;
+        }
+
+        Script simulateAutoTimeDetectionToggle() {
+            mFakeCallback.simulateAutoTimeZoneDetectionToggle();
+            mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
+            return this;
+        }
+
+        Script simulateTimePassing(long clockIncrementMillis) {
+            mFakeCallback.simulateTimePassing(clockIncrementMillis);
+            return this;
+        }
+
+        Script verifySystemClockWasNotSetAndResetCallTracking() {
+            mFakeCallback.verifySystemClockNotSet();
+            mFakeCallback.verifyIntentWasNotBroadcast();
+            mFakeCallback.resetCallTracking();
+            return this;
+        }
+
+        Script verifySystemClockWasSetAndResetCallTracking(
+                long expectedSystemClockMillis, boolean expectNetworkBroadcast) {
+            mFakeCallback.verifySystemClockWasSet(expectedSystemClockMillis);
+            if (expectNetworkBroadcast) {
+                mFakeCallback.verifyIntentWasBroadcast();
+            }
+            mFakeCallback.resetCallTracking();
+            return this;
+        }
+
+        /**
+         * White box test info: Asserts the latest suggestion for the phone ID is as expected.
+         */
+        Script assertLatestPhoneSuggestion(int phoneId, PhoneTimeSuggestion expected) {
+            assertEquals(expected, mTimeDetectorStrategy.getLatestPhoneSuggestion(phoneId));
+            return this;
+        }
+
+        /**
+         * White box test info: Returns the phone suggestion that would be used, if any, given the
+         * current elapsed real time clock.
+         */
+        PhoneTimeSuggestion peekBestPhoneSuggestion() {
+            return mTimeDetectorStrategy.findBestPhoneSuggestionForTests();
+        }
+
+        /**
+         * Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
+         * reference time.
+         */
+        ManualTimeSuggestion generateManualTimeSuggestion(long timeMillis) {
+            TimestampedValue<Long> utcTime =
+                    new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis);
+            return new ManualTimeSuggestion(utcTime);
+        }
+
+        /**
+         * Generates a PhoneTimeSuggestion using the current elapsed realtime clock for the
+         * reference time.
+         */
+        PhoneTimeSuggestion generatePhoneTimeSuggestion(int phoneId, Long timeMillis) {
+            TimestampedValue<Long> time = null;
+            if (timeMillis != null) {
+                time = new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis);
+            }
+            return createPhoneTimeSuggestion(phoneId, time);
+        }
+    }
+
+    private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
+            TimestampedValue<Long> utcTime) {
+        return new PhoneTimeSuggestion.Builder(phoneId)
+                .setUtcTime(utcTime)
+                .build();
+    }
+
+    private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute,
+            int second) {
+        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC"));
+        cal.clear();
+        cal.set(year, monthInYear - 1, day, hourOfDay, minute, second);
+        return cal.getTimeInMillis();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java
index 270436d..2429cfc 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyTest.java
@@ -50,7 +50,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedList;
-import java.util.Objects;
 
 /**
  * White-box unit tests for {@link TimeZoneDetectorStrategy}.
@@ -445,8 +444,7 @@
     static class FakeTimeZoneDetectorStrategyCallback implements TimeZoneDetectorStrategy.Callback {
 
         private boolean mAutoTimeZoneDetectionEnabled;
-        private TestState<TimeZoneChange> mTimeZoneChanges = new TestState<>();
-        private String mTimeZoneId;
+        private TestState<String> mTimeZoneId = new TestState<>();
 
         @Override
         public boolean isAutoTimeZoneDetectionEnabled() {
@@ -455,18 +453,17 @@
 
         @Override
         public boolean isDeviceTimeZoneInitialized() {
-            return mTimeZoneId != null;
+            return mTimeZoneId.getLatest() != null;
         }
 
         @Override
         public String getDeviceTimeZone() {
-            return mTimeZoneId;
+            return mTimeZoneId.getLatest();
         }
 
         @Override
-        public void setDeviceTimeZone(String zoneId, boolean withNetworkBroadcast) {
-            mTimeZoneId = zoneId;
-            mTimeZoneChanges.set(new TimeZoneChange(zoneId, withNetworkBroadcast));
+        public void setDeviceTimeZone(String zoneId) {
+            mTimeZoneId.set(zoneId);
         }
 
         void initializeAutoTimeZoneDetection(boolean enabled) {
@@ -474,7 +471,7 @@
         }
 
         void initializeTimeZone(String zoneId) {
-            mTimeZoneId = zoneId;
+            mTimeZoneId.init(zoneId);
         }
 
         void setAutoTimeZoneDetectionEnabled(boolean enabled) {
@@ -482,46 +479,17 @@
         }
 
         void assertTimeZoneNotSet() {
-            mTimeZoneChanges.assertHasNotBeenSet();
+            mTimeZoneId.assertHasNotBeenSet();
         }
 
-        void assertTimeZoneSet(String timeZoneId, boolean withNetworkBroadcast) {
-            mTimeZoneChanges.assertHasBeenSet();
-            mTimeZoneChanges.assertChangeCount(1);
-            TimeZoneChange expectedChange = new TimeZoneChange(timeZoneId, withNetworkBroadcast);
-            mTimeZoneChanges.assertLatestEquals(expectedChange);
+        void assertTimeZoneSet(String timeZoneId) {
+            mTimeZoneId.assertHasBeenSet();
+            mTimeZoneId.assertChangeCount(1);
+            mTimeZoneId.assertLatestEquals(timeZoneId);
         }
 
         void commitAllChanges() {
-            mTimeZoneChanges.commitLatest();
-        }
-    }
-
-    private static class TimeZoneChange {
-        private final String mTimeZoneId;
-        private final boolean mWithNetworkBroadcast;
-
-        private TimeZoneChange(String timeZoneId, boolean withNetworkBroadcast) {
-            mTimeZoneId = timeZoneId;
-            mWithNetworkBroadcast = withNetworkBroadcast;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            TimeZoneChange that = (TimeZoneChange) o;
-            return mWithNetworkBroadcast == that.mWithNetworkBroadcast
-                    && mTimeZoneId.equals(that.mTimeZoneId);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mTimeZoneId, mWithNetworkBroadcast);
+            mTimeZoneId.commitLatest();
         }
     }
 
@@ -614,21 +582,13 @@
         }
 
         Script verifyTimeZoneSetAndReset(PhoneTimeZoneSuggestion suggestion) {
-            // Phone suggestions should cause a TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE
-            // broadcast.
-            boolean withNetworkBroadcast = true;
-            mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(
-                    suggestion.getZoneId(), withNetworkBroadcast);
+            mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(suggestion.getZoneId());
             mFakeTimeZoneDetectorStrategyCallback.commitAllChanges();
             return this;
         }
 
         Script verifyTimeZoneSetAndReset(ManualTimeZoneSuggestion suggestion) {
-            // Manual suggestions should not cause a TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE
-            // broadcast.
-            boolean withNetworkBroadcast = false;
-            mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(
-                    suggestion.getZoneId(), withNetworkBroadcast);
+            mFakeTimeZoneDetectorStrategyCallback.assertTimeZoneSet(suggestion.getZoneId());
             mFakeTimeZoneDetectorStrategyCallback.commitAllChanges();
             return this;
         }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index b5542af..0fce618 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4193,6 +4193,7 @@
         assertEquals(0, mService.countLogSmartSuggestionsVisible);
     }
 
+    @Test
     public void testReportSeen_delegated() {
         Notification.Builder nb =
                 new Notification.Builder(mContext, mTestNotificationChannel.getId())
diff --git a/services/usage/Android.bp b/services/usage/Android.bp
index 1064b6e..156bf33 100644
--- a/services/usage/Android.bp
+++ b/services/usage/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.usage-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.usage",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.usage-sources"],
     libs: ["services.core"],
 }
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 75e8fb5..cb120fc 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -1356,7 +1356,8 @@
     private void fetchCarrierPrivilegedAppsLocked() {
         TelephonyManager telephonyManager =
                 mContext.getSystemService(TelephonyManager.class);
-        mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivilegesForAllPhones();
+        mCarrierPrivilegedApps =
+                telephonyManager.getCarrierPrivilegedPackagesForAllActiveSubscriptions();
         mHaveCarrierPrivilegedApps = true;
         if (DEBUG) {
             Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 20855b7..d2c973a 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -1,6 +1,13 @@
+filegroup {
+    name: "services.usb-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.usb",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.usb-sources"],
 
     libs: [
         "services.core",
diff --git a/services/voiceinteraction/Android.bp b/services/voiceinteraction/Android.bp
index 390406f..85b96f34 100644
--- a/services/voiceinteraction/Android.bp
+++ b/services/voiceinteraction/Android.bp
@@ -1,5 +1,12 @@
+filegroup {
+    name: "services.voiceinteraction-sources",
+    srcs: ["java/**/*.java"],
+    path: "java",
+    visibility: ["//frameworks/base/services"],
+}
+
 java_library_static {
     name: "services.voiceinteraction",
-    srcs: ["java/**/*.java"],
+    srcs: [":services.voiceinteraction-sources"],
     libs: ["services.core"],
 }
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
index 59a80fb..993d1e1 100644
--- a/startop/iorap/Android.bp
+++ b/startop/iorap/Android.bp
@@ -12,19 +12,24 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+filegroup {
+  name: "services.startop.iorap-javasources",
+  srcs: ["src/**/*.java"],
+  path: "src",
+  visibility: ["//visibility:private"],
+}
+
+filegroup {
+  name: "services.startop.iorap-sources",
+  srcs: [
+    ":services.startop.iorap-javasources",
+    ":iorap-aidl",
+  ],
+  visibility: ["//frameworks/base/services:__subpackages__"],
+}
+
 java_library_static {
   name: "services.startop.iorap",
-
-  aidl: {
-    include_dirs: [
-      "system/iorap/binder",
-    ],
-  },
-
+  srcs: [":services.startop.iorap-sources"],
   libs: ["services.core"],
-
-  srcs: [
-      ":iorap-aidl",
-      "**/*.java",
-  ],
 }
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 58abf00..456290c 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -24,9 +24,6 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.telecom.Connection.VideoProvider;
-import android.telephony.Annotation.RilRadioTechnology;
-import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 
 import java.util.ArrayList;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index c063279..8808339 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -502,51 +502,116 @@
     //**********************************************************************************************
 
     /**
-     * Define IMS Audio Codec
+     * Indicates that the audio codec is currently not specified or is unknown.
      */
-    // Current audio codec is NONE
     public static final int AUDIO_CODEC_NONE = ImsStreamMediaProfile.AUDIO_QUALITY_NONE; // 0
-    // Current audio codec is AMR
+    /**
+     * Adaptive Multi-rate audio codec.
+     */
     public static final int AUDIO_CODEC_AMR = ImsStreamMediaProfile.AUDIO_QUALITY_AMR; // 1
-    // Current audio codec is AMR_WB
+    /**
+     * Adaptive Multi-rate wideband audio codec.
+     */
     public static final int AUDIO_CODEC_AMR_WB = ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB; // 2
-    // Current audio codec is QCELP13K
+    /**
+     * Qualcomm code-excited linear prediction 13 kilobit audio codec.
+     */
     public static final int AUDIO_CODEC_QCELP13K = ImsStreamMediaProfile.AUDIO_QUALITY_QCELP13K; //3
-    // Current audio codec is EVRC
+    /**
+     * Enhanced Variable Rate Codec.  See 3GPP2 C.S0014-A.
+     */
     public static final int AUDIO_CODEC_EVRC = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC; // 4
-    // Current audio codec is EVRC_B
+    /**
+     * Enhanced Variable Rate Codec B.  Commonly used on CDMA networks.
+     */
     public static final int AUDIO_CODEC_EVRC_B = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_B; // 5
-    // Current audio codec is EVRC_WB
+    /**
+     * Enhanced Variable Rate Wideband Codec.  See RFC5188.
+     */
     public static final int AUDIO_CODEC_EVRC_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB; // 6
-    // Current audio codec is EVRC_NW
+    /**
+     * Enhanced Variable Rate Narrowband-Wideband Codec.
+     */
     public static final int AUDIO_CODEC_EVRC_NW = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_NW; // 7
-    // Current audio codec is GSM_EFR
+    /**
+     * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or simply EFR.
+     */
     public static final int AUDIO_CODEC_GSM_EFR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_EFR; // 8
-    // Current audio codec is GSM_FR
+    /**
+     * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or simply FR.
+     */
     public static final int AUDIO_CODEC_GSM_FR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_FR; // 9
-    // Current audio codec is GSM_HR
+    /**
+     * GSM Half Rate audio codec.
+     */
     public static final int AUDIO_CODEC_GSM_HR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_HR; // 10
-    // Current audio codec is G711U
+    /**
+     * ITU-T G711U audio codec.
+     */
     public static final int AUDIO_CODEC_G711U = ImsStreamMediaProfile.AUDIO_QUALITY_G711U; // 11
-    // Current audio codec is G723
+    /**
+     * ITU-T G723 audio codec.
+     */
     public static final int AUDIO_CODEC_G723 = ImsStreamMediaProfile.AUDIO_QUALITY_G723; // 12
-    // Current audio codec is G711A
+    /**
+     * ITU-T G711A audio codec.
+     */
     public static final int AUDIO_CODEC_G711A = ImsStreamMediaProfile.AUDIO_QUALITY_G711A; // 13
-    // Current audio codec is G722
+    /**
+     * ITU-T G722 audio codec.
+     */
     public static final int AUDIO_CODEC_G722 = ImsStreamMediaProfile.AUDIO_QUALITY_G722; // 14
-    // Current audio codec is G711AB
+    /**
+     * ITU-T G711AB audio codec.
+     */
     public static final int AUDIO_CODEC_G711AB = ImsStreamMediaProfile.AUDIO_QUALITY_G711AB; // 15
-    // Current audio codec is G729
+    /**
+     * ITU-T G729 audio codec.
+     */
     public static final int AUDIO_CODEC_G729 = ImsStreamMediaProfile.AUDIO_QUALITY_G729; // 16
-    // Current audio codec is EVS_NB
+    /**
+     * Enhanced Voice Services Narrowband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_NB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_NB; // 17
-    // Current audio codec is EVS_WB
+    /**
+     * Enhanced Voice Services Wideband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB; // 18
-    // Current audio codec is EVS_SWB
+    /**
+     * Enhanced Voice Services Super-Wideband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_SWB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB; // 19
-    // Current audio codec is EVS_FB
+    /**
+     * Enhanced Voice Services Fullband audio codec.  See 3GPP TS 26.441.
+     */
     public static final int AUDIO_CODEC_EVS_FB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB; // 20
 
+    /**@hide*/
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "AUDIO_CODEC_", value = {
+            AUDIO_CODEC_NONE,
+            AUDIO_CODEC_AMR,
+            AUDIO_CODEC_AMR_WB,
+            AUDIO_CODEC_QCELP13K,
+            AUDIO_CODEC_EVRC,
+            AUDIO_CODEC_EVRC_B,
+            AUDIO_CODEC_EVRC_WB,
+            AUDIO_CODEC_EVRC_NW,
+            AUDIO_CODEC_GSM_EFR,
+            AUDIO_CODEC_GSM_FR,
+            AUDIO_CODEC_GSM_HR,
+            AUDIO_CODEC_G711U,
+            AUDIO_CODEC_G723,
+            AUDIO_CODEC_G711A,
+            AUDIO_CODEC_G722,
+            AUDIO_CODEC_G711AB,
+            AUDIO_CODEC_G729,
+            AUDIO_CODEC_EVS_NB,
+            AUDIO_CODEC_EVS_SWB,
+            AUDIO_CODEC_EVS_FB
+    })
+    public @interface AudioCodec {}
+
     /**
      * Connection extra key used to store the last forwarded number associated with the current
      * connection.  Used to communicate to the user interface that the connection was forwarded via
@@ -640,10 +705,10 @@
             "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
 
     /**
-     * The audio codec in use for the current {@link Connection}, if known. Valid values include
-     * {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}.
+     * The audio codec in use for the current {@link Connection}, if known.  Examples of valid
+     * values include {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}.
      */
-    public static final String EXTRA_AUDIO_CODEC =
+    public static final @AudioCodec String EXTRA_AUDIO_CODEC =
             "android.telecom.extra.AUDIO_CODEC";
 
     /**
@@ -695,6 +760,15 @@
     public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
 
     /**
+     * Connection event used to inform Telecom when a switch operation on a call has failed.
+     * <p>
+     * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
+     * expected to be null when this connection event is used.
+     */
+    public static final String EVENT_CALL_SWITCH_FAILED =
+            "android.telecom.event.CALL_SWITCH_FAILED";
+
+    /**
      * Connection event used to inform {@link InCallService}s when the process of merging a
      * Connection into a conference has begun.
      * <p>
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 20862c5..af3c55a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -485,6 +485,103 @@
             "android.telecom.extra.START_CALL_WITH_RTT";
 
     /**
+     * Start an activity indicating that the completion of an outgoing call or an incoming call
+     * which was not blocked by the {@link CallScreeningService}, and which was NOT terminated
+     * while the call was in {@link Call#STATE_AUDIO_PROCESSING}.
+     *
+     * The {@link Uri} extra {@link #EXTRA_HANDLE} will contain the uri handle(phone number) for the
+     * call which completed.
+     *
+     * The integer extra {@link #EXTRA_DISCONNECT_CAUSE} will indicate the reason for the call
+     * disconnection. See {@link #EXTRA_DISCONNECT_CAUSE} for more information.
+     *
+     * The integer extra {@link #EXTRA_CALL_DURATION} will indicate the duration of the call. See
+     * {@link #EXTRA_CALL_DURATION} for more information.
+     */
+    public static final String ACTION_POST_CALL = "android.telecom.action.POST_CALL";
+
+    /**
+     * A {@link Uri} extra, which when set on the {@link #ACTION_POST_CALL} intent, indicates the
+     * uri handle(phone number) of the completed call.
+     */
+    public static final String EXTRA_HANDLE = "android.telecom.extra.HANDLE";
+
+    /**
+     * A integer value provided for completed calls to indicate the reason for the call
+     * disconnection.
+     * <p>
+     * Allowed values:
+     * <ul>
+     * <li>{@link DisconnectCause#UNKNOWN}</li>
+     * <li>{@link DisconnectCause#LOCAL}</li>
+     * <li>{@link DisconnectCause#REMOTE}</li>
+     * <li>{@link DisconnectCause#REJECTED}</li>
+     * <li>{@link DisconnectCause#MISSED}</li>
+     * </ul>
+     * </p>
+     */
+    public static final String EXTRA_DISCONNECT_CAUSE = "android.telecom.extra.DISCONNECT_CAUSE";
+
+    /**
+     * A integer value provided for completed calls to indicate the duration of the call.
+     * <p>
+     * Allowed values:
+     * <ul>
+     * <li>{@link #DURATION_VERY_SHORT}</li>
+     * <li>{@link #DURATION_SHORT}</li>
+     * <li>{@link #DURATION_MEDIUM}</li>
+     * <li>{@link #DURATION_LONG}</li>
+     * </ul>
+     * </p>
+     */
+    public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
+
+    /**
+     * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+     * call was < 3 seconds.
+     */
+    public static final int DURATION_VERY_SHORT = 0;
+
+    /**
+     * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+     * call was >= 3 seconds and < 60 seconds.
+     */
+    public static final int DURATION_SHORT = 1;
+
+    /**
+     * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+     * call was >= 60 seconds and < 120 seconds.
+     */
+    public static final int DURATION_MEDIUM = 2;
+
+    /**
+     * A integer value for {@link #EXTRA_CALL_DURATION}, indicates the duration of the completed
+     * call was >= 120 seconds.
+     */
+    public static final int DURATION_LONG = 3;
+
+    /**
+     * The threshold between {@link #DURATION_VERY_SHORT} calls and {@link #DURATION_SHORT} calls in
+     * milliseconds.
+     * @hide
+     */
+    public static final long VERY_SHORT_CALL_TIME_MS = 3000;
+
+    /**
+     * The threshold between {@link #DURATION_SHORT} calls and {@link #DURATION_MEDIUM} calls in
+     * milliseconds.
+     * @hide
+     */
+    public static final long SHORT_CALL_TIME_MS = 60000;
+
+    /**
+     * The threshold between {@link #DURATION_MEDIUM} calls and {@link #DURATION_LONG} calls in
+     * milliseconds.
+     * @hide
+     */
+    public static final long MEDIUM_CALL_TIME_MS = 120000;
+
+    /**
      * A boolean meta-data value indicating whether an {@link InCallService} implements an
      * in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which
      * would also like to replace the in-call interface should set this meta-data to {@code true} in
@@ -1959,6 +2056,29 @@
         return result;
     }
 
+
+    /**
+     * Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
+     * launch the activity for emergency dialer.
+     *
+     * @param number Optional number to call in emergency dialer
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public Intent createLaunchEmergencyDialerIntent(@Nullable String number) {
+        ITelecomService service = getTelecomService();
+        Intent result = null;
+        if (service != null) {
+            try {
+                result = service.createLaunchEmergencyDialerIntent(number);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error createLaunchEmergencyDialerIntent", e);
+            }
+        }
+        return result;
+    }
+
     /**
      * Determines whether Telecom would permit an incoming call to be added via the
      * {@link #addNewIncomingCall(PhoneAccountHandle, Bundle)} API for the specified
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index cedc4b9..204c37e 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -266,6 +266,11 @@
     **/
     Intent createManageBlockedNumbersIntent();
 
+   /**
+    * @see TelecomServiceImpl#createLaunchEmergencyDialerIntent
+    */
+    Intent createLaunchEmergencyDialerIntent(in String number);
+
     /**
      * @see TelecomServiceImpl#isIncomingCallPermitted
      */
diff --git a/telephony/java/com/android/internal/telephony/EncodeException.java b/telephony/common/com/android/internal/telephony/EncodeException.java
similarity index 100%
rename from telephony/java/com/android/internal/telephony/EncodeException.java
rename to telephony/common/com/android/internal/telephony/EncodeException.java
diff --git a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
new file mode 100644
index 0000000..922af12
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+
+import com.android.internal.os.BackgroundThread;
+
+/**
+ * Helper class for monitoring the state of packages: adding, removing,
+ * updating, and disappearing and reappearing on the SD card.
+ */
+public abstract class PackageChangeReceiver extends BroadcastReceiver {
+    static final IntentFilter sPackageIntentFilter = new IntentFilter();
+    static {
+        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        sPackageIntentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        sPackageIntentFilter.addDataScheme("package");
+    }
+    Context mRegisteredContext;
+
+    /**
+     * To register the intents that needed for monitoring the state of packages
+     */
+    public void register(@NonNull Context context, @Nullable Looper thread,
+            @Nullable UserHandle user) {
+        if (mRegisteredContext != null) {
+            throw new IllegalStateException("Already registered");
+        }
+        Handler handler = (thread == null) ? BackgroundThread.getHandler() : new Handler(thread);
+        mRegisteredContext = context;
+        if (handler != null) {
+            if (user != null) {
+                context.registerReceiverAsUser(this, user, sPackageIntentFilter, null, handler);
+            } else {
+                context.registerReceiver(this, sPackageIntentFilter,
+                        null, handler);
+            }
+        } else {
+            throw new NullPointerException();
+        }
+    }
+
+    /**
+     * To unregister the intents for monitoring the state of packages
+     */
+    public void unregister() {
+        if (mRegisteredContext == null) {
+            throw new IllegalStateException("Not registered");
+        }
+        mRegisteredContext.unregisterReceiver(this);
+        mRegisteredContext = null;
+    }
+
+    /**
+     * This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
+     */
+    public void onPackageAdded(@Nullable String packageName) {
+    }
+
+    /**
+     * This method is invoked when receive the Intent.ACTION_PACKAGE_REMOVED
+     */
+    public void onPackageRemoved(@Nullable String packageName) {
+    }
+
+    /**
+     * This method is invoked when Intent.EXTRA_REPLACING as extra field is true
+     */
+    public void onPackageUpdateFinished(@Nullable String packageName) {
+    }
+
+    /**
+     * This method is invoked when receive the Intent.ACTION_PACKAGE_CHANGED or
+     * Intent.EXTRA_REPLACING as extra field is true
+     */
+    public void onPackageModified(@Nullable String packageName) {
+    }
+
+    /**
+     * This method is invoked when receive the Intent.ACTION_QUERY_PACKAGE_RESTART and
+     * Intent.ACTION_PACKAGE_RESTARTED
+     */
+    public void onHandleForceStop(@Nullable String[] packages, boolean doit) {
+    }
+
+    /**
+     * This method is invoked when receive the Intent.ACTION_PACKAGE_REMOVED
+     */
+    public void onPackageDisappeared() {
+    }
+
+    /**
+     * This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
+     */
+    public void onPackageAppeared() {
+    }
+
+    @Override
+    public void onReceive(@Nullable Context context, @Nullable Intent intent) {
+        String action = intent.getAction();
+
+        if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+            String pkg = getPackageName(intent);
+            if (pkg != null) {
+                if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    onPackageUpdateFinished(pkg);
+                    onPackageModified(pkg);
+                } else {
+                    onPackageAdded(pkg);
+                }
+                onPackageAppeared();
+            }
+        } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+            String pkg = getPackageName(intent);
+            if (pkg != null) {
+                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    onPackageRemoved(pkg);
+                }
+                onPackageDisappeared();
+            }
+        } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+            String pkg = getPackageName(intent);
+            if (pkg != null) {
+                onPackageModified(pkg);
+            }
+        } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
+            String[] disappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+            onHandleForceStop(disappearingPackages, false);
+        } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+            String[] disappearingPackages = new String[] {getPackageName(intent)};
+            onHandleForceStop(disappearingPackages, true);
+        }
+    }
+
+    String getPackageName(Intent intent) {
+        Uri uri = intent.getData();
+        String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+        return pkg;
+    }
+}
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 9da45da..07dfcf0 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -39,11 +39,12 @@
 import android.os.UserHandle;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
+import android.telephony.PackageChangeReceiver;
 import android.telephony.Rlog;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
-import com.android.internal.content.PackageMonitor;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
@@ -67,10 +68,10 @@
  */
 public final class SmsApplication {
     static final String LOG_TAG = "SmsApplication";
-    private static final String PHONE_PACKAGE_NAME = "com.android.phone";
-    private static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
-    private static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
-    private static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
+    public static final String PHONE_PACKAGE_NAME = "com.android.phone";
+    public static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+    public static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
+    public static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
 
     private static final String SCHEME_SMS = "sms";
     private static final String SCHEME_SMSTO = "smsto";
@@ -79,13 +80,13 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_MULTIUSER = false;
 
-    private static final int[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
-            AppOpsManager.OP_READ_SMS,
-            AppOpsManager.OP_WRITE_SMS,
-            AppOpsManager.OP_RECEIVE_SMS,
-            AppOpsManager.OP_RECEIVE_WAP_PUSH,
-            AppOpsManager.OP_SEND_SMS,
-            AppOpsManager.OP_READ_CELL_BROADCASTS
+    private static final String[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
+            AppOpsManager.OPSTR_READ_SMS,
+            AppOpsManager.OPSTR_WRITE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
+            AppOpsManager.OPSTR_SEND_SMS,
+            AppOpsManager.OPSTR_READ_CELL_BROADCASTS
     };
 
     private static SmsPackageMonitor sSmsPackageMonitor = null;
@@ -305,7 +306,7 @@
                 Uri.fromParts(SCHEME_SMSTO, "", null));
         List<ResolveInfo> respondServices = packageManager.queryIntentServicesAsUser(intent,
                 PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.getUserHandleForUid(userId));
+                UserHandle.of(userId));
         for (ResolveInfo resolveInfo : respondServices) {
             final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
             if (serviceInfo == null) {
@@ -501,7 +502,7 @@
 
         // If we found a package, make sure AppOps permissions are set up correctly
         if (applicationData != null) {
-            // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
+            // We can only call unsafeCheckOp if we are privileged (updateIfNeeded) or if the app we
             // are checking is for our current uid. Doing this check from the unprivileged current
             // SMS app allows us to tell the current SMS app that it is not in a good state and
             // needs to ask to be the current SMS app again to work properly.
@@ -555,23 +556,23 @@
         // apps, all of them should be able to write to telephony provider.
         // This is to allow the proxy package permission check in telephony provider
         // to pass.
-        for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
-            appOps.setUidMode(appop, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
+        for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            appOps.setUidMode(opStr, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
         }
     }
 
     private static boolean tryFixExclusiveSmsAppops(Context context,
             SmsApplicationData applicationData, boolean updateIfNeeded) {
         AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
-        for (int appOp : DEFAULT_APP_EXCLUSIVE_APPOPS) {
-            int mode = appOps.checkOp(appOp, applicationData.mUid,
+        for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            int mode = appOps.unsafeCheckOp(opStr, applicationData.mUid,
                     applicationData.mPackageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 Rlog.e(LOG_TAG, applicationData.mPackageName + " lost "
-                        + AppOpsManager.modeToName(appOp) + ": "
+                        + opStr + ": "
                         + (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
                 if (updateIfNeeded) {
-                    appOps.setUidMode(appOp, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
+                    appOps.setUidMode(opStr, applicationData.mUid, AppOpsManager.MODE_ALLOWED);
                 } else {
                     return false;
                 }
@@ -757,7 +758,7 @@
         }
         try {
             PackageInfo info = packageManager.getPackageInfo(packageName, 0);
-            int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
+            int mode = appOps.unsafeCheckOp(AppOpsManager.OPSTR_WRITE_SMS, info.applicationInfo.uid,
                     packageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 Rlog.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS:  (fixing)");
@@ -773,8 +774,8 @@
 
     private static void setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid,
             int mode) {
-        for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
-            appOpsManager.setUidMode(appop, uid, mode);
+        for (String opStr : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            appOpsManager.setUidMode(opStr, uid, mode);
         }
     }
 
@@ -782,7 +783,7 @@
      * Tracks package changes and ensures that the default SMS app is always configured to be the
      * preferred activity for SENDTO sms/mms intents.
      */
-    private static final class SmsPackageMonitor extends PackageMonitor {
+    private static final class SmsPackageMonitor extends PackageChangeReceiver {
         final Context mContext;
 
         public SmsPackageMonitor(Context context) {
@@ -791,12 +792,12 @@
         }
 
         @Override
-        public void onPackageDisappeared(String packageName, int reason) {
+        public void onPackageDisappeared() {
             onPackageChanged();
         }
 
         @Override
-        public void onPackageAppeared(String packageName, int reason) {
+        public void onPackageAppeared() {
             onPackageChanged();
         }
 
@@ -829,7 +830,7 @@
 
     public static void initSmsPackageMonitor(Context context) {
         sSmsPackageMonitor = new SmsPackageMonitor(context);
-        sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL, false);
+        sSmsPackageMonitor.register(context, context.getMainLooper(), UserHandle.ALL);
     }
 
     @UnsupportedAppUsage
@@ -899,6 +900,7 @@
      * @param userId target user ID.
      * @return component name of the app and class to deliver SMS messages to
      */
+    @VisibleForTesting
     public static ComponentName getDefaultSmsApplicationAsUser(Context context,
             boolean updateIfNeeded, int userId) {
         final long token = Binder.clearCallingIdentity();
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
index 367aad1..06c08f5 100644
--- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -20,8 +20,8 @@
 import android.database.Cursor;
 import android.database.SQLException;
 import android.os.Binder;
-import android.os.Build;
 import android.os.PersistableBundle;
+import android.os.SystemProperties;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.Rlog;
@@ -43,7 +43,7 @@
  */
 public class SmsNumberUtils {
     private static final String TAG = "SmsNumberUtils";
-    private static final boolean DBG = Build.IS_DEBUGGABLE;
+    private static final boolean DBG = SystemProperties.getInt("ro.debuggable", 0) == 1;
 
     private static final String PLUS_SIGN = "+";
 
diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java
index b237705..8efca0e 100755
--- a/telephony/common/com/google/android/mms/pdu/PduPersister.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java
@@ -34,6 +34,7 @@
 import android.provider.Telephony.MmsSms.PendingMessages;
 import android.provider.Telephony.Threads;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -1448,9 +1449,9 @@
         final Set<String> myPhoneNumbers = new HashSet<String>();
         if (excludeMyNumber) {
             // Build a list of my phone numbers from the various sims.
-            for (int subid : subscriptionManager.getActiveSubscriptionIdList()) {
+            for (SubscriptionInfo subInfo : subscriptionManager.getActiveSubscriptionInfoList()) {
                 final String myNumber = mContext.getSystemService(TelephonyManager.class).
-                        createForSubscriptionId(subid).getLine1Number();
+                        createForSubscriptionId(subInfo.getSubscriptionId()).getLine1Number();
                 if (myNumber != null) {
                     myPhoneNumbers.add(myNumber);
                 }
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index f89bbc7..7482ecc 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -98,7 +98,13 @@
             TelephonyManager.NETWORK_TYPE_GSM,
             TelephonyManager.NETWORK_TYPE_TD_SCDMA,
             TelephonyManager.NETWORK_TYPE_IWLAN,
-            TelephonyManager.NETWORK_TYPE_LTE_CA,
+
+            //TODO: In order for @SystemApi methods to use this class, there cannot be any
+            // public hidden members.  This network type is marked as hidden because it is not a
+            // true network type and we are looking to remove it completely from the available list
+            // of network types.
+            //TelephonyManager.NETWORK_TYPE_LTE_CA,
+
             TelephonyManager.NETWORK_TYPE_NR,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -116,7 +122,8 @@
             ApnSetting.TYPE_CBS,
             ApnSetting.TYPE_IA,
             ApnSetting.TYPE_EMERGENCY,
-            ApnSetting.TYPE_MCX
+            ApnSetting.TYPE_MCX,
+            ApnSetting.TYPE_XCAP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApnType {
@@ -463,9 +470,7 @@
             DataFailCause.UNKNOWN,
             DataFailCause.RADIO_NOT_AVAILABLE,
             DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
-            DataFailCause.CONNECTION_TO_DATACONNECTIONAC_BROKEN,
             DataFailCause.LOST_CONNECTION,
-            DataFailCause.RESET_BY_FRAMEWORK
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DataFailureCause {
@@ -486,30 +491,85 @@
             PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
     public @interface PreciseCallStates {}
 
+    @IntDef(value = {
+            DisconnectCause.NOT_VALID,
+            DisconnectCause.NOT_DISCONNECTED,
+            DisconnectCause.INCOMING_MISSED,
+            DisconnectCause.NORMAL,
+            DisconnectCause.LOCAL,
+            DisconnectCause.BUSY,
+            DisconnectCause.CONGESTION,
+            DisconnectCause.MMI,
+            DisconnectCause.INVALID_NUMBER,
+            DisconnectCause.NUMBER_UNREACHABLE,
+            DisconnectCause.SERVER_UNREACHABLE,
+            DisconnectCause.INVALID_CREDENTIALS,
+            DisconnectCause.OUT_OF_NETWORK,
+            DisconnectCause.SERVER_ERROR,
+            DisconnectCause.TIMED_OUT,
+            DisconnectCause.LOST_SIGNAL,
+            DisconnectCause.LIMIT_EXCEEDED,
+            DisconnectCause.INCOMING_REJECTED,
+            DisconnectCause.POWER_OFF,
+            DisconnectCause.OUT_OF_SERVICE,
+            DisconnectCause.ICC_ERROR,
+            DisconnectCause.CALL_BARRED,
+            DisconnectCause.FDN_BLOCKED,
+            DisconnectCause.CS_RESTRICTED,
+            DisconnectCause.CS_RESTRICTED_NORMAL,
+            DisconnectCause.CS_RESTRICTED_EMERGENCY,
+            DisconnectCause.UNOBTAINABLE_NUMBER,
+            DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+            DisconnectCause.CDMA_DROP,
+            DisconnectCause.CDMA_INTERCEPT,
+            DisconnectCause.CDMA_REORDER,
+            DisconnectCause.CDMA_SO_REJECT,
+            DisconnectCause.CDMA_RETRY_ORDER,
+            DisconnectCause.CDMA_ACCESS_FAILURE,
+            DisconnectCause.CDMA_PREEMPTED,
+            DisconnectCause.CDMA_NOT_EMERGENCY,
+            DisconnectCause.CDMA_ACCESS_BLOCKED,
+            DisconnectCause.ERROR_UNSPECIFIED,
+    })
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
-            ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
-            ServiceState.RIL_RADIO_TECHNOLOGY_GPRS,
-            ServiceState.RIL_RADIO_TECHNOLOGY_EDGE,
-            ServiceState.RIL_RADIO_TECHNOLOGY_UMTS,
-            ServiceState.RIL_RADIO_TECHNOLOGY_IS95A,
-            ServiceState.RIL_RADIO_TECHNOLOGY_IS95B,
-            ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT,
-            ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0,
-            ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A,
-            ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA,
-            ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA,
-            ServiceState.RIL_RADIO_TECHNOLOGY_HSPA,
-            ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B,
-            ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD,
-            ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
-            ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP,
-            ServiceState.RIL_RADIO_TECHNOLOGY_GSM,
-            ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA,
-            ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
-            ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
-            ServiceState.RIL_RADIO_TECHNOLOGY_NR})
-    public @interface RilRadioTechnology {}
+    public @interface DisconnectCauses {
+    }
+
+    @IntDef(value = {
+            PreciseDisconnectCause.NOT_VALID,
+            PreciseDisconnectCause.NO_DISCONNECT_CAUSE_AVAILABLE,
+            PreciseDisconnectCause.UNOBTAINABLE_NUMBER,
+            PreciseDisconnectCause.NORMAL,
+            PreciseDisconnectCause.BUSY,
+            PreciseDisconnectCause.NUMBER_CHANGED,
+            PreciseDisconnectCause.STATUS_ENQUIRY,
+            PreciseDisconnectCause.NORMAL_UNSPECIFIED,
+            PreciseDisconnectCause.NO_CIRCUIT_AVAIL,
+            PreciseDisconnectCause.TEMPORARY_FAILURE,
+            PreciseDisconnectCause.SWITCHING_CONGESTION,
+            PreciseDisconnectCause.CHANNEL_NOT_AVAIL,
+            PreciseDisconnectCause.QOS_NOT_AVAIL,
+            PreciseDisconnectCause.BEARER_NOT_AVAIL,
+            PreciseDisconnectCause.ACM_LIMIT_EXCEEDED,
+            PreciseDisconnectCause.CALL_BARRED,
+            PreciseDisconnectCause.FDN_BLOCKED,
+            PreciseDisconnectCause.IMSI_UNKNOWN_IN_VLR,
+            PreciseDisconnectCause.IMEI_NOT_ACCEPTED,
+            PreciseDisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+            PreciseDisconnectCause.CDMA_DROP,
+            PreciseDisconnectCause.CDMA_INTERCEPT,
+            PreciseDisconnectCause.CDMA_REORDER,
+            PreciseDisconnectCause.CDMA_SO_REJECT,
+            PreciseDisconnectCause.CDMA_RETRY_ORDER,
+            PreciseDisconnectCause.CDMA_ACCESS_FAILURE,
+            PreciseDisconnectCause.CDMA_PREEMPTED,
+            PreciseDisconnectCause.CDMA_NOT_EMERGENCY,
+            PreciseDisconnectCause.CDMA_ACCESS_BLOCKED,
+            PreciseDisconnectCause.ERROR_UNSPECIFIED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PreciseDisconnectCauses {
+    }
 
     @IntDef({
             Connection.AUDIO_CODEC_NONE,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 92c6e93..57a8018 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -100,6 +100,16 @@
             KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
 
     /**
+     * Boolean indicating the Supplementary Services(SS) is disable when airplane mode on in the
+     * Call Settings menu.
+     * {@code true}: SS is disable when airplane mode on.
+     * {@code false}: SS is enable when airplane mode on.
+     * The default value for this key is {@code false}
+     */
+    public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL =
+            "disable_supplementary_services_in_airplane_mode_bool";
+
+    /**
      * Boolean indicating if the "Call forwarding" item is visible in the Call Settings menu.
      * true means visible. false means gone.
      * @hide
@@ -409,12 +419,33 @@
             KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
 
     /**
-     * Override the device's configuration for the ImsService to use for this SIM card.
+     * The package name containing the ImsService that will be bound to the telephony framework to
+     * support both IMS MMTEL and RCS feature functionality instead of the device default
+     * ImsService for this subscription.
+     * @deprecated Use {@link #KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING} and
+     * {@link #KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING} instead to configure these values
+     * separately. If any of those values are not empty, they will override this value.
      */
     public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING =
             "config_ims_package_override_string";
 
     /**
+     * The package name containing the ImsService that will be bound to the telephony framework to
+     * support IMS MMTEL feature functionality instead of the device default ImsService for this
+     * subscription.
+     */
+    public static final String KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING =
+            "config_ims_mmtel_package_override_string";
+
+    /**
+     * The package name containing the ImsService that will be bound to the telephony framework to
+     * support IMS RCS feature functionality instead of the device default ImsService for this
+     * subscription.
+     */
+    public static final String KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING =
+            "config_ims_rcs_package_override_string";
+
+    /**
      * Override the package that will manage {@link SubscriptionPlan}
      * information instead of the {@link CarrierService} that defines this
      * value.
@@ -823,13 +854,6 @@
             "always_show_emergency_alert_onoff_bool";
 
     /**
-     * The flag to disable cell broadcast severe alert when extreme alert is disabled.
-     * @hide
-     */
-    public static final String KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL =
-            "disable_severe_when_extreme_disabled_bool";
-
-    /**
      * The data call retry configuration for different types of APN.
      * @hide
      */
@@ -1946,6 +1970,12 @@
             "allow_add_call_during_video_call";
 
     /**
+     * When false, indicates that holding a video call is disabled
+     */
+    public static final String KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL =
+            "allow_holding_video_call";
+
+    /**
      * When true, indicates that the HD audio icon in the in-call screen should not be shown for
      * VoWifi calls.
      * @hide
@@ -2182,7 +2212,7 @@
      * the start of the next month.
      * <p>
      * This setting may be still overridden by explicit user choice. By default,
-     * the platform value will be used.
+     * {@link #DATA_CYCLE_USE_PLATFORM_DEFAULT} will be used.
      */
     public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT =
             "monthly_data_cycle_day_int";
@@ -2191,10 +2221,7 @@
      * When {@link #KEY_MONTHLY_DATA_CYCLE_DAY_INT}, {@link #KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG},
      * or {@link #KEY_DATA_WARNING_THRESHOLD_BYTES_LONG} are set to this value, the platform default
      * value will be used for that key.
-     *
-     * @hide
      */
-    @Deprecated
     public static final int DATA_CYCLE_USE_PLATFORM_DEFAULT = -1;
 
     /**
@@ -2218,8 +2245,8 @@
      * If the value is set to {@link #DATA_CYCLE_THRESHOLD_DISABLED}, the data usage warning will
      * be disabled.
      * <p>
-     * This setting may be overridden by explicit user choice. By default, the platform value
-     * will be used.
+     * This setting may be overridden by explicit user choice. By default,
+     * {@link #DATA_CYCLE_USE_PLATFORM_DEFAULT} will be used.
      */
     public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG =
             "data_warning_threshold_bytes_long";
@@ -2227,8 +2254,7 @@
     /**
      * Controls if the device should automatically notify the user as they reach
      * their cellular data warning. When set to {@code false} the carrier is
-     * expected to have implemented their own notification mechanism.
-     * @hide
+     * expected to have implemented their own notification mechanism. {@code true} by default.
      */
     public static final String KEY_DATA_WARNING_NOTIFICATION_BOOL =
             "data_warning_notification_bool";
@@ -2250,8 +2276,8 @@
      * phone. If the value is set to {@link #DATA_CYCLE_THRESHOLD_DISABLED}, the data limit will be
      * disabled.
      * <p>
-     * This setting may be overridden by explicit user choice. By default, the platform value
-     * will be used.
+     * This setting may be overridden by explicit user choice. By default,
+     * {@link #DATA_CYCLE_USE_PLATFORM_DEFAULT} will be used.
      */
     public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG =
             "data_limit_threshold_bytes_long";
@@ -2259,8 +2285,7 @@
     /**
      * Controls if the device should automatically notify the user as they reach
      * their cellular data limit. When set to {@code false} the carrier is
-     * expected to have implemented their own notification mechanism.
-     * @hide
+     * expected to have implemented their own notification mechanism. {@code true} by default.
      */
     public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL =
             "data_limit_notification_bool";
@@ -2268,8 +2293,7 @@
     /**
      * Controls if the device should automatically notify the user when rapid
      * cellular data usage is observed. When set to {@code false} the carrier is
-     * expected to have implemented their own notification mechanism.
-     * @hide
+     * expected to have implemented their own notification mechanism.  {@code true} by default.
      */
     public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL =
             "data_rapid_notification_bool";
@@ -2293,13 +2317,41 @@
     /**
      * Determine whether to use only RSRP for the number of LTE signal bars.
      * @hide
+     *
+     * @deprecated use {@link #KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT}.
      */
     // FIXME: this key and related keys must not be exposed without a consistent philosophy for
     // all RATs.
+    @Deprecated
     public static final String KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL =
             "use_only_rsrp_for_lte_signal_bar_bool";
 
     /**
+     * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP),
+     * Reference Signal Received Quality (RSRQ), or/and Reference Signal Signal to Noise Ratio
+     * (RSSNR) for the number of LTE signal bars and signal criteria reporting enabling.
+     *
+     * <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
+     * not be used for calculating signal level. If multiple measures are set bit, the parameter
+     * whose value is smallest is used to indicate the signal level.
+     *
+     *  RSRP = 1 << 0,
+     *  RSRQ = 1 << 1,
+     *  RSSNR = 1 << 2,
+     *
+     *  The value of this key must be bitwise OR of {@link CellSignalStrengthLte#USE_RSRP},
+     *  {@link CellSignalStrengthLte#USE_RSRQ}, {@link CellSignalStrengthLte#USE_RSSNR}.
+     *
+     * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
+     * If the key is invalid or not configured, a default value (RSRP | RSSNR = 1 << 0 | 1 << 2)
+     * will apply.
+     *
+     * @hide
+     */
+    public static final String KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT =
+            "parameters_used_for_lte_signal_bar_int";
+
+    /**
      * List of 4 customized 5G SS reference signal received power (SSRSRP) thresholds.
      *
      * Reference: 3GPP TS 38.215
@@ -2323,7 +2375,7 @@
      * Reference: 3GPP TS 38.215
      *
      * 4 threshold integers must be within the boundaries [-20 dB, -3 dB], and the levels are:
-     *     "NONE: [-23, threshold1]"
+     *     "NONE: [-20, threshold1]"
      *     "POOR: (threshold1, threshold2]"
      *     "MODERATE: (threshold2, threshold3]"
      *     "GOOD:  (threshold3, threshold4]"
@@ -2357,15 +2409,26 @@
     /**
      * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
      * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
-     * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
-     * parameter whose value is smallest is used to indicate the signal bar.
+     * ratio (SSSINR) for the number of 5G NR signal bars and signal criteria reporting enabling.
+     *
+     * <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
+     * not be used for calculating signal level. If multiple measures are set bit, the parameter
+     * whose value is smallest is used to indicate the signal level.
      *
      *  SSRSRP = 1 << 0,
      *  SSRSRQ = 1 << 1,
      *  SSSINR = 1 << 2,
      *
+     *  The value of this key must be bitwise OR of {@link CellSignalStrengthNr#USE_SSRSRP},
+     *  {@link CellSignalStrengthNr#USE_SSRSRQ}, {@link CellSignalStrengthNr#USE_SSSINR}.
+     *
+     * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+     * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
+     *
      *  Reference: 3GPP TS 38.215,
      *             3GPP TS 38.133 10.1.16.1
+     *
+     * @hide
      */
     public static final String KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT =
             "parameters_use_for_5g_nr_signal_bar_int";
@@ -2591,6 +2654,42 @@
             "lte_rsrp_thresholds_int_array";
 
     /**
+     * A list of 4 customized LTE Reference Signal Received Quality (RSRQ) thresholds.
+     *
+     * Reference: TS 136.133 v12.6.0 section 9.1.7 - RSRQ Measurement Report Mapping.
+     *
+     * 4 threshold integers must be within the boundaries [-34 dB, 3 dB], and the levels are:
+     *     "NONE: [-34, threshold1)"
+     *     "POOR: [threshold1, threshold2)"
+     *     "MODERATE: [threshold2, threshold3)"
+     *     "GOOD:  [threshold3, threshold4)"
+     *     "EXCELLENT:  [threshold4, 3]"
+     *
+     * This key is considered invalid if the format is violated. If the key is invalid or
+     * not configured, a default value set will apply.
+     */
+    public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY =
+            "lte_rsrq_thresholds_int_array";
+
+    /**
+     * A list of 4 customized LTE Reference Signal Signal to Noise Ratio (RSSNR) thresholds.
+     *
+     * 4 threshold integers must be within the boundaries [-200, 300], and the levels are:
+     *     "NONE: [-200, threshold1)"
+     *     "POOR: [threshold1, threshold2)"
+     *     "MODERATE: [threshold2, threshold3)"
+     *     "GOOD:  [threshold3, threshold4)"
+     *     "EXCELLENT:  [threshold4, 300]"
+     * Note: the unit of the values is 10*db; it is derived by multiplying 10 on the original dB
+     * value reported by modem.
+     *
+     * This key is considered invalid if the format is violated. If the key is invalid or
+     * not configured, a default value set will apply.
+     */
+    public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY =
+            "lte_rssnr_thresholds_int_array";
+
+    /**
      * Decides when clients try to bind to iwlan network service, which package name will
      * the binding intent go to.
      * @hide
@@ -2968,10 +3067,11 @@
             "data_switch_validation_timeout_long";
 
     /**
-     * GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration.
-     * @hide
+     * GPS configs. See the GNSS HAL documentation for more details.
      */
     public static final class Gps {
+        private Gps() {}
+
         /** Prefix of all Gps.KEY_* constants. */
         public static final String KEY_PREFIX = "gps.";
 
@@ -3011,10 +3111,14 @@
         /**
          * SUPL server host for SET Initiated & non-ES Network-Initiated SUPL requests.
          * Default to supl.google.com
+         * @hide
          */
         public static final String KEY_SUPL_HOST_STRING = KEY_PREFIX + "supl_host";
 
-        /** SUPL server port. Default to 7275. */
+        /**
+         * SUPL server port. Default to 7275.
+         * @hide
+         */
         public static final String KEY_SUPL_PORT_STRING = KEY_PREFIX + "supl_port";
 
         /**
@@ -3022,6 +3126,7 @@
          * with bits 0:7 representing a service indicator field, bits 8:15
          * representing the minor version and bits 16:23 representing the
          * major version. Default to 0x20000.
+         * @hide
          */
         public static final String KEY_SUPL_VER_STRING = KEY_PREFIX + "supl_ver";
 
@@ -3029,6 +3134,7 @@
          * SUPL_MODE configuration bit mask
          * 1 - Mobile Station Based. This is default.
          * 2 - Mobile Station Assisted.
+         * @hide
          */
         public static final String KEY_SUPL_MODE_STRING = KEY_PREFIX + "supl_mode";
 
@@ -3037,6 +3143,7 @@
          * (e.g. E911), and SUPL non-ES requests to only outside of non user emergency sessions.
          * 0 - no.
          * 1 - yes. This is default.
+         * @hide
          */
         // TODO(b/119567985): name this key properly
         public static final String KEY_SUPL_ES_STRING = KEY_PREFIX + "supl_es";
@@ -3046,6 +3153,7 @@
          * 0 - Radio Resource Location Protocol in user plane and control plane. This is default.
          * 1 - Enable LTE Positioning Protocol in user plane.
          * 2 - Enable LTE Positioning Protocol in control plane.
+         * @hide
          */
         public static final String KEY_LPP_PROFILE_STRING = KEY_PREFIX + "lpp_profile";
 
@@ -3053,6 +3161,7 @@
          * Determine whether to use emergency PDN for emergency SUPL.
          * 0 - no.
          * 1 - yes. This is default.
+         * @hide
          */
         public static final String KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING =
                 KEY_PREFIX + "use_emergency_pdn_for_emergency_supl";
@@ -3063,6 +3172,7 @@
          * 1 - Use A-GLONASS in Radio Resource Control(RRC) control-plane.
          * 2 - Use A-GLONASS in Radio Resource Location user-plane.
          * 4 - Use A-GLONASS in LTE Positioning Protocol User plane.
+         * @hide
          */
         public static final String KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING =
                 KEY_PREFIX + "a_glonass_pos_protocol_select";
@@ -3074,11 +3184,13 @@
          * "1" - Lock Mobile Originated GPS functionalities.
          * "2" - Lock Network initiated GPS functionalities.
          * "3" - Lock both. This is default.
+         * @hide
          */
         public static final String KEY_GPS_LOCK_STRING = KEY_PREFIX + "gps_lock";
 
         /**
          * Control Plane / SUPL NI emergency extension time in seconds. Default to "0".
+         * @hide
          */
         public static final String KEY_ES_EXTENSION_SEC_STRING = KEY_PREFIX + "es_extension_sec";
 
@@ -3087,6 +3199,7 @@
          * the non-framework entities requesting location directly from GNSS without involving
          * the framework, as managed by IGnssVisibilityControl.hal. For example,
          * "com.example.mdt com.example.ims".
+         * @hide
          */
         public static final String KEY_NFW_PROXY_APPS_STRING = KEY_PREFIX + "nfw_proxy_apps";
 
@@ -3107,6 +3220,18 @@
         public static final String KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT = KEY_PREFIX
                 + "es_supl_control_plane_support_int";
 
+        /**
+         * A list of roaming PLMNs where SUPL ES mode does not support a control-plane mechanism to
+         * get a user's location in the event that data plane SUPL fails or is otherwise
+         * unavailable.
+         * <p>
+         * A string array of PLMNs that do not support a control-plane mechanism for getting a
+         * user's location for SUPL ES.
+         * @hide
+         */
+        public static final String KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY =
+                KEY_PREFIX + "es_supl_data_plane_only_roaming_plmn_string_array";
+
         private static PersistableBundle getDefaults() {
             PersistableBundle defaults = new PersistableBundle();
             defaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true);
@@ -3123,63 +3248,11 @@
             defaults.putString(KEY_NFW_PROXY_APPS_STRING, "");
             defaults.putInt(KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT,
                     SUPL_EMERGENCY_MODE_TYPE_CP_ONLY);
+            defaults.putStringArray(KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY, null);
             return defaults;
         }
     }
 
-    /**
-     * Wi-Fi configs used in Carrier Wi-Fi application.
-     * TODO(b/132059890): Expose it in a future release as systemapi.
-     *
-     * @hide
-     */
-    public static final class Wifi {
-        /** Prefix of all Wifi.KEY_* constants. */
-        public static final String KEY_PREFIX = "wifi.";
-
-        /**
-         * Whenever any information under wifi namespace is changed, the version should be
-         * incremented by 1 so that the device is able to figure out the latest profiles based on
-         * the version.
-         */
-        public static final String KEY_CARRIER_PROFILES_VERSION_INT =
-                KEY_PREFIX + "carrier_profiles_version_int";
-
-        /**
-         * It contains the package name of connection manager that the carrier owns.
-         *
-         * <P>Once it is installed, the profiles installed by Carrier Wi-Fi Application
-         * will be deleted.
-         * Once it is uninstalled, Carrier Wi-Fi Application will re-install the latest profiles.
-         */
-        public static final String KEY_CARRIER_CONNECTION_MANAGER_PACKAGE_STRING =
-                KEY_PREFIX + "carrier_connection_manager_package_string";
-        /**
-         * It is to have the list of wifi networks profiles which contain the information about
-         * the wifi-networks to which carrier wants the device to connect.
-         */
-        public static final String KEY_NETWORK_PROFILES_STRING_ARRAY =
-                KEY_PREFIX + "network_profiles_string_array";
-
-        /**
-         * It is to have the list of Passpoint profiles which contain the information about
-         * the Passpoint networks to which carrier wants the device to connect.
-         */
-        public static final String KEY_PASSPOINT_PROFILES_STRING_ARRAY =
-                KEY_PREFIX + "passpoint_profiles_string_array";
-
-        private static PersistableBundle getDefaults() {
-            PersistableBundle defaults = new PersistableBundle();
-            defaults.putInt(KEY_CARRIER_PROFILES_VERSION_INT, -1);
-            defaults.putString(KEY_CARRIER_CONNECTION_MANAGER_PACKAGE_STRING, null);
-            defaults.putStringArray(KEY_NETWORK_PROFILES_STRING_ARRAY, null);
-            defaults.putStringArray(KEY_PASSPOINT_PROFILES_STRING_ARRAY, null);
-            return defaults;
-        }
-
-        private Wifi() {}
-    }
-
    /**
     * An int array containing CDMA enhanced roaming indicator values for Home (non-roaming) network.
     * The default values come from 3GPP2 C.R1001 table 8.1-1.
@@ -3393,6 +3466,7 @@
         sDefaults.putBoolean(KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL, true);
         sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL, true);
         sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL, true);
+        sDefaults.putBoolean(KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL, false);
         sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
         sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
         sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
@@ -3441,7 +3515,6 @@
         sDefaults.putStringArray(KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
-        sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
         sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
                 "default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
                         + "320000:5000,640000:5000,1280000:5000,1800000:5000",
@@ -3473,6 +3546,8 @@
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putString(KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
+        sDefaults.putString(KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING, null);
+        sDefaults.putString(KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING, null);
         sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_DIAL_STRING_REPLACE_STRING_ARRAY, null);
@@ -3616,6 +3691,7 @@
         sDefaults.putBoolean(KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL, false);
         sDefaults.putBoolean(KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL, true);
         sDefaults.putBoolean(KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL, true);
+        sDefaults.putBoolean(KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_WIFI_CALLS_CAN_BE_HD_AUDIO, true);
         sDefaults.putBoolean(KEY_VIDEO_CALLS_CAN_BE_HD_AUDIO, true);
         sDefaults.putBoolean(KEY_GSM_CDMA_CALLS_CAN_BE_HD_AUDIO, false);
@@ -3685,6 +3761,20 @@
                         -108, /* SIGNAL_STRENGTH_GOOD */
                         -98,  /* SIGNAL_STRENGTH_GREAT */
                 });
+        sDefaults.putIntArray(KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY,
+                new int[] {
+                        -19, /* SIGNAL_STRENGTH_POOR */
+                        -17, /* SIGNAL_STRENGTH_MODERATE */
+                        -14, /* SIGNAL_STRENGTH_GOOD */
+                        -12  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putIntArray(KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY,
+                new int[] {
+                        -30, /* SIGNAL_STRENGTH_POOR */
+                        10,  /* SIGNAL_STRENGTH_MODERATE */
+                        45,  /* SIGNAL_STRENGTH_GOOD */
+                        130  /* SIGNAL_STRENGTH_GREAT */
+                });
         sDefaults.putIntArray(KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY,
                 new int[] {
                         -115,  /* SIGNAL_STRENGTH_POOR */
@@ -3692,6 +3782,32 @@
                         -95, /* SIGNAL_STRENGTH_GOOD */
                         -85  /* SIGNAL_STRENGTH_GREAT */
                 });
+        sDefaults.putIntArray(KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
+                // Boundaries: [-140 dB, -44 dB]
+                new int[] {
+                    -125, /* SIGNAL_STRENGTH_POOR */
+                    -115, /* SIGNAL_STRENGTH_MODERATE */
+                    -105, /* SIGNAL_STRENGTH_GOOD */
+                    -95,  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putIntArray(KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
+                // Boundaries: [-20 dB, -3 dB]
+                new int[] {
+                    -14, /* SIGNAL_STRENGTH_POOR */
+                    -12, /* SIGNAL_STRENGTH_MODERATE */
+                    -10, /* SIGNAL_STRENGTH_GOOD */
+                    -8  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
+                // Boundaries: [-23 dB, 40 dB]
+                new int[] {
+                    -8, /* SIGNAL_STRENGTH_POOR */
+                    0, /* SIGNAL_STRENGTH_MODERATE */
+                    8, /* SIGNAL_STRENGTH_GOOD */
+                    16  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
+                CellSignalStrengthNr.USE_SSRSRP);
         sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "rssi");
         sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
@@ -3726,7 +3842,6 @@
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000);
         sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
         sDefaults.putAll(Gps.getDefaults());
-        sDefaults.putAll(Wifi.getDefaults());
         sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
                 new int[] {
                         1 /* Roaming Indicator Off */
@@ -3754,6 +3869,8 @@
                 new int[] {4 /* BUSY */});
         sDefaults.putBoolean(KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL, false);
         sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, 2000);
+        sDefaults.putInt(KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT,
+                CellSignalStrengthLte.USE_RSRP | CellSignalStrengthLte.USE_RSSNR);
     }
 
     /**
@@ -3810,6 +3927,34 @@
     @SystemApi
     @TestApi
     public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues) {
+        overrideConfig(subscriptionId, overrideValues, false);
+    }
+
+    /**
+     * Overrides the carrier config of the provided subscription ID with the provided values.
+     *
+     * Any further queries to carrier config from any process will return the overridden values
+     * after this method returns. The overrides are effective until the user passes in {@code null}
+     * for {@code overrideValues}. This removes all previous overrides and sets the carrier config
+     * back to production values.
+     *
+     * The overrides is stored persistently and will survive a reboot if {@code persistent} is true.
+     *
+     * May throw an {@link IllegalArgumentException} if {@code overrideValues} contains invalid
+     * values for the specified config keys.
+     *
+     * NOTE: This API is meant for testing purposes only.
+     *
+     * @param subscriptionId The subscription ID for which the override should be done.
+     * @param overrideValues Key-value pairs of the values that are to be overridden. If set to
+     *                       {@code null}, this will remove all previous overrides and set the
+     *                       carrier configuration back to production values.
+     * @param persistent     Determines whether the override should be persistent.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues,
+            boolean persistent) {
         try {
             ICarrierConfigLoader loader = getICarrierConfigLoader();
             if (loader == null) {
@@ -3817,7 +3962,7 @@
                         + " ICarrierConfigLoader is null");
                 return;
             }
-            loader.overrideConfig(subscriptionId, overrideValues);
+            loader.overrideConfig(subscriptionId, overrideValues, persistent);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "Error setting config for subId " + subscriptionId + ": "
                     + ex.toString());
@@ -3923,13 +4068,28 @@
         }
     }
 
-    /** {@hide} */
+    /**
+     * Gets the package name for a default carrier service.
+     * @return the package name for a default carrier service; empty string if not available.
+     *
+     * @hide
+     */
+    @NonNull
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getDefaultCarrierServicePackageName() {
         try {
-            return getICarrierConfigLoader().getDefaultCarrierServicePackageName();
-        } catch (Throwable t) {
-            return null;
+            ICarrierConfigLoader loader = getICarrierConfigLoader();
+            if (loader == null) {
+                Rlog.w(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null");
+                return "";
+            }
+            return loader.getDefaultCarrierServicePackageName();
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null"
+                    + ex.toString());
         }
+        return "";
     }
 
     /**
diff --git a/telephony/java/android/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java
index f4ce6e7..84be4e8 100644
--- a/telephony/java/android/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -20,16 +20,22 @@
 import android.annotation.SystemApi;
 import android.text.TextUtils;
 
+import com.android.internal.telephony.util.TelephonyUtils;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
-
 /**
- * This utils class is specifically used for geo-targeting of CellBroadcast messages.
+ * This utils class is used for geo-fencing of CellBroadcast messages and is used by the cell
+ * broadcast module.
+ *
  * The coordinates used by this utils class are latitude and longitude, but some algorithms in this
  * class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use
  * this class for anything other then geo-targeting of cellbroadcast messages.
+ *
+ * More information regarding cell broadcast geo-fencing logic is laid out in 3GPP TS 23.041 and
+ * ATIS-0700041.
  * @hide
  */
 @SystemApi
@@ -80,7 +86,7 @@
     /** @hide */
     private static final String POLYGON_SYMBOL = "polygon";
 
-    /** Point represent by (latitude, longitude). */
+    /** A point represented by (latitude, longitude). */
     public static class LatLng {
         public final double lat;
         public final double lng;
@@ -96,8 +102,8 @@
         }
 
         /**
-         * @param p the point use to calculate the subtraction result.
-         * @return the result of this point subtract the given point {@code p}.
+         * @param p the point to subtract
+         * @return the result of the subtraction
          */
         @NonNull
         public LatLng subtract(@NonNull LatLng p) {
@@ -105,9 +111,9 @@
         }
 
         /**
-         * Calculate the distance in meter between this point and the given point {@code p}.
-         * @param p the point use to calculate the distance.
-         * @return the distance in meter.
+         * Calculate the distance in meters between this point and the given point {@code p}.
+         * @param p the point used to calculate the distance.
+         * @return the distance in meters.
          */
         public double distance(@NonNull LatLng p) {
             double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat));
@@ -124,8 +130,9 @@
     }
 
     /**
-     * The class represents a simple polygon with at least 3 points.
-     * @hide
+     * A class representing a simple polygon with at least 3 points. This is used for geo-fencing
+     * logic with cell broadcasts. More information regarding cell broadcast geo-fencing logic is
+     * laid out in 3GPP TS 23.041 and ATIS-0700041.
      */
     public static class Polygon implements Geometry {
         /**
@@ -144,7 +151,7 @@
          * connected to form an edge of the polygon. The polygon has at least 3 vertices, and the
          * last vertices and the first vertices must be adjacent.
          *
-         * The longitude difference in the vertices should be less than 180 degree.
+         * The longitude difference in the vertices should be less than 180 degrees.
          */
         public Polygon(@NonNull List<LatLng> vertices) {
             mVertices = vertices;
@@ -163,19 +170,24 @@
                     .collect(Collectors.toList());
         }
 
-        public List<LatLng> getVertices() {
+        /**
+         * Return the list of vertices which compose the polygon.
+         */
+        public @NonNull List<LatLng> getVertices() {
             return mVertices;
         }
 
         /**
-         * Check if the given point {@code p} is inside the polygon. This method counts the number
-         * of times the polygon winds around the point P, A.K.A "winding number". The point is
-         * outside only when this "winding number" is 0.
+         * Check if the given LatLng is inside the polygon.
          *
-         * If a point is on the edge of the polygon, it is also considered to be inside the polygon.
+         * If a LatLng is on the edge of the polygon, it is also considered to be inside the
+         * polygon.
          */
         @Override
-        public boolean contains(LatLng latLng) {
+        public boolean contains(@NonNull LatLng latLng) {
+            // This method counts the number of times the polygon winds around the point P, A.K.A
+            // "winding number". The point is outside only when this "winding number" is 0.
+
             Point p = convertAndScaleLatLng(latLng);
 
             int n = mScaledVertices.size();
@@ -244,6 +256,7 @@
             return a.x * b.y - a.y * b.x;
         }
 
+        /** @hide */
         static final class Point {
             public final double x;
             public final double y;
@@ -257,32 +270,69 @@
                 return new Point(x - p.x, y - p.y);
             }
         }
+
+        @Override
+        public String toString() {
+            String str = "Polygon: ";
+            if (TelephonyUtils.IS_DEBUGGABLE) {
+                str += mVertices;
+            }
+            return str;
+        }
     }
 
     /**
-     * The class represents a circle.
-     * @hide
+     * A class represents a {@link Geometry} in the shape of a Circle. This is used for handling
+     * geo-fenced cell broadcasts. More information regarding cell broadcast geo-fencing logic is
+     * laid out in 3GPP TS 23.041 and ATIS-0700041.
      */
     public static class Circle implements Geometry {
         private final LatLng mCenter;
         private final double mRadiusMeter;
 
-        public Circle(LatLng center, double radiusMeter) {
+        /**
+         * Construct a Circle given a center point and a radius in meters.
+         *
+         * @param center the latitude and longitude of the center of the circle
+         * @param radiusInMeters the radius of the circle in meters
+         */
+        public Circle(@NonNull LatLng center, double radiusInMeters) {
             this.mCenter = center;
-            this.mRadiusMeter = radiusMeter;
+            this.mRadiusMeter = radiusInMeters;
         }
 
-        public LatLng getCenter() {
+        /**
+         * Return the latitude and longitude of the center of the circle;
+         */
+        public @NonNull LatLng getCenter() {
             return mCenter;
         }
 
+        /**
+         * Return the radius of the circle in meters.
+         */
         public double getRadius() {
             return mRadiusMeter;
         }
 
+        /**
+         * Check if the given LatLng is inside the circle.
+         *
+         * If a LatLng is on the edge of the circle, it is also considered to be inside the circle.
+         */
         @Override
-        public boolean contains(LatLng p) {
-            return mCenter.distance(p) <= mRadiusMeter;
+        public boolean contains(@NonNull LatLng latLng) {
+            return mCenter.distance(latLng) <= mRadiusMeter;
+        }
+
+        @Override
+        public String toString() {
+            String str = "Circle: ";
+            if (TelephonyUtils.IS_DEBUGGABLE) {
+                str += mCenter + ", radius = " + mRadiusMeter;
+            }
+
+            return str;
         }
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 8336d1b..8df9d23 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -55,6 +55,25 @@
     private static final int MAX_LTE_RSRP = -44;
     private static final int MIN_LTE_RSRP = -140;
 
+    /**
+     * Indicates RSRP is considered for {@link #getLevel()} and reported from modem.
+     *
+     * @hide
+     */
+    public static final int USE_RSRP = 1 << 0;
+    /**
+     * Indicates RSRQ is considered for {@link #getLevel()} and reported from modem.
+     *
+     * @hide
+     */
+    public static final int USE_RSRQ = 1 << 1;
+    /**
+     * Indicates RSSNR is considered for {@link #getLevel()} and reported from modem.
+     *
+     * @hide
+     */
+    public static final int USE_RSSNR = 1 << 2;
+
     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mSignalStrength; // To be removed
     private int mRssi;
@@ -70,6 +89,21 @@
     private int mTimingAdvance;
     private int mLevel;
 
+    /**
+     * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP),
+     * Reference Signal Received Quality (RSRQ), and/or Reference Signal Signal to Noise Ratio
+     * (RSSNR) for the number of LTE signal bars. If multiple measures are set, the parameter
+     * whose signal level value is smallest is used to indicate the signal level.
+     *
+     *  RSRP = 1 << 0,
+     *  RSRQ = 1 << 1,
+     *  RSSNR = 1 << 2,
+     *
+     * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
+     * If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply.
+     */
+    private int mParametersUseForLevel;
+
     /** @hide */
     @UnsupportedAppUsage
     public CellSignalStrengthLte() {
@@ -81,7 +115,7 @@
      *
      * @param rssi in dBm [-113,-51], UNKNOWN
      * @param rsrp in dBm [-140,-43], UNKNOWN
-     * @param rsrq in dB [-20,-3], UNKNOWN
+     * @param rsrq in dB [-34, 3], UNKNOWN
      * @param rssnr in 10*dB [-200, +300], UNKNOWN
      * @param cqi [0, 15], UNKNOWN
      * @param timingAdvance [0, 1282], UNKNOWN
@@ -94,7 +128,7 @@
         mRssi = inRangeOrUnavailable(rssi, -113, -51);
         mSignalStrength = mRssi;
         mRsrp = inRangeOrUnavailable(rsrp, -140, -43);
-        mRsrq = inRangeOrUnavailable(rsrq, -20, -3);
+        mRsrq = inRangeOrUnavailable(rsrq, -34, 3);
         mRssnr = inRangeOrUnavailable(rssnr, -200, 300);
         mCqi = inRangeOrUnavailable(cqi, 0, 15);
         mTimingAdvance = inRangeOrUnavailable(timingAdvance, 0, 1282);
@@ -125,6 +159,7 @@
         mCqi = s.mCqi;
         mTimingAdvance = s.mTimingAdvance;
         mLevel = s.mLevel;
+        mParametersUseForLevel = s.mParametersUseForLevel;
     }
 
     /** @hide */
@@ -144,6 +179,7 @@
         mCqi = CellInfo.UNAVAILABLE;
         mTimingAdvance = CellInfo.UNAVAILABLE;
         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        mParametersUseForLevel = USE_RSRP | USE_RSSNR;
     }
 
     /** {@inheritDoc} */
@@ -154,102 +190,153 @@
     }
 
     // Lifted from Default carrier configs and max range of RSRP
-    private static final int[] sThresholds = new int[]{-115, -105, -95, -85};
+    private static final int[] sRsrpThresholds = new int[] {
+            -115, /* SIGNAL_STRENGTH_POOR */
+            -105, /* SIGNAL_STRENGTH_MODERATE */
+            -95,  /* SIGNAL_STRENGTH_GOOD */
+            -85   /* SIGNAL_STRENGTH_GREAT */
+    };
+
+    // Lifted from Default carrier configs and max range of RSRQ
+    private static final int[] sRsrqThresholds = new int[] {
+            -19, /* SIGNAL_STRENGTH_POOR */
+            -17, /* SIGNAL_STRENGTH_MODERATE */
+            -14, /* SIGNAL_STRENGTH_GOOD */
+            -12  /* SIGNAL_STRENGTH_GREAT */
+    };
+    // Lifted from Default carrier configs and max range of RSSNR
+    private static final int[] sRssnrThresholds = new int[] {
+            -30, /* SIGNAL_STRENGTH_POOR */
+            10,  /* SIGNAL_STRENGTH_MODERATE */
+            45,  /* SIGNAL_STRENGTH_GOOD */
+            130  /* SIGNAL_STRENGTH_GREAT */
+    };
     private static final int sRsrpBoost = 0;
 
+    /**
+     * Checks if the given parameter type is considered to use for {@link #getLevel()}.
+     *
+     * Note: if multiple parameter types are considered, the smaller level for one of the
+     * parameters would be returned by {@link #getLevel()}
+     *
+     * @param parameterType bitwise OR of {@link #USE_RSRP}, {@link #USE_RSRQ},
+     *         {@link #USE_RSSNR}
+     * @return {@code true} if the level is calculated based on the given parameter type;
+     *      {@code false} otherwise.
+     */
+    private boolean isLevelForParameter(int parameterType) {
+        return (parameterType & mParametersUseForLevel) == parameterType;
+    }
+
     /** @hide */
     @Override
     public void updateLevel(PersistableBundle cc, ServiceState ss) {
-        int[] thresholds;
+        int[] rsrpThresholds, rsrqThresholds, rssnrThresholds;
         boolean rsrpOnly;
         if (cc == null) {
-            thresholds = sThresholds;
+            mParametersUseForLevel = USE_RSRP | USE_RSSNR;
+            rsrpThresholds = sRsrpThresholds;
+            rsrqThresholds = sRsrqThresholds;
+            rssnrThresholds = sRssnrThresholds;
             rsrpOnly = false;
         } else {
+            mParametersUseForLevel = cc.getInt(
+                    CarrierConfigManager.KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT);
+            Rlog.i(LOG_TAG, "Using signal strength level: " + mParametersUseForLevel);
+            rsrpThresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
+            if (rsrpThresholds == null) rsrpThresholds = sRsrpThresholds;
+            Rlog.i(LOG_TAG, "Applying LTE RSRP Thresholds: " + Arrays.toString(rsrpThresholds));
+            rsrqThresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY);
+            if (rsrqThresholds == null) rsrqThresholds = sRsrqThresholds;
+            Rlog.i(LOG_TAG, "Applying LTE RSRQ Thresholds: " + Arrays.toString(rsrqThresholds));
+            rssnrThresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY);
+            if (rssnrThresholds == null) rssnrThresholds = sRssnrThresholds;
+            Rlog.i(LOG_TAG, "Applying LTE RSSNR Thresholds: " + Arrays.toString(rssnrThresholds));
             rsrpOnly = cc.getBoolean(
                     CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false);
-            thresholds = cc.getIntArray(
-                    CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
-            if (thresholds == null) thresholds = sThresholds;
-            if (DBG) log("updateLevel() carrierconfig - rsrpOnly="
-                    + rsrpOnly + ", thresholds=" + Arrays.toString(thresholds));
         }
 
-
         int rsrpBoost = 0;
         if (ss != null) {
             rsrpBoost = ss.getLteEarfcnRsrpBoost();
         }
 
-        int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        int rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        int snrIconLevel = -1;
-
-        int rsrp = mRsrp + rsrpBoost;
-
-        if (rsrp < MIN_LTE_RSRP || rsrp > MAX_LTE_RSRP) {
-            rsrpIconLevel = -1;
-        } else {
-            rsrpIconLevel = thresholds.length;
-            while (rsrpIconLevel > 0 && rsrp < thresholds[rsrpIconLevel - 1]) rsrpIconLevel--;
-        }
+        int rsrp = inRangeOrUnavailable(mRsrp + rsrpBoost, MIN_LTE_RSRP, MAX_LTE_RSRP);
 
         if (rsrpOnly) {
-            if (DBG) log("updateLevel() - rsrp = " + rsrpIconLevel);
-            if (rsrpIconLevel != -1) {
-                mLevel = rsrpIconLevel;
+            int level = updateLevelWithMeasure(rsrp, rsrpThresholds);
+            if (DBG) log("updateLevel() - rsrp = " + level);
+            if (level != SignalStrength.INVALID) {
+                mLevel = level;
                 return;
             }
         }
 
-        /*
-         * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
-         * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
-         * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
-         * Icon Only
-         */
-        if (mRssnr > 300) snrIconLevel = -1;
-        else if (mRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
-        else if (mRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
-        else if (mRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
-        else if (mRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
-        else if (mRssnr >= -200)
-            snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        int rsrpLevel = SignalStrength.INVALID;
+        int rsrqLevel = SignalStrength.INVALID;
+        int rssnrLevel = SignalStrength.INVALID;
 
-        if (DBG) log("updateLevel() - rsrp:" + mRsrp + " snr:" + mRssnr + " rsrpIconLevel:"
-                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
-                + " lteRsrpBoost:" + sRsrpBoost);
-
-        /* Choose a measurement type to use for notification */
-        if (snrIconLevel != -1 && rsrpIconLevel != -1) {
-            /*
-             * The number of bars displayed shall be the smaller of the bars
-             * associated with LTE RSRP and the bars associated with the LTE
-             * RS_SNR
-             */
-            mLevel = (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
-            return;
+        if (isLevelForParameter(USE_RSRP)) {
+            rsrpLevel = updateLevelWithMeasure(rsrp, rsrpThresholds);
+            Rlog.i(LOG_TAG, "Updated 4G LTE RSRP Level: " + rsrpLevel);
         }
-
-        if (snrIconLevel != -1) {
-            mLevel = snrIconLevel;
-            return;
+        if (isLevelForParameter(USE_RSRQ)) {
+            rsrqLevel = updateLevelWithMeasure(mRsrq, rsrqThresholds);
+            Rlog.i(LOG_TAG, "Updated 4G LTE RSRQ Level: " + rsrqLevel);
         }
-
-        if (rsrpIconLevel != -1) {
-            mLevel = rsrpIconLevel;
-            return;
+        if (isLevelForParameter(USE_RSSNR)) {
+            rssnrLevel = updateLevelWithMeasure(mRssnr, rssnrThresholds);
+            Rlog.i(LOG_TAG, "Updated 4G LTE RSSNR Level: " + rssnrLevel);
         }
+        // Apply the smaller value among three levels of three measures.
+        mLevel = Math.min(Math.min(rsrpLevel, rsrqLevel), rssnrLevel);
 
-        if (mRssi > -51) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (mRssi >= -89) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
-        else if (mRssi >= -97) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
-        else if (mRssi >= -103) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
-        else if (mRssi >= -113) rssiIconLevel = SIGNAL_STRENGTH_POOR;
-        else rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:"
-                + rssiIconLevel);
-        mLevel = rssiIconLevel;
+        if (mLevel == SignalStrength.INVALID) {
+            int rssiLevel;
+            if (mRssi > -51) {
+                rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            } else if (mRssi >= -89) {
+                rssiLevel = SIGNAL_STRENGTH_GREAT;
+            } else if (mRssi >= -97) {
+                rssiLevel = SIGNAL_STRENGTH_GOOD;
+            } else if (mRssi >= -103) {
+                rssiLevel = SIGNAL_STRENGTH_MODERATE;
+            } else if (mRssi >= -113) {
+                rssiLevel = SIGNAL_STRENGTH_POOR;
+            } else {
+                rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            }
+            if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:" + rssiLevel);
+            mLevel = rssiLevel;
+        }
+    }
+
+    /**
+     * Update level with corresponding measure and thresholds.
+     *
+     * @param measure corresponding signal measure
+     * @param thresholds corresponding signal thresholds
+     * @return level of the signal strength
+     */
+    private int updateLevelWithMeasure(int measure, int[] thresholds) {
+        int level;
+        if (measure == CellInfo.UNAVAILABLE) {
+            level = SignalStrength.INVALID;
+        } else if (measure >= thresholds[3]) {
+            level = SIGNAL_STRENGTH_GREAT;
+        } else if (measure >= thresholds[2]) {
+            level = SIGNAL_STRENGTH_GOOD;
+        } else if (measure >= thresholds[1]) {
+            level = SIGNAL_STRENGTH_MODERATE;
+        } else if (measure >= thresholds[0]) {
+            level = SIGNAL_STRENGTH_POOR;
+        } else {
+            level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        }
+        return level;
     }
 
     /**
@@ -386,7 +473,8 @@
                 + " rssnr=" + mRssnr
                 + " cqi=" + mCqi
                 + " ta=" + mTimingAdvance
-                + " level=" + mLevel;
+                + " level=" + mLevel
+                + " parametersUseForLevel=" + mParametersUseForLevel;
     }
 
     /** Implement the Parcelable interface */
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index f9b7f6d..f31fafe 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -16,11 +16,15 @@
 
 package android.telephony;
 
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -36,13 +40,67 @@
 
     private static final String TAG = "CellSignalStrengthNr";
 
+    // Lifted from Default carrier configs and max range of SSRSRP
+    // Boundaries: [-140 dB, -44 dB]
+    private int[] mSsRsrpThresholds = new int[] {
+            -125, /* SIGNAL_STRENGTH_POOR */
+            -115, /* SIGNAL_STRENGTH_MODERATE */
+            -105, /* SIGNAL_STRENGTH_GOOD */
+            -95,  /* SIGNAL_STRENGTH_GREAT */
+    };
+
+    // Lifted from Default carrier configs and max range of SSRSRQ
+    // Boundaries: [-20 dB, -3 dB]
+    private int[] mSsRsrqThresholds = new int[] {
+            -14, /* SIGNAL_STRENGTH_POOR */
+            -12, /* SIGNAL_STRENGTH_MODERATE */
+            -10, /* SIGNAL_STRENGTH_GOOD */
+            -8  /* SIGNAL_STRENGTH_GREAT */
+    };
+
+    // Lifted from Default carrier configs and max range of SSSINR
+    // Boundaries: [-23 dB, 40 dB]
+    private int[] mSsSinrThresholds = new int[] {
+            -8, /* SIGNAL_STRENGTH_POOR */
+            0, /* SIGNAL_STRENGTH_MODERATE */
+            8, /* SIGNAL_STRENGTH_GOOD */
+            16  /* SIGNAL_STRENGTH_GREAT */
+    };
+
     /**
-     * These threshold values are copied from LTE.
-     * TODO: make it configurable via CarrierConfig.
+     * Indicates SSRSRP is considered for {@link #getLevel()} and reporting from modem.
+     *
+     * @hide
      */
-    private static final int SIGNAL_GREAT_THRESHOLD = -95;
-    private static final int SIGNAL_GOOD_THRESHOLD = -105;
-    private static final int SIGNAL_MODERATE_THRESHOLD = -115;
+    public static final int USE_SSRSRP = 1 << 0;
+    /**
+     * Indicates SSRSRQ is considered for {@link #getLevel()} and reporting from modem.
+     *
+     * @hide
+     */
+    public static final int USE_SSRSRQ = 1 << 1;
+    /**
+     * Indicates SSSINR is considered for {@link #getLevel()} and reporting from modem.
+     *
+     * @hide
+     */
+    public static final int USE_SSSINR = 1 << 2;
+
+    /**
+     * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
+     * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
+     * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
+     * parameter whose value is smallest is used to indicate the signal bar.
+     *
+     * @hide
+     */
+    @IntDef(flag = true, prefix = { "USE_" }, value = {
+        USE_SSRSRP,
+        USE_SSRSRQ,
+        USE_SSSINR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SignalLevelAndReportCriteriaSource {}
 
     private int mCsiRsrp;
     private int mCsiRsrq;
@@ -52,6 +110,21 @@
     private int mSsSinr;
     private int mLevel;
 
+    /**
+     * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
+     * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
+     * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
+     * parameter whose value is smallest is used to indicate the signal bar.
+     *
+     *  SSRSRP = 1 << 0,
+     *  SSRSRQ = 1 << 1,
+     *  SSSINR = 1 << 2,
+     *
+     * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+     * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
+     */
+    private int mParametersUseForLevel;
+
     /** @hide */
     public CellSignalStrengthNr() {
         setDefaultValues();
@@ -182,6 +255,7 @@
         mSsRsrq = CellInfo.UNAVAILABLE;
         mSsSinr = CellInfo.UNAVAILABLE;
         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        mParametersUseForLevel = USE_SSRSRP;
     }
 
     /** {@inheritDoc} */
@@ -191,20 +265,83 @@
         return mLevel;
     }
 
+    /**
+     * Checks if the given parameter type is considered to use for {@link #getLevel()}.
+     *
+     * Note: if multiple parameter types are considered, the smaller level for one of the
+     * parameters would be returned by {@link #getLevel()}
+     *
+     * @param parameterType bitwise OR of {@link #USE_SSRSRP}, {@link #USE_SSRSRQ},
+     *         {@link #USE_SSSINR}
+     * @return {@code true} if the level is calculated based on the given parameter type;
+     *      {@code false} otherwise.
+     *
+     */
+    private boolean isLevelForParameter(@SignalLevelAndReportCriteriaSource int parameterType) {
+        return (parameterType & mParametersUseForLevel) == parameterType;
+    }
+
     /** @hide */
     @Override
     public void updateLevel(PersistableBundle cc, ServiceState ss) {
-        if (mSsRsrp == CellInfo.UNAVAILABLE) {
-            mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        } else if (mSsRsrp >= SIGNAL_GREAT_THRESHOLD) {
-            mLevel = SIGNAL_STRENGTH_GREAT;
-        } else if (mSsRsrp >= SIGNAL_GOOD_THRESHOLD) {
-            mLevel = SIGNAL_STRENGTH_GOOD;
-        } else if (mSsRsrp >= SIGNAL_MODERATE_THRESHOLD) {
-            mLevel = SIGNAL_STRENGTH_MODERATE;
+        if (cc == null) {
+            mParametersUseForLevel = USE_SSRSRP;
         } else {
-            mLevel = SIGNAL_STRENGTH_POOR;
+            mParametersUseForLevel = cc.getInt(
+                    CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, USE_SSRSRP);
+            Rlog.i(TAG, "Using SSRSRP for Level.");
+            mSsRsrpThresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY);
+            Rlog.i(TAG, "Applying 5G NR SSRSRP Thresholds: " + Arrays.toString(mSsRsrpThresholds));
+            mSsRsrqThresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY);
+            Rlog.i(TAG, "Applying 5G NR SSRSRQ Thresholds: " + Arrays.toString(mSsRsrqThresholds));
+            mSsSinrThresholds = cc.getIntArray(
+                    CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY);
+            Rlog.i(TAG, "Applying 5G NR SSSINR Thresholds: " + Arrays.toString(mSsSinrThresholds));
         }
+        int ssRsrpLevel = SignalStrength.INVALID;
+        int ssRsrqLevel = SignalStrength.INVALID;
+        int ssSinrLevel = SignalStrength.INVALID;
+        if (isLevelForParameter(USE_SSRSRP)) {
+            ssRsrpLevel = updateLevelWithMeasure(mSsRsrp, mSsRsrpThresholds);
+            Rlog.i(TAG, "Updated 5G NR SSRSRP Level: " + ssRsrpLevel);
+        }
+        if (isLevelForParameter(USE_SSRSRQ)) {
+            ssRsrqLevel = updateLevelWithMeasure(mSsRsrq, mSsRsrqThresholds);
+            Rlog.i(TAG, "Updated 5G NR SSRSRQ Level: " + ssRsrqLevel);
+        }
+        if (isLevelForParameter(USE_SSSINR)) {
+            ssSinrLevel = updateLevelWithMeasure(mSsSinr, mSsSinrThresholds);
+            Rlog.i(TAG, "Updated 5G NR SSSINR Level: " + ssSinrLevel);
+        }
+        // Apply the smaller value among three levels of three measures.
+        mLevel = Math.min(Math.min(ssRsrpLevel, ssRsrqLevel), ssSinrLevel);
+    }
+
+    /**
+     * Update level with corresponding measure and thresholds.
+     *
+     * @param measure corresponding signal measure
+     * @param thresholds corresponding signal thresholds
+     * @return level of the signal strength
+     */
+    private int updateLevelWithMeasure(int measure, int[] thresholds) {
+        int level;
+        if (measure == CellInfo.UNAVAILABLE) {
+            level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        } else if (measure > thresholds[3]) {
+            level = SIGNAL_STRENGTH_GREAT;
+        } else if (measure > thresholds[2]) {
+            level = SIGNAL_STRENGTH_GOOD;
+        } else if (measure > thresholds[1]) {
+            level = SIGNAL_STRENGTH_MODERATE;
+        }  else if (measure > thresholds[0]) {
+            level = SIGNAL_STRENGTH_POOR;
+        } else {
+            level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        }
+        return level;
     }
 
     /**
@@ -247,6 +384,7 @@
         mSsRsrq = s.mSsRsrq;
         mSsSinr = s.mSsSinr;
         mLevel = s.mLevel;
+        mParametersUseForLevel = s.mParametersUseForLevel;
     }
 
     /** @hide */
@@ -290,6 +428,7 @@
                 .append(" ssRsrq = " + mSsRsrq)
                 .append(" ssSinr = " + mSsSinr)
                 .append(" level = " + mLevel)
+                .append(" parametersUseForLevel = " + mParametersUseForLevel)
                 .append(" }")
                 .toString();
     }
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 246bec7..e1c4bef 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -15,17 +15,14 @@
  */
 package android.telephony;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.PersistableBundle;
-
 import android.telephony.Annotation.DataFailureCause;
-import com.android.internal.util.ArrayUtils;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import com.android.internal.telephony.util.ArrayUtils;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -953,14 +950,10 @@
     public static final int UNKNOWN = 0x10000;
     /** Data fail due to radio not unavailable. */
     public static final int RADIO_NOT_AVAILABLE = 0x10001;                   /* no retry */
-    /** @hide */
+    /** Data fail due to unacceptable network parameter. */
     public static final int UNACCEPTABLE_NETWORK_PARAMETER = 0x10002;        /* no retry */
-    /** @hide */
-    public static final int CONNECTION_TO_DATACONNECTIONAC_BROKEN = 0x10003;
     /** Data connection was lost. */
     public static final int LOST_CONNECTION = 0x10004;
-    /** @hide */
-    public static final int RESET_BY_FRAMEWORK = 0x10005;
 
     /**
      * Data handover failed.
@@ -1364,10 +1357,7 @@
         sFailCauseMap.put(RADIO_NOT_AVAILABLE, "RADIO_NOT_AVAILABLE");
         sFailCauseMap.put(UNACCEPTABLE_NETWORK_PARAMETER,
                 "UNACCEPTABLE_NETWORK_PARAMETER");
-        sFailCauseMap.put(CONNECTION_TO_DATACONNECTIONAC_BROKEN,
-                "CONNECTION_TO_DATACONNECTIONAC_BROKEN");
         sFailCauseMap.put(LOST_CONNECTION, "LOST_CONNECTION");
-        sFailCauseMap.put(RESET_BY_FRAMEWORK, "RESET_BY_FRAMEWORK");
     }
 
     private DataFailCause() {
diff --git a/telephony/java/android/telephony/IFinancialSmsCallback.aidl b/telephony/java/android/telephony/IFinancialSmsCallback.aidl
deleted file mode 100644
index aa88615..0000000
--- a/telephony/java/android/telephony/IFinancialSmsCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-** Copyright 2019, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.telephony;
-
-import android.app.PendingIntent;
-import android.database.CursorWindow;
-import android.net.Uri;
-import android.os.Bundle;
-import com.android.internal.telephony.SmsRawData;
-
-/** Interface for returning back the financial sms messages asynchrously.
- *  @hide
- */
-interface IFinancialSmsCallback {
-    /**
-     * Return sms messages back to calling financial app.
-     *
-     * @param messages the sms messages returned for cinancial app.
-     */
-    oneway void onGetSmsMessagesForFinancialApp(in CursorWindow messages);
-}
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 02d8be3..39af34c 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -16,7 +16,10 @@
 
 package android.telephony.ims;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.telephony.SubscriptionManager;
 
@@ -25,12 +28,15 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 @SystemService(Context.TELEPHONY_IMS_SERVICE)
 public class ImsManager {
 
     private Context mContext;
 
-    public ImsManager(Context context) {
+    /** @hide */
+    public ImsManager(@NonNull Context context) {
         mContext = context;
     }
 
@@ -41,6 +47,7 @@
      * @throws IllegalArgumentException if the subscription is invalid.
      * @return a ImsRcsManager instance with the specific subscription ID.
      */
+    @NonNull
     public ImsRcsManager getImsRcsManager(int subscriptionId) {
         if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
             throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
@@ -56,6 +63,7 @@
      * @throws IllegalArgumentException if the subscription is invalid.
      * @return a ImsMmTelManager instance with the specific subscription ID.
      */
+    @NonNull
     public ImsMmTelManager getImsMmTelManager(int subscriptionId) {
         if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
             throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index eb744f6..d4526a4 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -33,6 +33,8 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.internal.telephony.util.TelephonyUtils;
+
 import java.util.List;
 
 /**
@@ -162,7 +164,7 @@
         }
         Log.e(TAG, errorMsg);
         try {
-            if (Build.IS_DEBUGGABLE) {
+            if (TelephonyUtils.IS_DEBUGGABLE) {
                 Toast.makeText(context, errorMsg, Toast.LENGTH_SHORT).show();
             }
         } catch (Throwable t) {
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index a0af392..aee7cca 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -16,43 +16,65 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import android.os.SystemClock;
+import android.util.Range;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
- * Reports modem activity information
+ * Reports modem activity information.
  * @hide
  */
-public class ModemActivityInfo implements Parcelable {
+@SystemApi
+public final class ModemActivityInfo implements Parcelable {
     /**
-     * Tx power index
-     * index 0 = tx_power < 0dBm
-     * index 1 = 0dBm < tx_power < 5dBm
-     * index 2 = 5dBm < tx_power < 15dBm
-     * index 3 = 15dBm < tx_power < 20dBm
-     * index 4 = tx_power > 20dBm
+     * Tx(transmit) power level. see power index below
+     * <ul>
+     *   <li> index 0 = tx_power < 0dBm. </li>
+     *   <li> index 1 = 0dBm < tx_power < 5dBm. </li>
+     *   <li> index 2 = 5dBm < tx_power < 15dBm. </li>
+     *   <li> index 3 = 15dBm < tx_power < 20dBm. </li>
+     *   <li> index 4 = tx_power > 20dBm. </li>
+     * </ul>
      */
     public static final int TX_POWER_LEVELS = 5;
+    private static final Range<Integer>[] TX_POWER_RANGES = new Range[] {
+        new Range<>(Integer.MIN_VALUE, 0),
+        new Range<>(0, 5),
+        new Range<>(5, 15),
+        new Range<>(15, 20),
+        new Range<>(20, Integer.MAX_VALUE)
+
+    };
 
     private long mTimestamp;
     private int mSleepTimeMs;
     private int mIdleTimeMs;
-    private int [] mTxTimeMs = new int[TX_POWER_LEVELS];
+    private List<TransmitPower> mTransmitPowerInfo = new ArrayList<>(TX_POWER_LEVELS);
     private int mRxTimeMs;
-    private int mEnergyUsed;
 
     public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
-                        int[] txTimeMs, int rxTimeMs, int energyUsed) {
+                        @NonNull int[] txTimeMs, int rxTimeMs) {
         mTimestamp = timestamp;
         mSleepTimeMs = sleepTimeMs;
         mIdleTimeMs = idleTimeMs;
         if (txTimeMs != null) {
-            System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+            populateTransmitPowerRange(txTimeMs);
         }
         mRxTimeMs = rxTimeMs;
-        mEnergyUsed = energyUsed;
+    }
+
+    /** helper API to populate tx power range for each bucket **/
+    private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) {
+        for (int i = 0; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
+            mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
+        }
     }
 
     @Override
@@ -61,9 +83,8 @@
             + " mTimestamp=" + mTimestamp
             + " mSleepTimeMs=" + mSleepTimeMs
             + " mIdleTimeMs=" + mIdleTimeMs
-            + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
+            + " mTransmitPowerInfo[]=" + mTransmitPowerInfo.toString()
             + " mRxTimeMs=" + mRxTimeMs
-            + " mEnergyUsed=" + mEnergyUsed
             + "}";
     }
 
@@ -82,9 +103,8 @@
                 txTimeMs[i] = in.readInt();
             }
             int rxTimeMs = in.readInt();
-            int energyUsed = in.readInt();
             return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
-                                txTimeMs, rxTimeMs, energyUsed);
+                                txTimeMs, rxTimeMs);
         }
 
         public ModemActivityInfo[] newArray(int size) {
@@ -92,107 +112,158 @@
         }
     };
 
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(mTimestamp);
         dest.writeInt(mSleepTimeMs);
         dest.writeInt(mIdleTimeMs);
         for (int i = 0; i < TX_POWER_LEVELS; i++) {
-            dest.writeInt(mTxTimeMs[i]);
+            dest.writeInt(mTransmitPowerInfo.get(i).getTimeInMillis());
         }
         dest.writeInt(mRxTimeMs);
-        dest.writeInt(mEnergyUsed);
     }
 
     /**
-     * @return timestamp of record creation
+     * @return milliseconds since boot, including mTimeInMillis spent in sleep.
+     * @see SystemClock#elapsedRealtime()
      */
     public long getTimestamp() {
         return mTimestamp;
     }
 
+    /** @hide */
     public void setTimestamp(long timestamp) {
         mTimestamp = timestamp;
     }
 
     /**
-     * @return tx time in ms. It's an array of tx times
-     * with each index...
+     * @return an arrayList of {@link TransmitPower} with each element representing the total time where
+     * transmitter is awake time (in ms) for a given power range (in dbm).
+     *
+     * @see #TX_POWER_LEVELS
      */
-    public int [] getTxTimeMillis() {
-        return mTxTimeMs;
+    @NonNull
+    public List<TransmitPower> getTransmitPowerInfo() {
+        return mTransmitPowerInfo;
     }
 
-    public void setTxTimeMillis(int[] txTimeMs) {
-        mTxTimeMs = txTimeMs;
+    /** @hide */
+    public void setTransmitTimeMillis(int[] txTimeMs) {
+        populateTransmitPowerRange(txTimeMs);
+    }
+
+    /** @hide */
+    @NonNull
+    public int[] getTransmitTimeMillis() {
+        int[] transmitTimeMillis = new int[TX_POWER_LEVELS];
+        for (int i = 0; i < transmitTimeMillis.length; i++) {
+            transmitTimeMillis[i] = mTransmitPowerInfo.get(i).getTimeInMillis();
+        }
+        return transmitTimeMillis;
     }
 
     /**
-     * @return sleep time in ms.
+     * @return total mTimeInMillis (in ms) when modem is in a low power or sleep state.
      */
     public int getSleepTimeMillis() {
         return mSleepTimeMs;
     }
 
+    /** @hide */
     public void setSleepTimeMillis(int sleepTimeMillis) {
         mSleepTimeMs = sleepTimeMillis;
     }
 
     /**
-     * @return idle time in ms.
+     * @return total mTimeInMillis (in ms) when modem is awake but neither the transmitter nor receiver are
+     * active.
      */
     public int getIdleTimeMillis() {
         return mIdleTimeMs;
     }
 
+    /** @hide */
     public void setIdleTimeMillis(int idleTimeMillis) {
         mIdleTimeMs = idleTimeMillis;
     }
 
     /**
-     * @return rx time in ms.
+     * @return rx(receive) mTimeInMillis in ms.
      */
-    public int getRxTimeMillis() {
+    public int getReceiveTimeMillis() {
         return mRxTimeMs;
     }
 
-    public void setRxTimeMillis(int rxTimeMillis) {
+    /** @hide */
+    public void setReceiveTimeMillis(int rxTimeMillis) {
         mRxTimeMs = rxTimeMillis;
     }
 
     /**
-     * product of current(mA), voltage(V) and time(ms)
-     * @return energy used
-     */
-    public int getEnergyUsed () {
-        return mEnergyUsed;
-    }
-
-    public void setEnergyUsed(int energyUsed) {
-        mEnergyUsed = energyUsed;
-    }
-
-    /**
-     * @return if the record is valid
+     * @return {@code true} if this {@link ModemActivityInfo} record is valid,
+     * {@code false} otherwise.
+     *
+     * @hide
      */
     public boolean isValid() {
-        for (int txVal : getTxTimeMillis()) {
-            if(txVal < 0) {
+        for (TransmitPower powerInfo : getTransmitPowerInfo()) {
+            if(powerInfo.getTimeInMillis() < 0) {
                 return false;
             }
         }
 
         return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
-                && (getRxTimeMillis() >= 0) && (getEnergyUsed() >= 0) && !isEmpty());
+                && (getReceiveTimeMillis() >= 0) && !isEmpty());
     }
 
     private boolean isEmpty() {
-        for (int txVal : getTxTimeMillis()) {
-            if(txVal != 0) {
+        for (TransmitPower txVal : getTransmitPowerInfo()) {
+            if(txVal.getTimeInMillis() != 0) {
                 return false;
             }
         }
 
         return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
-                && (getRxTimeMillis() == 0) && (getEnergyUsed() == 0));
+                && (getReceiveTimeMillis() == 0));
+    }
+
+    /**
+     * Transmit power Information, including the power range in dbm and the total time (in ms) where
+     * the transmitter is active/awake for this power range.
+     * e.g, range: 0dbm(lower) ~ 5dbm(upper)
+     *      time: 5ms
+     */
+    public class TransmitPower {
+        private int mTimeInMillis;
+        private Range<Integer> mPowerRangeInDbm;
+        /** @hide */
+        public TransmitPower(@NonNull Range<Integer> range, int time) {
+            this.mTimeInMillis = time;
+            this.mPowerRangeInDbm = range;
+        }
+
+        /**
+         * @return the total time in ms where the transmitter is active/wake for this power range
+         * {@link #getPowerRangeInDbm()}.
+         */
+        public int getTimeInMillis() {
+            return mTimeInMillis;
+        }
+
+        /**
+         * @return the power range in dbm. e.g, range: 0dbm(lower) ~ 5dbm(upper)
+         */
+        @NonNull
+        public Range<Integer> getPowerRangeInDbm() {
+            return mPowerRangeInDbm;
+        }
+
+        @Override
+        public String toString() {
+            return "TransmitPower{"
+                + " mTimeInMillis=" + mTimeInMillis
+                + " mPowerRangeInDbm={" + mPowerRangeInDbm.getLower()
+                + "," + mPowerRangeInDbm.getUpper()
+                + "}}";
+        }
     }
 }
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index bbf746fc..fc717e7 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -24,8 +24,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.TransportType;
-
 import android.telephony.Annotation.NetworkType;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -90,7 +90,7 @@
      * Dual Connectivity(EN-DC).
      * @hide
      */
-    public static final int NR_STATE_NONE = -1;
+    public static final int NR_STATE_NONE = 0;
 
     /**
      * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 17b7963f..8a75831 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,12 +29,13 @@
 /**
  * Define capability of a modem group. That is, the capabilities
  * are shared between those modems defined by list of modem IDs.
- * @hide
  */
-public class PhoneCapability implements Parcelable {
+public final class PhoneCapability implements Parcelable {
     // Hardcoded default DSDS capability.
+    /** @hide */
     public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
     // Hardcoded default Single SIM single standby capability.
+    /** @hide */
     public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
 
     static {
@@ -48,13 +51,18 @@
         logicalModemList.add(modemInfo1);
         DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
     }
-
+    /** @hide */
     public final int maxActiveVoiceCalls;
+    /** @hide */
     public final int maxActiveData;
+    /** @hide */
     public final int max5G;
+    /** @hide */
     public final boolean validationBeforeSwitchSupported;
+    /** @hide */
     public final List<ModemInfo> logicalModemList;
 
+    /** @hide */
     public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
             List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) {
         this.maxActiveVoiceCalls = maxActiveVoiceCalls;
@@ -116,7 +124,7 @@
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+    public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
         dest.writeInt(maxActiveVoiceCalls);
         dest.writeInt(maxActiveData);
         dest.writeInt(max5G);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 4a1bc1f..67afa7d 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -16,8 +16,6 @@
 
 package android.telephony;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -31,9 +29,9 @@
 import android.location.CountryDetector;
 import android.net.Uri;
 import android.os.PersistableBundle;
-import android.os.SystemProperties;
 import android.provider.Contacts;
 import android.provider.ContactsContract;
+import android.sysprop.TelephonyProperties;
 import android.telecom.PhoneAccount;
 import android.text.Editable;
 import android.text.Spannable;
@@ -2659,7 +2657,7 @@
             ps = NANP_IDP_STRING;
         } else {
             // in case, there is no IDD is found, we shouldn't convert it.
-            ps = SystemProperties.get(PROPERTY_OPERATOR_IDP_STRING, PLUS_SIGN_STRING);
+            ps = TelephonyProperties.operator_idp_string().orElse(PLUS_SIGN_STRING);
         }
         return ps;
     }
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index 9f75332..bfa6326 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,19 +16,18 @@
 
 package android.telephony;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.Annotation.DisconnectCauses;
 import android.telephony.Annotation.PreciseCallStates;
+import android.telephony.Annotation.PreciseDisconnectCauses;
 import android.telephony.DisconnectCause;
 import android.telephony.PreciseDisconnectCause;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 
 /**
@@ -73,19 +72,26 @@
     private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
     private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
     private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
-    private int mDisconnectCause = DisconnectCause.NOT_VALID;
-    private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+    private @DisconnectCauses int mDisconnectCause = DisconnectCause.NOT_VALID;
+    private @PreciseDisconnectCauses int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
 
     /**
-     * Constructor
+     * Construct PreciseCallState with parameters
+     *
+     * @param ringingCall ring call state
+     * @param foregroundCall foreground call state
+     * @param backgroundCall background call state
+     * @param disconnectCause disconnect cause
+     * @param preciseDisconnectCause precise disconnect cause
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public PreciseCallState(@PreciseCallStates int ringingCall,
                             @PreciseCallStates int foregroundCall,
-                            @PreciseCallStates int backgroundCall, int disconnectCause,
-                            int preciseDisconnectCause) {
+                            @PreciseCallStates int backgroundCall,
+                            @DisconnectCauses int disconnectCause,
+                            @PreciseDisconnectCauses int preciseDisconnectCause) {
         mRingingCallState = ringingCall;
         mForegroundCallState = foregroundCall;
         mBackgroundCallState = backgroundCall;
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 257d634..78ad5c5 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -19,8 +19,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.LinkProperties;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.ApnType;
@@ -29,6 +31,8 @@
 import android.telephony.Annotation.NetworkType;
 import android.telephony.data.ApnSetting;
 
+import dalvik.system.VMRuntime;
+
 import java.util.Objects;
 
 
@@ -46,35 +50,62 @@
  *   <li>Data connection fail cause.
  * </ul>
  *
- * @hide
  */
-@SystemApi
 public final class PreciseDataConnectionState implements Parcelable {
 
     private @DataState int mState = TelephonyManager.DATA_UNKNOWN;
     private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
     private @DataFailureCause int mFailCause = DataFailCause.NONE;
-    private @ApnType int mAPNTypes = ApnSetting.TYPE_NONE;
-    private String mAPN = "";
+    private @ApnType int mApnTypes = ApnSetting.TYPE_NONE;
+    private String mApn = "";
     private LinkProperties mLinkProperties = null;
+    private ApnSetting mApnSetting = null;
 
     /**
      * Constructor
      *
+     * @deprecated this constructor has been superseded and should not be used.
      * @hide
      */
-    @UnsupportedAppUsage
+    @TestApi
+    @Deprecated
+    @UnsupportedAppUsage // (maxTargetSdk = Build.VERSION_CODES.Q)
+    // FIXME: figure out how to remove the UnsupportedAppUsage and delete this constructor
     public PreciseDataConnectionState(@DataState int state,
                                       @NetworkType int networkType,
-                                      @ApnType int apnTypes, String apn,
-                                      LinkProperties linkProperties,
+                                      @ApnType int apnTypes, @NonNull String apn,
+                                      @Nullable LinkProperties linkProperties,
                                       @DataFailureCause int failCause) {
+        this(state, networkType, apnTypes, apn, linkProperties, failCause, null);
+    }
+
+
+    /**
+     * Constructor
+     *
+     * @param state the state of the data connection
+     * @param networkType the access network that is/would carry this data connection
+     * @param apnTypes the APN types that this data connection carries
+     * @param apnSetting if there is a valid APN for this Data Connection, then the APN Settings;
+     *        if there is no valid APN setting for the specific type, then this will be null
+     * @param linkProperties if the data connection is connected, the properties of the connection
+     * @param failCause in case a procedure related to this data connection fails, a non-zero error
+     *        code indicating the cause of the failure.
+     * @hide
+     */
+    public PreciseDataConnectionState(@DataState int state,
+                                      @NetworkType int networkType,
+                                      @ApnType int apnTypes, @NonNull String apn,
+                                      @Nullable LinkProperties linkProperties,
+                                      @DataFailureCause int failCause,
+                                      @Nullable ApnSetting apnSetting) {
         mState = state;
         mNetworkType = networkType;
-        mAPNTypes = apnTypes;
-        mAPN = apn;
+        mApnTypes = apnTypes;
+        mApn = apn;
         mLinkProperties = linkProperties;
         mFailCause = failCause;
+        mApnSetting = apnSetting;
     }
 
     /**
@@ -93,76 +124,160 @@
     private PreciseDataConnectionState(Parcel in) {
         mState = in.readInt();
         mNetworkType = in.readInt();
-        mAPNTypes = in.readInt();
-        mAPN = in.readString();
-        mLinkProperties = (LinkProperties)in.readParcelable(null);
+        mApnTypes = in.readInt();
+        mApn = in.readString();
+        mLinkProperties = (LinkProperties) in.readParcelable(null);
         mFailCause = in.readInt();
+        mApnSetting = (ApnSetting) in.readParcelable(null);
     }
 
     /**
      * Returns the state of data connection that supported the apn types returned by
      * {@link #getDataConnectionApnTypeBitMask()}
+     *
+     * @deprecated use {@link #getState()}
+     * @hide
      */
+    @Deprecated
+    @SystemApi
     public @DataState int getDataConnectionState() {
+        if (mState == TelephonyManager.DATA_DISCONNECTING
+                && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+            return TelephonyManager.DATA_CONNECTED;
+        }
+
+        return mState;
+    }
+
+    /**
+     * Returns the high-level state of this data connection.
+     */
+    public @DataState int getState() {
         return mState;
     }
 
     /**
      * Returns the network type associated with this data connection.
+     *
+     * @deprecated use {@link getNetworkType()}
      * @hide
      */
+    @Deprecated
+    @SystemApi
     public @NetworkType int getDataConnectionNetworkType() {
         return mNetworkType;
     }
 
     /**
-     * Returns the data connection APN types supported by this connection and triggers
-     * {@link PreciseDataConnectionState} change.
+     * Returns the network type associated with this data connection.
+     *
+     * Return the current/latest (radio) bearer technology that carries this data connection.
+     * For a variety of reasons, the network type can change during the life of the data
+     * connection, and this information is not reliable unless the physical link is currently
+     * active; (there is currently no mechanism to know whether the physical link is active at
+     * any given moment). Thus, this value is generally correct but may not be relied-upon to
+     * represent the status of the radio bearer at any given moment.
      */
-    public @ApnType int getDataConnectionApnTypeBitMask() {
-        return mAPNTypes;
+    public @NetworkType int getNetworkType() {
+        return mNetworkType;
     }
 
     /**
-     * Returns APN {@link ApnSetting} of this data connection.
+     * Returns the APN types mapped to this data connection.
+     *
+     * @deprecated use {@link #getApnSetting()}
+     * @hide
      */
-    @Nullable
+    @Deprecated
+    @SystemApi
+    public @ApnType int getDataConnectionApnTypeBitMask() {
+        return mApnTypes;
+    }
+
+    /**
+     * Returns APN of this data connection.
+     *
+     * @deprecated use {@link #getApnSetting()}
+     * @hide
+     */
+    @NonNull
+    @SystemApi
+    @Deprecated
     public String getDataConnectionApn() {
-        return mAPN;
+        return mApn;
     }
 
     /**
      * Get the properties of the network link {@link LinkProperties}.
+     *
+     * @deprecated use {@link #getLinkProperties()}
      * @hide
      */
-    @UnsupportedAppUsage
+    @Deprecated
+    @SystemApi
+    @Nullable
     public LinkProperties getDataConnectionLinkProperties() {
         return mLinkProperties;
     }
 
     /**
-     * Returns data connection fail cause, in case there was a failure.
+     * Get the properties of the network link {@link LinkProperties}.
      */
-    public @Annotation.DataFailureCause int getDataConnectionFailCause() {
+    @Nullable
+    public LinkProperties getLinkProperties() {
+        return mLinkProperties;
+    }
+
+    /**
+     * Returns the cause code generated by the most recent state change.
+     *
+     * @deprecated use {@link #getLastCauseCode()}
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public int getDataConnectionFailCause() {
         return mFailCause;
     }
 
+    /**
+     * Returns the cause code generated by the most recent state change.
+     *
+     * Return the cause code for the most recent change in {@link #getState}. In the event of an
+     * error, this cause code will be non-zero.
+     */
+    // FIXME(b144774287): some of these cause codes should have a prescribed meaning.
+    public int getLastCauseCode() {
+        return mFailCause;
+    }
+
+    /**
+     * Return the APN Settings for this data connection.
+     *
+     * Returns the ApnSetting that was used to configure this data connection.
+     */
+    // FIXME: This shouldn't be nullable; update once the ApnSetting is supplied correctly
+    @Nullable ApnSetting getApnSetting() {
+        return mApnSetting;
+    }
+
     @Override
     public int describeContents() {
         return 0;
     }
 
     @Override
-    public void writeToParcel(Parcel out, int flags) {
+    public void writeToParcel(@NonNull Parcel out, int flags) {
         out.writeInt(mState);
         out.writeInt(mNetworkType);
-        out.writeInt(mAPNTypes);
-        out.writeString(mAPN);
+        out.writeInt(mApnTypes);
+        out.writeString(mApn);
         out.writeParcelable(mLinkProperties, flags);
         out.writeInt(mFailCause);
+        out.writeParcelable(mApnSetting, flags);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<PreciseDataConnectionState> CREATOR
+    public static final @NonNull Parcelable.Creator<PreciseDataConnectionState> CREATOR
             = new Parcelable.Creator<PreciseDataConnectionState>() {
 
         public PreciseDataConnectionState createFromParcel(Parcel in) {
@@ -176,8 +291,8 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mState, mNetworkType, mAPNTypes, mAPN, mLinkProperties,
-                mFailCause);
+        return Objects.hash(mState, mNetworkType, mApnTypes, mApn, mLinkProperties,
+                mFailCause, mApnSetting);
     }
 
     @Override
@@ -188,11 +303,12 @@
         }
 
         PreciseDataConnectionState other = (PreciseDataConnectionState) obj;
-        return Objects.equals(mAPN, other.mAPN) && mAPNTypes == other.mAPNTypes
+        return Objects.equals(mApn, other.mApn) && mApnTypes == other.mApnTypes
                 && mFailCause == other.mFailCause
                 && Objects.equals(mLinkProperties, other.mLinkProperties)
                 && mNetworkType == other.mNetworkType
-                && mState == other.mState;
+                && mState == other.mState
+                && Objects.equals(mApnSetting, other.mApnSetting);
     }
 
     @NonNull
@@ -202,10 +318,11 @@
 
         sb.append("Data Connection state: " + mState);
         sb.append(", Network type: " + mNetworkType);
-        sb.append(", APN types: " + ApnSetting.getApnTypesStringFromBitmask(mAPNTypes));
-        sb.append(", APN: " + mAPN);
+        sb.append(", APN types: " + ApnSetting.getApnTypesStringFromBitmask(mApnTypes));
+        sb.append(", APN: " + mApn);
         sb.append(", Link properties: " + mLinkProperties);
         sb.append(", Fail cause: " + DataFailCause.toString(mFailCause));
+        sb.append(", Apn Setting: " + mApnSetting);
 
         return sb.toString();
     }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1e601cf..1014571 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -30,7 +30,6 @@
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.Annotation.NetworkType;
-import android.telephony.Annotation.RilRadioTechnology;
 import android.telephony.NetworkRegistrationInfo.Domain;
 import android.telephony.NetworkRegistrationInfo.NRState;
 import android.text.TextUtils;
@@ -102,7 +101,7 @@
      * Indicates frequency range is unknown.
      * @hide
      */
-    public static final int FREQUENCY_RANGE_UNKNOWN = -1;
+    public static final int FREQUENCY_RANGE_UNKNOWN = 0;
 
     /**
      * Indicates the frequency range is below 1GHz.
@@ -221,6 +220,36 @@
     public static final int  RIL_RADIO_TECHNOLOGY_NR = 20;
 
     /**
+     * RIL Radio Annotation
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
+        ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
+        ServiceState.RIL_RADIO_TECHNOLOGY_GPRS,
+        ServiceState.RIL_RADIO_TECHNOLOGY_EDGE,
+        ServiceState.RIL_RADIO_TECHNOLOGY_UMTS,
+        ServiceState.RIL_RADIO_TECHNOLOGY_IS95A,
+        ServiceState.RIL_RADIO_TECHNOLOGY_IS95B,
+        ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT,
+        ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0,
+        ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A,
+        ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA,
+        ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA,
+        ServiceState.RIL_RADIO_TECHNOLOGY_HSPA,
+        ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B,
+        ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD,
+        ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
+        ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP,
+        ServiceState.RIL_RADIO_TECHNOLOGY_GSM,
+        ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA,
+        ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
+        ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
+        ServiceState.RIL_RADIO_TECHNOLOGY_NR})
+    public @interface RilRadioTechnology {}
+
+
+    /**
      * The number of the radio technologies.
      */
     private static final int NEXT_RIL_RADIO_TECHNOLOGY = 21;
@@ -278,12 +307,9 @@
      */
     public static final int UNKNOWN_ID = -1;
 
-    private String mVoiceOperatorAlphaLong;
-    private String mVoiceOperatorAlphaShort;
-    private String mVoiceOperatorNumeric;
-    private String mDataOperatorAlphaLong;
-    private String mDataOperatorAlphaShort;
-    private String mDataOperatorNumeric;
+    private String mOperatorAlphaLong;
+    private String mOperatorAlphaShort;
+    private String mOperatorNumeric;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private boolean mIsManualNetworkSelection;
 
@@ -379,12 +405,9 @@
     protected void copyFrom(ServiceState s) {
         mVoiceRegState = s.mVoiceRegState;
         mDataRegState = s.mDataRegState;
-        mVoiceOperatorAlphaLong = s.mVoiceOperatorAlphaLong;
-        mVoiceOperatorAlphaShort = s.mVoiceOperatorAlphaShort;
-        mVoiceOperatorNumeric = s.mVoiceOperatorNumeric;
-        mDataOperatorAlphaLong = s.mDataOperatorAlphaLong;
-        mDataOperatorAlphaShort = s.mDataOperatorAlphaShort;
-        mDataOperatorNumeric = s.mDataOperatorNumeric;
+        mOperatorAlphaLong = s.mOperatorAlphaLong;
+        mOperatorAlphaShort = s.mOperatorAlphaShort;
+        mOperatorNumeric = s.mOperatorNumeric;
         mIsManualNetworkSelection = s.mIsManualNetworkSelection;
         mCssIndicator = s.mCssIndicator;
         mNetworkId = s.mNetworkId;
@@ -418,12 +441,9 @@
     public ServiceState(Parcel in) {
         mVoiceRegState = in.readInt();
         mDataRegState = in.readInt();
-        mVoiceOperatorAlphaLong = in.readString();
-        mVoiceOperatorAlphaShort = in.readString();
-        mVoiceOperatorNumeric = in.readString();
-        mDataOperatorAlphaLong = in.readString();
-        mDataOperatorAlphaShort = in.readString();
-        mDataOperatorNumeric = in.readString();
+        mOperatorAlphaLong = in.readString();
+        mOperatorAlphaShort = in.readString();
+        mOperatorNumeric = in.readString();
         mIsManualNetworkSelection = in.readInt() != 0;
         mCssIndicator = (in.readInt() != 0);
         mNetworkId = in.readInt();
@@ -448,12 +468,9 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mVoiceRegState);
         out.writeInt(mDataRegState);
-        out.writeString(mVoiceOperatorAlphaLong);
-        out.writeString(mVoiceOperatorAlphaShort);
-        out.writeString(mVoiceOperatorNumeric);
-        out.writeString(mDataOperatorAlphaLong);
-        out.writeString(mDataOperatorAlphaShort);
-        out.writeString(mDataOperatorNumeric);
+        out.writeString(mOperatorAlphaLong);
+        out.writeString(mOperatorAlphaShort);
+        out.writeString(mOperatorNumeric);
         out.writeInt(mIsManualNetworkSelection ? 1 : 0);
         out.writeInt(mCssIndicator ? 1 : 0);
         out.writeInt(mNetworkId);
@@ -691,7 +708,7 @@
      * @return long name of operator, null if unregistered or unknown
      */
     public String getOperatorAlphaLong() {
-        return mVoiceOperatorAlphaLong;
+        return mOperatorAlphaLong;
     }
 
     /**
@@ -699,18 +716,10 @@
      * @return long name of operator
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+            publicAlternatives = "Use {@link #getOperatorAlphaLong} instead.")
     public String getVoiceOperatorAlphaLong() {
-        return mVoiceOperatorAlphaLong;
-    }
-
-    /**
-     * Get current registered data network operator name in long alphanumeric format.
-     * @return long name of voice operator
-     * @hide
-     */
-    public String getDataOperatorAlphaLong() {
-        return mDataOperatorAlphaLong;
+        return mOperatorAlphaLong;
     }
 
     /**
@@ -721,7 +730,7 @@
      * @return short name of operator, null if unregistered or unknown
      */
     public String getOperatorAlphaShort() {
-        return mVoiceOperatorAlphaShort;
+        return mOperatorAlphaShort;
     }
 
     /**
@@ -729,9 +738,10 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+            publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
     public String getVoiceOperatorAlphaShort() {
-        return mVoiceOperatorAlphaShort;
+        return mOperatorAlphaShort;
     }
 
     /**
@@ -739,9 +749,10 @@
      * @return short name of operator, null if unregistered or unknown
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+            publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
     public String getDataOperatorAlphaShort() {
-        return mDataOperatorAlphaShort;
+        return mOperatorAlphaShort;
     }
 
     /**
@@ -755,11 +766,11 @@
      * @hide
      */
     public String getOperatorAlpha() {
-        if (TextUtils.isEmpty(mVoiceOperatorAlphaLong)) {
-            return mVoiceOperatorAlphaShort;
+        if (TextUtils.isEmpty(mOperatorAlphaLong)) {
+            return mOperatorAlphaShort;
         }
 
-        return mVoiceOperatorAlphaLong;
+        return mOperatorAlphaLong;
     }
 
     /**
@@ -775,7 +786,7 @@
      * {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}.
      */
     public String getOperatorNumeric() {
-        return mVoiceOperatorNumeric;
+        return mOperatorNumeric;
     }
 
     /**
@@ -785,7 +796,7 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getVoiceOperatorNumeric() {
-        return mVoiceOperatorNumeric;
+        return mOperatorNumeric;
     }
 
     /**
@@ -793,9 +804,10 @@
      * @return numeric format of operator, null if unregistered or unknown
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
+            publicAlternatives = "Use {@link #getOperatorNumeric} instead.")
     public String getDataOperatorNumeric() {
-        return mDataOperatorNumeric;
+        return mOperatorNumeric;
     }
 
     /**
@@ -815,12 +827,9 @@
                     mDataRegState,
                     mChannelNumber,
                     Arrays.hashCode(mCellBandwidths),
-                    mVoiceOperatorAlphaLong,
-                    mVoiceOperatorAlphaShort,
-                    mVoiceOperatorNumeric,
-                    mDataOperatorAlphaLong,
-                    mDataOperatorAlphaShort,
-                    mDataOperatorNumeric,
+                    mOperatorAlphaLong,
+                    mOperatorAlphaShort,
+                    mOperatorNumeric,
                     mIsManualNetworkSelection,
                     mCssIndicator,
                     mNetworkId,
@@ -850,12 +859,9 @@
                     && mIsManualNetworkSelection == s.mIsManualNetworkSelection
                     && mChannelNumber == s.mChannelNumber
                     && Arrays.equals(mCellBandwidths, s.mCellBandwidths)
-                    && equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
-                    && equalsHandlesNulls(mVoiceOperatorAlphaShort, s.mVoiceOperatorAlphaShort)
-                    && equalsHandlesNulls(mVoiceOperatorNumeric, s.mVoiceOperatorNumeric)
-                    && equalsHandlesNulls(mDataOperatorAlphaLong, s.mDataOperatorAlphaLong)
-                    && equalsHandlesNulls(mDataOperatorAlphaShort, s.mDataOperatorAlphaShort)
-                    && equalsHandlesNulls(mDataOperatorNumeric, s.mDataOperatorNumeric)
+                    && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong)
+                    && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort)
+                    && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric)
                     && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
                     && equalsHandlesNulls(mNetworkId, s.mNetworkId)
                     && equalsHandlesNulls(mSystemId, s.mSystemId)
@@ -964,7 +970,7 @@
                 rtString = "LTE_CA";
                 break;
             case RIL_RADIO_TECHNOLOGY_NR:
-                rtString = "LTE_NR";
+                rtString = "NR_SA";
                 break;
             default:
                 rtString = "Unexpected";
@@ -1007,10 +1013,8 @@
                     .append(", mChannelNumber=").append(mChannelNumber)
                     .append(", duplexMode()=").append(getDuplexMode())
                     .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
-                    .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
-                    .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
-                    .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
-                    .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
+                    .append(", mOperatorAlphaLong=").append(mOperatorAlphaLong)
+                    .append(", mOperatorAlphaShort=").append(mOperatorAlphaShort)
                     .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
                     .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
                     .append(", getRilVoiceRadioTechnology=").append(getRilVoiceRadioTechnology())
@@ -1040,12 +1044,9 @@
         mDataRegState = STATE_OUT_OF_SERVICE;
         mChannelNumber = -1;
         mCellBandwidths = new int[0];
-        mVoiceOperatorAlphaLong = null;
-        mVoiceOperatorAlphaShort = null;
-        mVoiceOperatorNumeric = null;
-        mDataOperatorAlphaLong = null;
-        mDataOperatorAlphaShort = null;
-        mDataOperatorNumeric = null;
+        mOperatorAlphaLong = null;
+        mOperatorAlphaShort = null;
+        mOperatorNumeric = null;
         mIsManualNetworkSelection = false;
         mCssIndicator = false;
         mNetworkId = -1;
@@ -1204,26 +1205,9 @@
     }
 
     public void setOperatorName(String longName, String shortName, String numeric) {
-        mVoiceOperatorAlphaLong = longName;
-        mVoiceOperatorAlphaShort = shortName;
-        mVoiceOperatorNumeric = numeric;
-        mDataOperatorAlphaLong = longName;
-        mDataOperatorAlphaShort = shortName;
-        mDataOperatorNumeric = numeric;
-    }
-
-    /** @hide */
-    public void setVoiceOperatorName(String longName, String shortName, String numeric) {
-        mVoiceOperatorAlphaLong = longName;
-        mVoiceOperatorAlphaShort = shortName;
-        mVoiceOperatorNumeric = numeric;
-    }
-
-    /** @hide */
-    public void setDataOperatorName(String longName, String shortName, String numeric) {
-        mDataOperatorAlphaLong = longName;
-        mDataOperatorAlphaShort = shortName;
-        mDataOperatorNumeric = numeric;
+        mOperatorAlphaLong = longName;
+        mOperatorAlphaShort = shortName;
+        mOperatorNumeric = numeric;
     }
 
     /**
@@ -1233,19 +1217,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public void setOperatorAlphaLong(String longName) {
-        mVoiceOperatorAlphaLong = longName;
-        mDataOperatorAlphaLong = longName;
-    }
-
-    /** @hide */
-    public void setVoiceOperatorAlphaLong(String longName) {
-        mVoiceOperatorAlphaLong = longName;
-    }
-
-    /** @hide */
-    public void setDataOperatorAlphaLong(String longName) {
-        mDataOperatorAlphaLong = longName;
+    public void setOperatorAlphaLong(@Nullable String longName) {
+        mOperatorAlphaLong = longName;
     }
 
     public void setIsManualSelection(boolean isManual) {
@@ -1293,12 +1266,12 @@
         m.putInt("dataRegState", mDataRegState);
         m.putInt("dataRoamingType", getDataRoamingType());
         m.putInt("voiceRoamingType", getVoiceRoamingType());
-        m.putString("operator-alpha-long", mVoiceOperatorAlphaLong);
-        m.putString("operator-alpha-short", mVoiceOperatorAlphaShort);
-        m.putString("operator-numeric", mVoiceOperatorNumeric);
-        m.putString("data-operator-alpha-long", mDataOperatorAlphaLong);
-        m.putString("data-operator-alpha-short", mDataOperatorAlphaShort);
-        m.putString("data-operator-numeric", mDataOperatorNumeric);
+        m.putString("operator-alpha-long", mOperatorAlphaLong);
+        m.putString("operator-alpha-short", mOperatorAlphaShort);
+        m.putString("operator-numeric", mOperatorNumeric);
+        m.putString("data-operator-alpha-long", mOperatorAlphaLong);
+        m.putString("data-operator-alpha-short", mOperatorAlphaShort);
+        m.putString("data-operator-numeric", mOperatorNumeric);
         m.putBoolean("manual", mIsManualNetworkSelection);
         m.putInt("radioTechnology", getRilVoiceRadioTechnology());
         m.putInt("dataRadioTechnology", getRadioTechnology());
@@ -1535,8 +1508,9 @@
                 return AccessNetworkType.CDMA2000;
             case RIL_RADIO_TECHNOLOGY_LTE:
             case RIL_RADIO_TECHNOLOGY_LTE_CA:
-            case RIL_RADIO_TECHNOLOGY_NR:
                 return AccessNetworkType.EUTRAN;
+            case RIL_RADIO_TECHNOLOGY_NR:
+                return AccessNetworkType.NGRAN;
             case RIL_RADIO_TECHNOLOGY_IWLAN:
                 return AccessNetworkType.IWLAN;
             case RIL_RADIO_TECHNOLOGY_UNKNOWN:
@@ -1933,12 +1907,9 @@
         }
         if (!removeCoarseLocation) return state;
 
-        state.mDataOperatorAlphaLong = null;
-        state.mDataOperatorAlphaShort = null;
-        state.mDataOperatorNumeric = null;
-        state.mVoiceOperatorAlphaLong = null;
-        state.mVoiceOperatorAlphaShort = null;
-        state.mVoiceOperatorNumeric = null;
+        state.mOperatorAlphaLong = null;
+        state.mOperatorAlphaShort = null;
+        state.mOperatorNumeric = null;
 
         return state;
     }
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 9aafc1b..aac56c0 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -332,17 +332,16 @@
     /**
      * {@link Parcelable.Creator}
      *
-     * @hide
      */
-    @UnsupportedAppUsage
-    public static final @android.annotation.NonNull Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
-        public SignalStrength createFromParcel(Parcel in) {
-            return new SignalStrength(in);
-        }
+    public static final @android.annotation.NonNull Parcelable.Creator<SignalStrength> CREATOR =
+            new Parcelable.Creator<SignalStrength>() {
+                public SignalStrength createFromParcel(Parcel in) {
+                    return new SignalStrength(in);
+                }
 
-        public SignalStrength[] newArray(int size) {
-            return new SignalStrength[size];
-        }
+                public SignalStrength[] newArray(int size) {
+                    return new SignalStrength[size];
+                }
     };
 
     /**
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
new file mode 100644
index 0000000..f6f6d75
--- /dev/null
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Defines the threshold value of the signal strength.
+ * @hide
+ */
+public class SignalThresholdInfo implements Parcelable {
+    /**
+     * Received Signal Strength Indication.
+     * Range: -113 dBm and -51 dBm
+     * Used RAN: GERAN, CDMA2000
+     * Reference: 3GPP TS 27.007 section 8.5.
+     */
+    public static final int SIGNAL_RSSI = 1;
+
+    /**
+     * Received Signal Code Power.
+     * Range: -120 dBm to -25 dBm;
+     * Used RAN: UTRAN
+     * Reference: 3GPP TS 25.123, section 9.1.1.1
+     */
+    public static final int SIGNAL_RSCP = 2;
+
+    /**
+     * Reference Signal Received Power.
+     * Range: -140 dBm to -44 dBm;
+     * Used RAN: EUTRAN
+     * Reference: 3GPP TS 36.133 9.1.4
+     */
+    public static final int SIGNAL_RSRP = 3;
+
+    /**
+     * Reference Signal Received Quality
+     * Range: -20 dB to -3 dB;
+     * Used RAN: EUTRAN
+     * Reference: 3GPP TS 36.133 9.1.7
+     */
+    public static final int SIGNAL_RSRQ = 4;
+
+    /**
+     * Reference Signal Signal to Noise Ratio
+     * Range: -20 dB to 30 dB;
+     * Used RAN: EUTRAN
+     */
+    public static final int SIGNAL_RSSNR = 5;
+
+    /**
+     * 5G SS reference signal received power.
+     * Range: -140 dBm to -44 dBm.
+     * Used RAN: NGRAN
+     * Reference: 3GPP TS 38.215.
+     */
+    public static final int SIGNAL_SSRSRP = 6;
+
+    /**
+     * 5G SS reference signal received quality.
+     * Range: -20 dB to -3 dB.
+     * Used RAN: NGRAN
+     * Reference: 3GPP TS 38.215.
+     */
+    public static final int SIGNAL_SSRSRQ = 7;
+
+    /**
+     * 5G SS signal-to-noise and interference ratio.
+     * Range: -23 dB to 40 dB
+     * Used RAN: NGRAN
+     * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
+     */
+    public static final int SIGNAL_SSSINR = 8;
+
+    /** @hide */
+    @IntDef(prefix = { "SIGNAL_" }, value = {
+        SIGNAL_RSSI,
+        SIGNAL_RSCP,
+        SIGNAL_RSRP,
+        SIGNAL_RSRQ,
+        SIGNAL_RSSNR,
+        SIGNAL_SSRSRP,
+        SIGNAL_SSRSRQ,
+        SIGNAL_SSSINR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SignalMeasurementType {}
+
+    @SignalMeasurementType
+    private int mSignalMeasurement;
+
+    /**
+     * A hysteresis time in milliseconds to prevent flapping.
+     * A value of 0 disables hysteresis
+     */
+    private int mHysteresisMs;
+
+    /**
+     * An interval in dB defining the required magnitude change between reports.
+     * hysteresisDb must be smaller than the smallest threshold delta.
+     * An interval value of 0 disables hysteresis.
+     */
+    private int mHysteresisDb;
+
+    /**
+     * List of threshold values.
+     * Range and unit must reference specific SignalMeasurementType
+     * The threshold values for which to apply criteria.
+     * A vector size of 0 disables the use of thresholds for reporting.
+     */
+    private int[] mThresholds = null;
+
+    /**
+     * {@code true} means modem must trigger the report based on the criteria;
+     * {@code false} means modem must not trigger the report based on the criteria.
+     */
+    private boolean mIsEnabled = true;
+
+    /**
+     * Indicates the hysteresisMs is disabled.
+     */
+    public static final int HYSTERESIS_MS_DISABLED = 0;
+
+    /**
+     * Indicates the hysteresisDb is disabled.
+     */
+    public static final int HYSTERESIS_DB_DISABLED = 0;
+
+    /**
+     * Constructor
+     *
+     * @param signalMeasurement Signal Measurement Type
+     * @param hysteresisMs hysteresisMs
+     * @param hysteresisDb hysteresisDb
+     * @param thresholds threshold value
+     * @param isEnabled isEnabled
+     */
+    public SignalThresholdInfo(@SignalMeasurementType int signalMeasurement,
+            int hysteresisMs, int hysteresisDb, @NonNull int [] thresholds, boolean isEnabled) {
+        mSignalMeasurement = signalMeasurement;
+        mHysteresisMs = hysteresisMs < 0 ? HYSTERESIS_MS_DISABLED : hysteresisMs;
+        mHysteresisDb = hysteresisDb < 0 ? HYSTERESIS_DB_DISABLED : hysteresisDb;
+        mThresholds = thresholds == null ? null : thresholds.clone();
+        mIsEnabled = isEnabled;
+    }
+
+    public @SignalMeasurementType int getSignalMeasurement() {
+        return mSignalMeasurement;
+    }
+
+    public int getHysteresisMs() {
+        return mHysteresisMs;
+    }
+
+    public int getHysteresisDb() {
+        return mHysteresisDb;
+    }
+
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    public int[] getThresholds() {
+        return mThresholds == null ? null : mThresholds.clone();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mSignalMeasurement);
+        out.writeInt(mHysteresisMs);
+        out.writeInt(mHysteresisDb);
+        out.writeIntArray(mThresholds);
+        out.writeBoolean(mIsEnabled);
+    }
+
+    private SignalThresholdInfo(Parcel in) {
+        mSignalMeasurement = in.readInt();
+        mHysteresisMs = in.readInt();
+        mHysteresisDb = in.readInt();
+        mThresholds = in.createIntArray();
+        mIsEnabled = in.readBoolean();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (!(o instanceof SignalThresholdInfo)) {
+            return false;
+        }
+
+        SignalThresholdInfo other = (SignalThresholdInfo) o;
+        return mSignalMeasurement == other.mSignalMeasurement
+                && mHysteresisMs == other.mHysteresisMs
+                && mHysteresisDb == other.mHysteresisDb
+                && Arrays.equals(mThresholds, other.mThresholds)
+                && mIsEnabled == other.mIsEnabled;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mSignalMeasurement, mHysteresisMs, mHysteresisDb, mThresholds, mIsEnabled);
+    }
+
+    public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
+            new Parcelable.Creator<SignalThresholdInfo>() {
+                @Override
+                public SignalThresholdInfo createFromParcel(Parcel in) {
+                    return new SignalThresholdInfo(in);
+                }
+
+                @Override
+                public SignalThresholdInfo[] newArray(int size) {
+                    return new SignalThresholdInfo[size];
+                }
+            };
+
+    @Override
+    public String toString() {
+        return new StringBuilder("SignalThresholdInfo{")
+            .append("mSignalMeasurement=").append(mSignalMeasurement)
+            .append("mHysteresisMs=").append(mSignalMeasurement)
+            .append("mHysteresisDb=").append(mHysteresisDb)
+            .append("mThresholds=").append(Arrays.toString(mThresholds))
+            .append("mIsEnabled=").append(mIsEnabled)
+            .append("}").toString();
+    }
+}
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index fad70d2..045d1eb 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -29,6 +29,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -407,13 +408,17 @@
     }
 
     /**
-     * Get the warning area coordinates information represent by polygons and circles.
-     * @return a list of geometries, {@link Nullable} means there is no coordinate information
-     * associated to this message.
+     * Get the warning area coordinates information represented by polygons and circles.
+     * @return a list of geometries, or an empty list if there is no coordinate information
+     * associated with this message.
      * @hide
      */
-    @Nullable
+    @SystemApi
+    @NonNull
     public List<Geometry> getGeometries() {
+        if (mGeometries == null) {
+            return new ArrayList<>();
+        }
         return mGeometries;
     }
 
@@ -528,7 +533,8 @@
                 + ", priority=" + mPriority
                 + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
                 + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "")
-                + ", maximumWaitingTime = " + mMaximumWaitTimeSec
+                + ", maximumWaitingTime=" + mMaximumWaitTimeSec
+                + ", received time=" + mReceivedTimeMillis
                 + ", slotIndex = " + mSlotIndex
                 + ", geo=" + (mGeometries != null
                 ? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null")
@@ -720,6 +726,6 @@
      * @return {@code True} if this message needs geo-fencing check.
      */
     public boolean needGeoFencingCheck() {
-        return mMaximumWaitTimeSec > 0 && mGeometries != null;
+        return mMaximumWaitTimeSec > 0 && mGeometries != null && !mGeometries.isEmpty();
     }
 }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index daeacf8..3496686 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -31,7 +31,6 @@
 import android.content.pm.PackageManager;
 import android.database.CursorWindow;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -79,11 +78,6 @@
             SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
     private static final Object sLockObject = new Object();
 
-    /** @hide */
-    public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0;
-    /** @hide */
-    public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1;
-
     /** SMS record length from TS 51.011 10.5.3
      * @hide
      */
@@ -2004,6 +1998,27 @@
         }
     }
 
+    /**
+     * Gets the total capacity of SMS storage on RUIM and SIM cards
+     *
+     * @return the total capacity count of SMS on RUIM and SIM cards
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public int getSmsCapacityOnIcc() {
+        int ret = 0;
+        try {
+            ISms iccISms = getISmsService();
+            if (iccISms != null) {
+                ret = iccISms.getSmsCapacityOnIccForSubscriber(getSubscriptionId());
+            }
+        } catch (RemoteException ex) {
+            //ignore it
+        }
+        return ret;
+    }
+
     // see SmsMessage.getStatusOnIcc
 
     /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
@@ -2403,22 +2418,31 @@
     public static final String MESSAGE_STATUS_READ = "read";
 
     /**
-     * Get carrier-dependent configuration values.
+     * Get carrier-dependent MMS configuration values.
      *
      * <p class="note"><strong>Note:</strong> This method is intended for internal use by carrier
-     * applications or the Telephony framework and will never trigger an SMS disambiguation
-     * dialog. If this method is called on a device that has multiple active subscriptions, this
-     * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
-     * default subscription is defined, the subscription ID associated with this message will be
-     * INVALID, which will result in the operation being completed on the subscription associated
-     * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the
-     * operation is performed on the correct subscription.
+     * applications or the Telephony framework and will never trigger an SMS disambiguation dialog.
+     * If this method is called on a device that has multiple active subscriptions, this {@link
+     * SmsManager} instance has been created with {@link #getDefault()}, and no user-defined default
+     * subscription is defined, the subscription ID associated with this message will be INVALID,
+     * which will result in the operation being completed on the subscription associated with
+     * logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation is
+     * performed on the correct subscription.
      * </p>
      *
-     * @return bundle key/values pairs of configuration values
+     * @return the bundle key/values pairs that contains MMS configuration values
      */
+    @Nullable
     public Bundle getCarrierConfigValues() {
-        return MmsManager.getInstance().getCarrierConfigValues(getSubscriptionId());
+        try {
+            ISms iSms = getISmsService();
+            if (iSms != null) {
+                return iSms.getCarrierConfigValuesForSubscriber(getSubscriptionId());
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return null;
     }
 
     /**
@@ -2457,7 +2481,9 @@
         }
     }
 
-    /** callback for providing asynchronous sms messages for financial app. */
+    /**
+     * callback for providing asynchronous sms messages for financial app.
+     */
     public abstract static class FinancialSmsCallback {
         /**
          * Callback to send sms messages back to financial app asynchronously.
@@ -2483,24 +2509,14 @@
      * @param params the parameters to filter SMS messages returned.
      * @param executor the executor on which callback will be invoked.
      * @param callback a callback to receive CursorWindow with SMS messages.
+     *
      */
     @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS)
     public void getSmsMessagesForFinancialApp(
             Bundle params,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull FinancialSmsCallback callback) {
-        try {
-            ISms iccSms = getISmsServiceOrThrow();
-            iccSms.getSmsMessagesForFinancialApp(
-                    getSubscriptionId(), ActivityThread.currentPackageName(), params,
-                    new IFinancialSmsCallback.Stub() {
-                        public void onGetSmsMessagesForFinancialApp(CursorWindow msgs) {
-                            Binder.withCleanCallingIdentity(() -> executor.execute(
-                                    () -> callback.onFinancialSmsMessages(msgs)));
-                        }});
-        } catch (RemoteException ex) {
-            ex.rethrowFromSystemServer();
-        }
+        // This API is not functional and thus removed to avoid future confusion.
     }
 
     /**
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index b705d71..392d3eb 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -344,10 +344,12 @@
      * @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
      *     are counted as single space chars. If false, and if the messageBody contains non-7-bit
      *     encodable characters, length is calculated using a 16-bit encoding.
-     * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+     * @return an int[6] with int[0] being the number of SMS's required, int[1] the number of code
      *     units used, and int[2] is the number of code units remaining until the next message.
      *     int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
-     *     SmsConstants).
+     *     SmsConstants). int[4] is the GSM national language table to use, or 0 for the default
+     *     7-bit alphabet. int[5] The GSM national language shift table to use, or 0 for the default
+     *     7-bit extension table.
      */
     public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
         return calculateLength(msgBody, use7bitOnly, SmsManager.getDefaultSmsSubscriptionId());
@@ -362,10 +364,12 @@
      *     are counted as single space chars. If false, and if the messageBody contains non-7-bit
      *     encodable characters, length is calculated using a 16-bit encoding.
      * @param subId Subscription to take SMS format.
-     * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+     * @return an int[6] with int[0] being the number of SMS's required, int[1] the number of code
      *     units used, and int[2] is the number of code units remaining until the next message.
      *     int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
-     *     SmsConstants).
+     *     SmsConstants). int[4] is the GSM national language table to use, or 0 for the default
+     *     7-bit alphabet. int[5] The GSM national language shift table to use, or 0 for the default
+     *     7-bit extension table.
      * @hide
      */
     public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly, int subId) {
@@ -376,11 +380,13 @@
                                 msgBody, use7bitOnly, true)
                         : com.android.internal.telephony.gsm.SmsMessage.calculateLength(
                                 msgBody, use7bitOnly);
-        int ret[] = new int[4];
+        int[] ret = new int[6];
         ret[0] = ted.msgCount;
         ret[1] = ted.codeUnitCount;
         ret[2] = ted.codeUnitsRemaining;
         ret[3] = ted.codeUnitSize;
+        ret[4] = ted.languageTable;
+        ret[5] = ted.languageShiftTable;
         return ret;
     }
 
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 9eff809..bbde1f4 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -30,7 +30,6 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Typeface;
-import android.os.Build;
 import android.os.Parcel;
 import android.os.ParcelUuid;
 import android.os.Parcelable;
@@ -38,6 +37,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
+import com.android.internal.telephony.util.TelephonyUtils;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -89,8 +90,8 @@
     private int mCarrierId;
 
     /**
-     * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
-     * NAME_SOURCE_USER_INPUT.
+     * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN,
+     * NAME_SOURCE_SIM_PNN, or NAME_SOURCE_USER_INPUT.
      */
     private int mNameSource;
 
@@ -209,6 +210,12 @@
     private int mSubscriptionType;
 
     /**
+     * Whether uicc applications are configured to enable or disable.
+     * By default it's true.
+     */
+    private boolean mAreUiccApplicationsEnabled = true;
+
+    /**
      * @hide
      */
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
@@ -219,7 +226,7 @@
                 roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, -1,
                 false, null, false, TelephonyManager.UNKNOWN_CARRIER_ID,
                 SubscriptionManager.PROFILE_CLASS_DEFAULT,
-                SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null);
+                SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null, true);
     }
 
     /**
@@ -233,7 +240,7 @@
         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
                 roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, -1,
                 isOpportunistic, groupUUID, false, carrierId, profileClass,
-                SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null);
+                SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null, true);
     }
 
     /**
@@ -245,7 +252,8 @@
             @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId,
             boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
             int carrierId, int profileClass, int subType, @Nullable String groupOwner,
-            @Nullable UiccAccessRule[] carrierConfigAccessRules) {
+            @Nullable UiccAccessRule[] carrierConfigAccessRules,
+            boolean areUiccApplicationsEnabled) {
         this.mId = id;
         this.mIccId = iccId;
         this.mSimSlotIndex = simSlotIndex;
@@ -271,6 +279,7 @@
         this.mSubscriptionType = subType;
         this.mGroupOwner = groupOwner;
         this.mCarrierConfigAccessRules = carrierConfigAccessRules;
+        this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled;
     }
 
     /**
@@ -334,7 +343,7 @@
     }
 
     /**
-     * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
+     * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN or
      * NAME_SOURCE_USER_INPUT.
      * @hide
      */
@@ -659,6 +668,15 @@
         return mIsGroupDisabled;
     }
 
+    /**
+     * Return whether uicc applications are set to be enabled or disabled.
+     * @hide
+     */
+    @SystemApi
+    public boolean areUiccApplicationsEnabled() {
+        return mAreUiccApplicationsEnabled;
+    }
+
     public static final @android.annotation.NonNull Parcelable.Creator<SubscriptionInfo> CREATOR = new Parcelable.Creator<SubscriptionInfo>() {
         @Override
         public SubscriptionInfo createFromParcel(Parcel source) {
@@ -690,12 +708,13 @@
             String groupOwner = source.readString();
             UiccAccessRule[] carrierConfigAccessRules = source.createTypedArray(
                 UiccAccessRule.CREATOR);
+            boolean areUiccApplicationsEnabled = source.readBoolean();
 
             SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
                     carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
                     countryIso, isEmbedded, nativeAccessRules, cardString, cardId, isOpportunistic,
                     groupUUID, isGroupDisabled, carrierid, profileClass, subType, groupOwner,
-                    carrierConfigAccessRules);
+                    carrierConfigAccessRules, areUiccApplicationsEnabled);
             info.setAssociatedPlmns(ehplmns, hplmns);
             return info;
         }
@@ -735,6 +754,7 @@
         dest.writeStringArray(mHplmns);
         dest.writeString(mGroupOwner);
         dest.writeTypedArray(mCarrierConfigAccessRules, flags);
+        dest.writeBoolean(mAreUiccApplicationsEnabled);
     }
 
     @Override
@@ -748,7 +768,7 @@
     public static String givePrintableIccid(String iccId) {
         String iccIdToPrint = null;
         if (iccId != null) {
-            if (iccId.length() > 9 && !Build.IS_DEBUGGABLE) {
+            if (iccId.length() > 9 && !TelephonyUtils.IS_DEBUGGABLE) {
                 iccIdToPrint = iccId.substring(0, 9) + Rlog.pii(false, iccId.substring(9));
             } else {
                 iccIdToPrint = iccId;
@@ -764,7 +784,8 @@
         return "{id=" + mId + " iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
                 + " carrierId=" + mCarrierId + " displayName=" + mDisplayName
                 + " carrierName=" + mCarrierName + " nameSource=" + mNameSource
-                + " iconTint=" + mIconTint + " mNumber=" + Rlog.pii(Build.IS_DEBUGGABLE, mNumber)
+                + " iconTint=" + mIconTint
+                + " mNumber=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber)
                 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
                 + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
                 + " nativeAccessRules " + Arrays.toString(mNativeAccessRules)
@@ -776,15 +797,16 @@
                 + " hplmns=" + Arrays.toString(mHplmns)
                 + " subscriptionType=" + mSubscriptionType
                 + " mGroupOwner=" + mGroupOwner
-                + " carrierConfigAccessRules=" + mCarrierConfigAccessRules + "}";
+                + " carrierConfigAccessRules=" + mCarrierConfigAccessRules
+                + " mAreUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled + "}";
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
-                mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc,
-                mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mNativeAccessRules,
-                mIsGroupDisabled, mCarrierId, mProfileClass, mGroupOwner);
+                mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString,
+                mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled,
+                mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled);
     }
 
     @Override
@@ -807,6 +829,7 @@
                 && mIsEmbedded == toCompare.mIsEmbedded
                 && mIsOpportunistic == toCompare.mIsOpportunistic
                 && mIsGroupDisabled == toCompare.mIsGroupDisabled
+                && mAreUiccApplicationsEnabled == toCompare.mAreUiccApplicationsEnabled
                 && mCarrierId == toCompare.mCarrierId
                 && Objects.equals(mGroupUUID, toCompare.mGroupUUID)
                 && Objects.equals(mIccId, toCompare.mIccId)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index fbbc951..376a5e0 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -35,7 +35,6 @@
 import android.annotation.UnsupportedAppUsage;
 import android.app.BroadcastOptions;
 import android.app.PendingIntent;
-import android.app.job.JobService;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
@@ -55,6 +54,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.provider.Telephony.SimInfo;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsMmTelManager;
 import android.util.DisplayMetrics;
@@ -130,7 +130,7 @@
 
     /** @hide */
     @UnsupportedAppUsage
-    public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+    public static final Uri CONTENT_URI = SimInfo.CONTENT_URI;
 
     /**
      * Generates a content {@link Uri} used to receive updates on simInfo change
@@ -148,10 +148,11 @@
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
      * subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()}
-     * while your app is running. You can also use a {@link JobService} to ensure your app
+     * while your app is running. You can also use a {@link android.app.job.JobService}
+     * to ensure your app
      * is notified of changes to the {@link Uri} even when it is not running.
-     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-     * updates to the {@link Uri}.
+     * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+     * delivery of updates to the {@link Uri}.
      * To be notified of changes to a specific subId, append subId to the URI
      * {@link Uri#withAppendedPath(Uri, String)}.
      * @hide
@@ -168,10 +169,10 @@
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
      * subscription advanced calling enabled
      * {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running.
-     * You can also use a {@link JobService} to ensure your app is notified of changes to the
-     * {@link Uri} even when it is not running.
-     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-     * updates to the {@link Uri}.
+     * You can also use a {@link android.app.job.JobService} to ensure your app is notified of
+     * changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+     * delivery of updates to the {@link Uri}.
      * To be notified of changes to a specific subId, append subId to the URI
      * {@link Uri#withAppendedPath(Uri, String)}.
      * @hide
@@ -187,10 +188,10 @@
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
      * subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()}
-     * while your app is running. You can also use a {@link JobService} to ensure your app
-     * is notified of changes to the {@link Uri} even when it is not running.
-     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-     * updates to the {@link Uri}.
+     * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+     * your app is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+     * delivery of updates to the {@link Uri}.
      * To be notified of changes to a specific subId, append subId to the URI
      * {@link Uri#withAppendedPath(Uri, String)}.
      * @hide
@@ -205,10 +206,10 @@
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
      * subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()}
-     * while your app is running. You can also use a {@link JobService} to ensure your app
-     * is notified of changes to the {@link Uri} even when it is not running.
-     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-     * updates to the {@link Uri}.
+     * while your app is running. You can also use a {@link android.app.job.JobService}
+     * to ensure your app is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+     * delivery of updates to the {@link Uri}.
      * To be notified of changes to a specific subId, append subId to the URI
      * {@link Uri#withAppendedPath(Uri, String)}.
      * @hide
@@ -225,10 +226,10 @@
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
      * subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()}
-     * while your app is running. You can also use a {@link JobService} to ensure your app
-     * is notified of changes to the {@link Uri} even when it is not running.
-     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-     * updates to the {@link Uri}.
+     * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+     * your app is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+     * delivery of updates to the {@link Uri}.
      * To be notified of changes to a specific subId, append subId to the URI
      * {@link Uri#withAppendedPath(Uri, String)}.
      * @hide
@@ -244,10 +245,10 @@
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
      * subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()}
-     * while your app is running. You can also use a {@link JobService} to ensure your app
-     * is notified of changes to the {@link Uri} even when it is not running.
-     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
-     * updates to the {@link Uri}.
+     * while your app is running. You can also use a {@link android.app.job.JobService} to ensure
+     * your app is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely
+     * delivery of updates to the {@link Uri}.
      * To be notified of changes to a specific subId, append subId to the URI
      * {@link Uri#withAppendedPath(Uri, String)}.
      * @hide
@@ -400,19 +401,19 @@
     public static final String NAME_SOURCE = "name_source";
 
     /**
-     * The name_source is the default
+     * The name_source is the default, which is from the carrier id.
      * @hide
      */
     public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
 
     /**
-     * The name_source is from the SIM
+     * The name_source is from SIM EF_SPN.
      * @hide
      */
-    public static final int NAME_SOURCE_SIM_SOURCE = 1;
+    public static final int NAME_SOURCE_SIM_SPN = 1;
 
     /**
-     * The name_source is from the user
+     * The name_source is from user input
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -425,6 +426,24 @@
     public static final int NAME_SOURCE_CARRIER = 3;
 
     /**
+     * The name_source is from SIM EF_PNN.
+     * @hide
+     */
+    public static final int NAME_SOURCE_SIM_PNN = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"NAME_SOURCE_"},
+            value = {
+                    NAME_SOURCE_DEFAULT_SOURCE,
+                    NAME_SOURCE_SIM_SPN,
+                    NAME_SOURCE_USER_INPUT,
+                    NAME_SOURCE_CARRIER,
+                    NAME_SOURCE_SIM_PNN
+            })
+    public @interface SimDisplayNameSource {}
+
+    /**
      * TelephonyProvider column name for the color of a SIM.
      * <P>Type: INTEGER (int)</P>
      */
@@ -816,6 +835,12 @@
     public static final String IMSI = "imsi";
 
     /**
+     * Whether uicc applications is set to be enabled or disabled. By default it's enabled.
+     * @hide
+     */
+    public static final String UICC_APPLICATIONS_ENABLED = "uicc_applications_enabled";
+
+    /**
      * Broadcast Action: The user has changed one of the default subs related to
      * data, phone calls, or sms</p>
      *
@@ -887,9 +912,9 @@
      * <p>
      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
      * changed.
-     *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS)
     public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED
@@ -1660,13 +1685,12 @@
      * Set display name by simInfo index with name source
      * @param displayName the display name of SIM card
      * @param subId the unique SubscriptionInfo index in database
-     * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
-     *                   2: NAME_SOURCE_USER_INPUT
+     * @param nameSource SIM display name source
      * @return the number of records updated or < 0 if invalid subId
      * @hide
      */
     @UnsupportedAppUsage
-    public int setDisplayName(String displayName, int subId, int nameSource) {
+    public int setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource) {
         if (VDBG) {
             logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
                     + " nameSource:" + nameSource);
@@ -2897,8 +2921,7 @@
      *
      * @throws SecurityException if the caller doesn't meet the requirements
      *             outlined above.
-     * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist,
-     *             or the groupUuid doesn't exist.
+     * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist.
      * @throws IllegalStateException if Telephony service is in bad state.
      *
      * @param subIdList list of subId that need adding into the group
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2cfc2b7..dd6abbc 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17,6 +17,8 @@
 package android.telephony;
 
 import static android.content.Context.TELECOM_SERVICE;
+import static android.provider.Telephony.Carriers.DPC_URI;
+import static android.provider.Telephony.Carriers.INVALID_APN_ID;
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
@@ -38,9 +40,13 @@
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.database.Cursor;
 import android.net.ConnectivityManager;
 import android.net.NetworkStats;
 import android.net.Uri;
@@ -59,6 +65,7 @@
 import android.os.WorkSource;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.carrier.CarrierIdentifier;
+import android.sysprop.TelephonyProperties;
 import android.telecom.CallScreeningService;
 import android.telecom.InCallService;
 import android.telecom.PhoneAccount;
@@ -71,6 +78,7 @@
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.data.ApnSetting;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
 import android.telephony.ims.ImsMmTelManager;
@@ -98,7 +106,6 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.SmsApplication;
-import com.android.internal.telephony.TelephonyProperties;
 
 import dalvik.system.VMRuntime;
 
@@ -142,6 +149,14 @@
     private static final String TAG = "TelephonyManager";
 
     /**
+     * To expand the error codes for {@link TelephonyManager#updateAvailableNetworks} and
+     * {@link TelephonyManager#setPreferredOpportunisticDataSubscription}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long CALLBACK_ON_MORE_ERROR_CODE_CHANGE = 130595455L;
+
+    /**
      * The key to use when placing the result of {@link #requestModemActivityInfo(ResultReceiver)}
      * into the ResultReceiver Bundle.
      * @hide
@@ -379,7 +394,7 @@
     @UnsupportedAppUsage
     public MultiSimVariants getMultiSimConfiguration() {
         String mSimConfig =
-            SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
+                TelephonyProperties.multi_sim_config().orElse("");
         if (mSimConfig.equals("dsds")) {
             return MultiSimVariants.DSDS;
         } else if (mSimConfig.equals("dsda")) {
@@ -416,14 +431,14 @@
         int modemCount = 1;
         switch (getMultiSimConfiguration()) {
             case UNKNOWN:
-                ConnectivityManager cm = mContext == null ? null : (ConnectivityManager) mContext
-                        .getSystemService(Context.CONNECTIVITY_SERVICE);
+                modemCount = MODEM_COUNT_SINGLE_MODEM;
                 // check for voice and data support, 0 if not supported
-                if (!isVoiceCapable() && !isSmsCapable() && cm != null
-                        && !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
-                    modemCount = MODEM_COUNT_NO_MODEM;
-                } else {
-                    modemCount = MODEM_COUNT_SINGLE_MODEM;
+                if (!isVoiceCapable() && !isSmsCapable() && mContext != null) {
+                    ConnectivityManager cm = (ConnectivityManager) mContext
+                            .getSystemService(Context.CONNECTIVITY_SERVICE);
+                    if (cm != null && !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
+                        modemCount = MODEM_COUNT_NO_MODEM;
+                    }
                 }
                 break;
             case DSDS:
@@ -445,8 +460,7 @@
      * {@link #getActiveModemCount} returns 1 while this API returns 2.
      */
     public @ModemCount int getSupportedModemCount() {
-        return SystemProperties.getInt(TelephonyProperties.PROPERTY_MAX_ACTIVE_MODEMS,
-                getActiveModemCount());
+        return TelephonyProperties.max_active_modems().orElse(getActiveModemCount());
     }
 
     /**
@@ -592,6 +606,7 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_EMERGENCY_ASSISTANCE =
             "android.telephony.action.EMERGENCY_ASSISTANCE";
@@ -703,31 +718,6 @@
     public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
 
     /**
-     * Broadcast intent action indicating that a precise call state
-     * (cellular) on the device has changed.
-     *
-     * <p>
-     * The {@link #EXTRA_RINGING_CALL_STATE} extra indicates the ringing call state.
-     * The {@link #EXTRA_FOREGROUND_CALL_STATE} extra indicates the foreground call state.
-     * The {@link #EXTRA_BACKGROUND_CALL_STATE} extra indicates the background call state.
-     *
-     * <p class="note">
-     * Requires the READ_PRECISE_PHONE_STATE permission.
-     *
-     * @see #EXTRA_RINGING_CALL_STATE
-     * @see #EXTRA_FOREGROUND_CALL_STATE
-     * @see #EXTRA_BACKGROUND_CALL_STATE
-     *
-     * <p class="note">
-     * Requires the READ_PRECISE_PHONE_STATE permission.
-     * @deprecated use {@link PhoneStateListener#LISTEN_PRECISE_CALL_STATE} instead
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PRECISE_CALL_STATE_CHANGED =
-            "android.intent.action.PRECISE_CALL_STATE";
-
-    /**
      * Broadcast intent action indicating that call disconnect cause has changed.
      *
      * <p>
@@ -749,78 +739,6 @@
     /**
      * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
      * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
-     * containing the state of the current ringing call.
-     *
-     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
-     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
-     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
-     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
-     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
-     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
-     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_RINGING_CALL_STATE = "ringing_state";
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
-     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
-     * containing the state of the current foreground call.
-     *
-     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
-     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
-     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
-     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
-     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
-     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
-     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_FOREGROUND_CALL_STATE = "foreground_state";
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
-     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
-     * containing the state of the current background call.
-     *
-     * @see PreciseCallState#PRECISE_CALL_STATE_NOT_VALID
-     * @see PreciseCallState#PRECISE_CALL_STATE_IDLE
-     * @see PreciseCallState#PRECISE_CALL_STATE_ACTIVE
-     * @see PreciseCallState#PRECISE_CALL_STATE_HOLDING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DIALING
-     * @see PreciseCallState#PRECISE_CALL_STATE_ALERTING
-     * @see PreciseCallState#PRECISE_CALL_STATE_INCOMING
-     * @see PreciseCallState#PRECISE_CALL_STATE_WAITING
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTED
-     * @see PreciseCallState#PRECISE_CALL_STATE_DISCONNECTING
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_BACKGROUND_CALL_STATE = "background_state";
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_CALL_STATE_CHANGED} broadcast and
-     * {@link PhoneStateListener#onPreciseCallStateChanged(PreciseCallState)} for an integer
      * containing the disconnect cause.
      *
      * @see DisconnectCause
@@ -829,8 +747,10 @@
      * Retrieve with
      * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
      *
+     * @deprecated Should use the {@link TelecomManager#EXTRA_DISCONNECT_CAUSE} instead.
      * @hide
      */
+    @Deprecated
     public static final String EXTRA_DISCONNECT_CAUSE = "disconnect_cause";
 
     /**
@@ -849,88 +769,6 @@
     public static final String EXTRA_PRECISE_DISCONNECT_CAUSE = "precise_disconnect_cause";
 
     /**
-     * Broadcast intent action indicating a data connection has changed,
-     * providing precise information about the connection.
-     *
-     * <p>
-     * The {@link #EXTRA_DATA_STATE} extra indicates the connection state.
-     * The {@link #EXTRA_DATA_NETWORK_TYPE} extra indicates the connection network type.
-     * The {@link #EXTRA_DATA_APN_TYPE} extra indicates the APN type.
-     * The {@link #EXTRA_DATA_APN} extra indicates the APN.
-     * The {@link #EXTRA_DATA_IFACE_PROPERTIES} extra indicates the connection interface.
-     * The {@link #EXTRA_DATA_FAILURE_CAUSE} extra indicates the connection fail cause.
-     *
-     * <p class="note">
-     * Requires the READ_PRECISE_PHONE_STATE permission.
-     *
-     * @see #EXTRA_DATA_STATE
-     * @see #EXTRA_DATA_NETWORK_TYPE
-     * @see #EXTRA_DATA_APN_TYPE
-     * @see #EXTRA_DATA_APN
-     * @see #EXTRA_DATA_IFACE
-     * @see #EXTRA_DATA_FAILURE_CAUSE
-     * @hide
-     *
-     * @deprecated If the app is running in the background, it won't be able to receive this
-     * broadcast. Apps should use ConnectivityManager {@link #registerNetworkCallback(
-     * android.net.NetworkRequest, ConnectivityManager.NetworkCallback)} to listen for network
-     * changes.
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @Deprecated
-    @UnsupportedAppUsage
-    public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
-            "android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
-     * for an integer containing the state of the current data connection.
-     *
-     * @see TelephonyManager#DATA_UNKNOWN
-     * @see TelephonyManager#DATA_DISCONNECTED
-     * @see TelephonyManager#DATA_CONNECTING
-     * @see TelephonyManager#DATA_CONNECTED
-     * @see TelephonyManager#DATA_SUSPENDED
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_DATA_STATE = PhoneConstants.STATE_KEY;
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
-     * for an integer containing the network type.
-     *
-     * @see TelephonyManager#NETWORK_TYPE_UNKNOWN
-     * @see TelephonyManager#NETWORK_TYPE_GPRS
-     * @see TelephonyManager#NETWORK_TYPE_EDGE
-     * @see TelephonyManager#NETWORK_TYPE_UMTS
-     * @see TelephonyManager#NETWORK_TYPE_CDMA
-     * @see TelephonyManager#NETWORK_TYPE_EVDO_0
-     * @see TelephonyManager#NETWORK_TYPE_EVDO_A
-     * @see TelephonyManager#NETWORK_TYPE_1xRTT
-     * @see TelephonyManager#NETWORK_TYPE_HSDPA
-     * @see TelephonyManager#NETWORK_TYPE_HSUPA
-     * @see TelephonyManager#NETWORK_TYPE_HSPA
-     * @see TelephonyManager#NETWORK_TYPE_IDEN
-     * @see TelephonyManager#NETWORK_TYPE_EVDO_B
-     * @see TelephonyManager#NETWORK_TYPE_LTE
-     * @see TelephonyManager#NETWORK_TYPE_EHRPD
-     * @see TelephonyManager#NETWORK_TYPE_HSPAP
-     * @see TelephonyManager#NETWORK_TYPE_NR
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getIntExtra(String name, int defaultValue)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_DATA_NETWORK_TYPE = PhoneConstants.DATA_NETWORK_TYPE_KEY;
-
-    /**
      * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
      * for an String containing the data APN type.
      *
@@ -955,30 +793,6 @@
     public static final String EXTRA_DATA_APN = PhoneConstants.DATA_APN_KEY;
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
-     * for an String representation of the data interface.
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getParcelableExtra(String name)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_DATA_LINK_PROPERTIES_KEY = PhoneConstants.DATA_LINK_PROPERTIES_KEY;
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
-     * for the data connection fail cause.
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getStringExtra(String name)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY;
-
-    /**
      * Broadcast intent action for letting the default dialer to know to show voicemail
      * notification.
      *
@@ -1639,6 +1453,26 @@
      */
     public static final String EXTRA_SIM_COMBINATION_NAMES =
             "android.telephony.extra.SIM_COMBINATION_NAMES";
+
+    /**
+     * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
+     * This is a sticky broadcast.
+     * The intent will have the following extra values:</p>
+     * <ul>
+     *   <li><em>time</em> - The time as a long in UTC milliseconds.</li>
+     * </ul>
+     *
+     * <p class="note">
+     * Requires the READ_PHONE_STATE permission.
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String ACTION_NETWORK_SET_TIME = "android.telephony.action.NETWORK_SET_TIME";
+
     //
     //
     // Device Info
@@ -1959,11 +1793,23 @@
     /**
      * Returns the Network Access Identifier (NAI). Return null if NAI is not available.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
+     * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+     * access is deprecated and will be removed in a future release.
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
      */
-    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getNai() {
         return getNaiBySubscriberId(getSubId());
     }
@@ -1971,6 +1817,21 @@
     /**
      * Returns the NAI. Return null if NAI is not available.
      *
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
+     * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+     * access is deprecated and will be removed in a future release.
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      *  @param slotIndex of which Nai is returned
      */
     /** {@hide}*/
@@ -2214,12 +2075,10 @@
     /** {@hide} */
     @UnsupportedAppUsage
     private int getPhoneTypeFromProperty(int phoneId) {
-        String type = getTelephonyProperty(phoneId,
-                TelephonyProperties.CURRENT_ACTIVE_PHONE, null);
-        if (type == null || type.isEmpty()) {
-            return getPhoneTypeFromNetworkType(phoneId);
-        }
-        return Integer.parseInt(type);
+        Integer type = getTelephonyProperty(
+                phoneId, TelephonyProperties.current_active_phone(), null);
+        if (type != null) return type;
+        return getPhoneTypeFromNetworkType(phoneId);
     }
 
     private int getPhoneTypeFromNetworkType() {
@@ -2231,9 +2090,9 @@
         // When the system property CURRENT_ACTIVE_PHONE, has not been set,
         // use the system property for default network type.
         // This is a fail safe, and can only happen at first boot.
-        String mode = getTelephonyProperty(phoneId, "ro.telephony.default_network", null);
-        if (mode != null && !mode.isEmpty()) {
-            return TelephonyManager.getPhoneType(Integer.parseInt(mode));
+        Integer mode = getTelephonyProperty(phoneId, TelephonyProperties.default_network(), null);
+        if (mode != null) {
+            return TelephonyManager.getPhoneType(mode);
         }
         return TelephonyManager.PHONE_TYPE_NONE;
     }
@@ -2337,7 +2196,7 @@
 
     /** The ProductType used for LTE on CDMA devices */
     private static final String sLteOnCdmaProductType =
-        SystemProperties.get(TelephonyProperties.PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE, "");
+            TelephonyProperties.lte_on_cdma_product_type().orElse("");
 
     /**
      * Return if the current radio is LTE on CDMA. This
@@ -2355,8 +2214,8 @@
         int curVal;
         String productType = "";
 
-        curVal = SystemProperties.getInt(TelephonyProperties.PROPERTY_LTE_ON_CDMA_DEVICE,
-                    PhoneConstants.LTE_ON_CDMA_UNKNOWN);
+        curVal = TelephonyProperties.lte_on_cdma_device().orElse(
+            PhoneConstants.LTE_ON_CDMA_UNKNOWN);
         retVal = curVal;
         if (retVal == PhoneConstants.LTE_ON_CDMA_UNKNOWN) {
             Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);
@@ -2408,7 +2267,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getNetworkOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
-        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");
+        return getTelephonyProperty(phoneId, TelephonyProperties.operator_alpha(), "");
     }
 
     /**
@@ -2452,7 +2311,7 @@
      **/
     @UnsupportedAppUsage
     public String getNetworkOperatorForPhone(int phoneId) {
-        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
+        return getTelephonyProperty(phoneId, TelephonyProperties.operator_numeric(), "");
     }
 
 
@@ -2516,8 +2375,7 @@
     @UnsupportedAppUsage
     public boolean isNetworkRoaming(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
-        return Boolean.parseBoolean(getTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null));
+        return getTelephonyProperty(subId, TelephonyProperties.operator_is_roaming(), false);
     }
 
     /**
@@ -2536,7 +2394,14 @@
      * @return the lowercase 2 character ISO-3166 country code, or empty string if not available.
      */
     public String getNetworkCountryIso() {
-        return getNetworkCountryIso(getPhoneId());
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) return "";
+            return telephony.getNetworkCountryIsoForPhone(getPhoneId(),
+                    null /* no permission check */);
+        } catch (RemoteException ex) {
+            return "";
+        }
     }
 
     /**
@@ -2557,16 +2422,23 @@
      *
      * @return the lowercase 2 character ISO-3166 country code, or empty string if not available.
      *
+     * @throws IllegalArgumentException when the slotIndex is invalid.
+     *
      * {@hide}
      */
     @SystemApi
     @TestApi
     @NonNull
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getNetworkCountryIso(int slotIndex) {
         try {
+            if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
+                throw new IllegalArgumentException("invalid slot index " + slotIndex);
+            }
+
             ITelephony telephony = getITelephony();
             if (telephony == null) return "";
-            return telephony.getNetworkCountryIsoForPhone(slotIndex);
+            return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName());
         } catch (RemoteException ex) {
             return "";
         }
@@ -2574,7 +2446,7 @@
 
     /*
      * When adding a network type to the list below, make sure to add the correct icon to
-     * MobileSignalController.mapIconSets().
+     * MobileSignalController.mapIconSets() as well as NETWORK_TYPES
      * Do not add negative types.
      */
     /** Network type is unknown */
@@ -2622,8 +2494,36 @@
     /** Current network is NR(New Radio) 5G. */
     public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20.
 
-    /** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
-    public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_NR;
+    private static final @NetworkType int[] NETWORK_TYPES = {
+            NETWORK_TYPE_GPRS,
+            NETWORK_TYPE_EDGE,
+            NETWORK_TYPE_UMTS,
+            NETWORK_TYPE_CDMA,
+            NETWORK_TYPE_EVDO_0,
+            NETWORK_TYPE_EVDO_A,
+            NETWORK_TYPE_1xRTT,
+            NETWORK_TYPE_HSDPA,
+            NETWORK_TYPE_HSUPA,
+            NETWORK_TYPE_HSPA,
+            NETWORK_TYPE_IDEN,
+            NETWORK_TYPE_EVDO_B,
+            NETWORK_TYPE_LTE,
+            NETWORK_TYPE_EHRPD,
+            NETWORK_TYPE_HSPAP,
+            NETWORK_TYPE_GSM,
+            NETWORK_TYPE_TD_SCDMA,
+            NETWORK_TYPE_IWLAN,
+            NETWORK_TYPE_LTE_CA,
+            NETWORK_TYPE_NR
+    };
+
+    /**
+     * Return a collection of all network types
+     * @return network types
+     */
+    public static @NonNull @NetworkType int[] getAllNetworkTypes() {
+        return NETWORK_TYPES;
+    }
 
     /**
      * Return the current data network type.
@@ -2916,6 +2816,24 @@
     //
     //
 
+    /** @hide */
+    @IntDef(prefix = {"SIM_STATE_"},
+            value = {
+                    SIM_STATE_UNKNOWN,
+                    SIM_STATE_ABSENT,
+                    SIM_STATE_PIN_REQUIRED,
+                    SIM_STATE_PUK_REQUIRED,
+                    SIM_STATE_NETWORK_LOCKED,
+                    SIM_STATE_READY,
+                    SIM_STATE_NOT_READY,
+                    SIM_STATE_PERM_DISABLED,
+                    SIM_STATE_CARD_IO_ERROR,
+                    SIM_STATE_CARD_RESTRICTED,
+                    SIM_STATE_LOADED,
+                    SIM_STATE_PRESENT,
+            })
+    public @interface SimState {}
+
     /**
      * SIM card state: Unknown. Signifies that the SIM is in transition
      * between states. For example, when the user inputs the SIM pin
@@ -3121,7 +3039,7 @@
      * @see #SIM_STATE_CARD_IO_ERROR
      * @see #SIM_STATE_CARD_RESTRICTED
      */
-    public int getSimState() {
+    public @SimState int getSimState() {
         int simState = getSimStateIncludingLoaded();
         if (simState == SIM_STATE_LOADED) {
             simState = SIM_STATE_READY;
@@ -3129,7 +3047,7 @@
         return simState;
     }
 
-    private int getSimStateIncludingLoaded() {
+    private @SimState int getSimStateIncludingLoaded() {
         int slotIndex = getSlotIndex();
         // slotIndex may be invalid due to sim being absent. In that case query all slots to get
         // sim state
@@ -3163,7 +3081,7 @@
      * @hide
      */
     @SystemApi
-    public int getSimCardState() {
+    public @SimState int getSimCardState() {
         int simState = getSimState();
         return getSimCardStateFromSimState(simState);
     }
@@ -3183,7 +3101,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public int getSimCardState(int physicalSlotIndex) {
+    public @SimState int getSimCardState(int physicalSlotIndex) {
         int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
         return getSimCardStateFromSimState(simState);
     }
@@ -3193,7 +3111,7 @@
      * @param simState
      * @return SIM card state
      */
-    private int getSimCardStateFromSimState(int simState) {
+    private @SimState int getSimCardStateFromSimState(int simState) {
         switch (simState) {
             case SIM_STATE_UNKNOWN:
             case SIM_STATE_ABSENT:
@@ -3233,7 +3151,7 @@
      * @hide
      */
     @SystemApi
-    public int getSimApplicationState() {
+    public @SimState int getSimApplicationState() {
         int simState = getSimStateIncludingLoaded();
         return getSimApplicationStateFromSimState(simState);
     }
@@ -3256,7 +3174,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public int getSimApplicationState(int physicalSlotIndex) {
+    public @SimState int getSimApplicationState(int physicalSlotIndex) {
         int simState =
                 SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
         return getSimApplicationStateFromSimState(simState);
@@ -3267,7 +3185,7 @@
      * @param simState
      * @return SIM application state
      */
-    private int getSimApplicationStateFromSimState(int simState) {
+    private @SimState int getSimApplicationStateFromSimState(int simState) {
         switch (simState) {
             case SIM_STATE_UNKNOWN:
             case SIM_STATE_ABSENT:
@@ -3324,7 +3242,7 @@
      * @see #SIM_STATE_CARD_IO_ERROR
      * @see #SIM_STATE_CARD_RESTRICTED
      */
-    public int getSimState(int slotIndex) {
+    public @SimState int getSimState(int slotIndex) {
         int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
         if (simState == SIM_STATE_LOADED) {
             simState = SIM_STATE_READY;
@@ -3414,8 +3332,7 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumericForPhone(int phoneId) {
-        return getTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
+        return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_numeric(), "");
     }
 
     /**
@@ -3452,8 +3369,7 @@
      */
     @UnsupportedAppUsage
     public String getSimOperatorNameForPhone(int phoneId) {
-         return getTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");
+        return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_alpha(), "");
     }
 
     /**
@@ -3485,8 +3401,7 @@
      */
     @UnsupportedAppUsage
     public String getSimCountryIsoForPhone(int phoneId) {
-        return getTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
+        return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_iso_country(), "");
     }
 
     /**
@@ -5131,6 +5046,7 @@
             DATA_CONNECTING,
             DATA_CONNECTED,
             DATA_SUSPENDED,
+            DATA_DISCONNECTING,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DataState{}
@@ -5147,6 +5063,12 @@
      * traffic is temporarily unavailable. For example, in a 2G network,
      * data activity may be suspended when a voice call arrives. */
     public static final int DATA_SUSPENDED      = 3;
+    /**
+     * Data connection state: Disconnecting.
+     *
+     * IP traffic may be available but will cease working imminently.
+     */
+    public static final int DATA_DISCONNECTING = 4;
 
     /**
      * Returns a constant indicating the current data connection state
@@ -5156,14 +5078,21 @@
      * @see #DATA_CONNECTING
      * @see #DATA_CONNECTED
      * @see #DATA_SUSPENDED
+     * @see #DATA_DISCONNECTING
      */
     public int getDataState() {
         try {
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return DATA_DISCONNECTED;
-            return telephony.getDataStateForSubId(
+            int state = telephony.getDataStateForSubId(
                     getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
+            if (state == TelephonyManager.DATA_DISCONNECTING
+                    && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+                return TelephonyManager.DATA_CONNECTED;
+            }
+
+            return state;
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return DATA_DISCONNECTED;
@@ -5184,6 +5113,7 @@
             case DATA_CONNECTING: return "CONNECTING";
             case DATA_CONNECTED: return "CONNECTED";
             case DATA_SUSPENDED: return "SUSPENDED";
+            case DATA_DISCONNECTING: return "DISCONNECTING";
         }
         return "UNKNOWN(" + state + ")";
     }
@@ -6496,74 +6426,14 @@
     }
 
     /**
-     * Sets a per-phone telephony property with the value specified.
-     *
-     * @hide
+     * Inserts or updates a list property. Expands the list if its length is not enough.
      */
-    @UnsupportedAppUsage
-    public static void setTelephonyProperty(int phoneId, String property, String value) {
-        String propVal = "";
-        String p[] = null;
-        String prop = SystemProperties.get(property);
-
-        if (value == null) {
-            value = "";
-        }
-        value.replace(',', ' ');
-        if (prop != null) {
-            p = prop.split(",");
-        }
-
-        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
-            Rlog.d(TAG, "setTelephonyProperty: invalid phoneId=" + phoneId +
-                    " property=" + property + " value: " + value + " prop=" + prop);
-            return;
-        }
-
-        for (int i = 0; i < phoneId; i++) {
-            String str = "";
-            if ((p != null) && (i < p.length)) {
-                str = p[i];
-            }
-            propVal = propVal + str + ",";
-        }
-
-        propVal = propVal + value;
-        if (p != null) {
-            for (int i = phoneId + 1; i < p.length; i++) {
-                propVal = propVal + "," + p[i];
-            }
-        }
-
-        int propValLen = propVal.length();
-        try {
-            propValLen = propVal.getBytes("utf-8").length;
-        } catch (java.io.UnsupportedEncodingException e) {
-            Rlog.d(TAG, "setTelephonyProperty: utf-8 not supported");
-        }
-        if (propValLen > SystemProperties.PROP_VALUE_MAX) {
-            Rlog.d(TAG, "setTelephonyProperty: property too long phoneId=" + phoneId +
-                    " property=" + property + " value: " + value + " propVal=" + propVal);
-            return;
-        }
-
-        SystemProperties.set(property, propVal);
+    private static <T> List<T> updateTelephonyProperty(List<T> prop, int phoneId, T value) {
+        List<T> ret = new ArrayList<>(prop);
+        while (ret.size() <= phoneId) ret.add(null);
+        ret.set(phoneId, value);
+        return ret;
     }
-
-    /**
-     * Sets a global telephony property with the value specified.
-     *
-     * @hide
-     */
-    public static void setTelephonyProperty(String property, String value) {
-        if (value == null) {
-            value = "";
-        }
-        Rlog.d(TAG, "setTelephonyProperty: success" + " property=" +
-                property + " value: " + value);
-        SystemProperties.set(property, value);
-    }
-
     /**
      * Convenience function for retrieving a value from the secure settings
      * value list as an integer.  Note that internally setting values are
@@ -6655,7 +6525,7 @@
     }
 
     /**
-     * Gets a per-phone telephony property.
+     * Gets a per-phone telephony property from a property name.
      *
      * @hide
      */
@@ -6673,6 +6543,15 @@
     }
 
     /**
+     * Gets a typed per-phone telephony property from a schematized list property.
+     */
+    private static <T> T getTelephonyProperty(int phoneId, List<T> prop, T defaultValue) {
+        T ret = null;
+        if (phoneId >= 0 && phoneId < prop.size()) ret = prop.get(phoneId);
+        return ret != null ? ret : defaultValue;
+    }
+
+    /**
      * Gets a global telephony property.
      *
      * See also getTelephonyProperty(phoneId, property, defaultVal). Most telephony properties are
@@ -6882,7 +6761,8 @@
      * If the list is longer than the size of EFfplmn, then the file will be written from the
      * beginning of the list up to the file size.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * <p>Requires Permission: {@link android.Manifest.permission#MODIFY_PHONE_STATE
+     * MODIFY_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param fplmns a list of PLMNs to be forbidden.
@@ -6896,7 +6776,7 @@
     public int setForbiddenPlmns(@NonNull List<String> fplmns) {
         try {
             ITelephony telephony = getITelephony();
-            if (telephony == null) return 0;
+            if (telephony == null) return -1;
             return telephony.setForbiddenPlmns(
                     getSubId(), APPTYPE_USIM, fplmns, getOpPackageName());
         } catch (RemoteException ex) {
@@ -6905,7 +6785,7 @@
             // This could happen before phone starts
             Rlog.e(TAG, "setForbiddenPlmns NullPointerException: " + ex.getMessage());
         }
-        return 0;
+        return -1;
     }
 
     /**
@@ -8008,17 +7888,25 @@
         return Collections.EMPTY_LIST;
     }
 
-    /** @hide */
-    public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
+    /**
+     * Get the names of packages with carrier privileges for all the active subscriptions.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
+    public List<String> getCarrierPrivilegedPackagesForAllActiveSubscriptions() {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony.getPackagesWithCarrierPrivilegesForAllPhones();
             }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones RemoteException", ex);
+            Rlog.e(TAG, "getCarrierPrivilegedPackagesForAllActiveSubscriptions RemoteException",
+                    ex);
         } catch (NullPointerException ex) {
-            Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones NPE", ex);
+            Rlog.e(TAG, "getCarrierPrivilegedPackagesForAllActiveSubscriptions NPE", ex);
         }
         return Collections.EMPTY_LIST;
     }
@@ -8388,6 +8276,44 @@
     }
 
     /**
+     * Shut down all the live radios over all the slot index.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void shutdownAllRadios() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.shutdownMobileRadios();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#shutdownMobileRadios", e);
+        }
+    }
+
+    /**
+     * Check if any radio is on over all the slot indexes.
+     *
+     * @return {@code true} if any radio is on over any slot index.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isAnyRadioPoweredOn() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.needMobileRadioShutdown();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#needMobileRadioShutdown", e);
+        }
+        return false;
+    }
+
+    /**
      * Radio explicitly powered off (e.g, airplane mode).
      * @hide
      */
@@ -9002,7 +8928,7 @@
     }
 
    /**
-    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
+    * Set TelephonyProperties.icc_operator_numeric for the default phone.
     *
     * @hide
     */
@@ -9012,18 +8938,21 @@
     }
 
    /**
-    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the given phone.
+    * Set TelephonyProperties.icc_operator_numeric for the given phone.
     *
     * @hide
     */
     @UnsupportedAppUsage
     public void setSimOperatorNumericForPhone(int phoneId, String numeric) {
-        setTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, numeric);
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.icc_operator_numeric(), phoneId, numeric);
+            TelephonyProperties.icc_operator_numeric(newList);
+        }
     }
 
     /**
-     * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
+     * Set TelephonyProperties.icc_operator_alpha for the default phone.
      *
      * @hide
      */
@@ -9033,18 +8962,21 @@
     }
 
     /**
-     * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the given phone.
+     * Set TelephonyProperties.icc_operator_alpha for the given phone.
      *
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setSimOperatorNameForPhone(int phoneId, String name) {
-        setTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, name);
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.icc_operator_alpha(), phoneId, name);
+            TelephonyProperties.icc_operator_alpha(newList);
+        }
     }
 
    /**
-    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY for the default phone.
+    * Set TelephonyProperties.icc_operator_iso_country for the default phone.
     *
     * @hide
     */
@@ -9054,18 +8986,21 @@
     }
 
    /**
-    * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY for the given phone.
+    * Set TelephonyProperties.icc_operator_iso_country for the given phone.
     *
     * @hide
     */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setSimCountryIsoForPhone(int phoneId, String iso) {
-        setTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.icc_operator_iso_country(), phoneId, iso);
+            TelephonyProperties.icc_operator_iso_country(newList);
+        }
     }
 
     /**
-     * Set TelephonyProperties.PROPERTY_SIM_STATE for the default phone.
+     * Set TelephonyProperties.sim_state for the default phone.
      *
      * @hide
      */
@@ -9075,14 +9010,17 @@
     }
 
     /**
-     * Set TelephonyProperties.PROPERTY_SIM_STATE for the given phone.
+     * Set TelephonyProperties.sim_state for the given phone.
      *
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setSimStateForPhone(int phoneId, String state) {
-        setTelephonyProperty(phoneId,
-                TelephonyProperties.PROPERTY_SIM_STATE, state);
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.sim_state(), phoneId, state);
+            TelephonyProperties.sim_state(newList);
+        }
     }
 
     /**
@@ -9187,7 +9125,11 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setBasebandVersionForPhone(int phoneId, String version) {
-        setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_BASEBAND_VERSION, version);
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.baseband_version(), phoneId, version);
+            TelephonyProperties.baseband_version(newList);
+        }
     }
 
     /**
@@ -9210,8 +9152,8 @@
      */
     private String getBasebandVersionLegacy(int phoneId) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            String prop = TelephonyProperties.PROPERTY_BASEBAND_VERSION +
-                    ((phoneId == 0) ? "" : Integer.toString(phoneId));
+            String prop = "gsm.version.baseband"
+                    + ((phoneId == 0) ? "" : Integer.toString(phoneId));
             return SystemProperties.get(prop);
         }
         return null;
@@ -9228,7 +9170,7 @@
         if (version != null && !version.isEmpty()) {
             setBasebandVersionForPhone(phoneId, version);
         }
-        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_BASEBAND_VERSION, "");
+        return getTelephonyProperty(phoneId, TelephonyProperties.baseband_version(), "");
     }
 
     /**
@@ -9254,8 +9196,9 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setPhoneType(int phoneId, int type) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            TelephonyManager.setTelephonyProperty(phoneId,
-                    TelephonyProperties.CURRENT_ACTIVE_PHONE, String.valueOf(type));
+            List<Integer> newList = updateTelephonyProperty(
+                    TelephonyProperties.current_active_phone(), phoneId, type);
+            TelephonyProperties.current_active_phone(newList);
         }
     }
 
@@ -9284,8 +9227,8 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public String getOtaSpNumberSchemaForPhone(int phoneId, String defaultValue) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            return TelephonyManager.getTelephonyProperty(phoneId,
-                    TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA, defaultValue);
+            return getTelephonyProperty(
+                    phoneId, TelephonyProperties.otasp_num_schema(), defaultValue);
         }
 
         return defaultValue;
@@ -9315,8 +9258,7 @@
      */
     public boolean getSmsReceiveCapableForPhone(int phoneId, boolean defaultValue) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            return Boolean.parseBoolean(TelephonyManager.getTelephonyProperty(phoneId,
-                    TelephonyProperties.PROPERTY_SMS_RECEIVE, String.valueOf(defaultValue)));
+            return getTelephonyProperty(phoneId, TelephonyProperties.sms_receive(), defaultValue);
         }
 
         return defaultValue;
@@ -9346,8 +9288,7 @@
      */
     public boolean getSmsSendCapableForPhone(int phoneId, boolean defaultValue) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            return Boolean.parseBoolean(TelephonyManager.getTelephonyProperty(phoneId,
-                    TelephonyProperties.PROPERTY_SMS_SEND, String.valueOf(defaultValue)));
+            return getTelephonyProperty(phoneId, TelephonyProperties.sms_send(), defaultValue);
         }
 
         return defaultValue;
@@ -9387,7 +9328,9 @@
     @UnsupportedAppUsage
     public void setNetworkOperatorNameForPhone(int phoneId, String name) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, name);
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.operator_alpha(), phoneId, name);
+            TelephonyProperties.operator_alpha(newList);
         }
     }
 
@@ -9409,7 +9352,11 @@
      */
     @UnsupportedAppUsage
     public void setNetworkOperatorNumericForPhone(int phoneId, String numeric) {
-        setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, numeric);
+        if (SubscriptionManager.isValidPhoneId(phoneId)) {
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.operator_numeric(), phoneId, numeric);
+            TelephonyProperties.operator_numeric(newList);
+        }
     }
 
     /**
@@ -9431,8 +9378,9 @@
     @UnsupportedAppUsage
     public void setNetworkRoamingForPhone(int phoneId, boolean isRoaming) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            setTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
-                    isRoaming ? "true" : "false");
+            List<Boolean> newList = updateTelephonyProperty(
+                    TelephonyProperties.operator_is_roaming(), phoneId, isRoaming);
+            TelephonyProperties.operator_is_roaming(newList);
         }
     }
 
@@ -9459,9 +9407,10 @@
     @UnsupportedAppUsage
     public void setDataNetworkTypeForPhone(int phoneId, int type) {
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
-            setTelephonyProperty(phoneId,
-                    TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
+            List<String> newList = updateTelephonyProperty(
+                    TelephonyProperties.data_network_type(), phoneId,
                     ServiceState.rilRadioTechnologyToString(type));
+            TelephonyProperties.data_network_type(newList);
         }
     }
 
@@ -10270,19 +10219,25 @@
     }
 
     /**
-     * Action set from carrier signalling broadcast receivers to enable/disable radio
-     * Permissions {@link android.Manifest.permission.MODIFY_PHONE_STATE} is required.
-     * @param subId the subscription ID that this action applies to.
+     * Carrier action to enable or disable the radio.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
      * @param enabled control enable or disable radio.
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
+    public void setRadioEnabled(boolean enabled) {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                service.carrierActionSetRadioEnabled(subId, enabled);
+                service.carrierActionSetRadioEnabled(
+                        getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#carrierActionSetRadioEnabled", e);
@@ -10290,20 +10245,25 @@
     }
 
     /**
-     * Action set from carrier signalling broadcast receivers to start/stop reporting default
-     * network available events
-     * Permissions {@link android.Manifest.permission.MODIFY_PHONE_STATE} is required.
-     * @param subId the subscription ID that this action applies to.
+     * Carrier action to start or stop reporting default network available events.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
      * @param report control start/stop reporting network status.
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
+    public void reportDefaultNetworkStatus(boolean report) {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                service.carrierActionReportDefaultNetworkStatus(subId, report);
+                service.carrierActionReportDefaultNetworkStatus(
+                        getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), report);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#carrierActionReportDefaultNetworkStatus", e);
@@ -10311,18 +10271,24 @@
     }
 
     /**
-     * Action set from carrier signalling broadcast receivers to reset all carrier actions
-     * Permissions {@link android.Manifest.permission.MODIFY_PHONE_STATE} is required.
-     * @param subId the subscription ID that this action applies to.
+     * Reset all carrier actions previously set by {@link #setRadioEnabled},
+     * {@link #reportDefaultNetworkStatus} and {@link #setCarrierDataEnabled}.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void carrierActionResetAll(int subId) {
+    public void resetAllCarrierActions() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                service.carrierActionResetAll(subId);
+                service.carrierActionResetAll(
+                        getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#carrierActionResetAll", e);
@@ -11200,7 +11166,9 @@
     @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
             SET_OPPORTUNISTIC_SUB_SUCCESS,
             SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
-            SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION})
+            SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION,
+            SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+            SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION})
     public @interface SetOpportunisticSubscriptionResult {}
 
     /**
@@ -11218,6 +11186,16 @@
      */
     public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2;
 
+    /**
+     * The subscription is not valid. It must be an opportunistic subscription.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3;
+
+    /**
+     * Subscription service happened remote exception.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"UPDATE_AVAILABLE_NETWORKS"}, value = {
@@ -11225,7 +11203,13 @@
             UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE,
             UPDATE_AVAILABLE_NETWORKS_ABORTED,
             UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS,
-            UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE})
+            UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE,
+            UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL,
+            UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL,
+            UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED,
+            UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+            UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION,
+            UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED})
     public @interface UpdateAvailableNetworksResult {}
 
     /**
@@ -11254,6 +11238,36 @@
     public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4;
 
     /**
+     * Disable modem fail.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_DISABLE_MODEM_FAIL = 5;
+
+    /**
+     * Enable modem fail.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_ENABLE_MODEM_FAIL = 6;
+
+    /**
+     * Carrier app does not support multiple available networks.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED = 7;
+
+    /**
+     * The subscription is not valid. It must be an opportunistic subscription.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE = 8;
+
+    /**
+     * There is no OpportunisticNetworkService.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION = 9;
+
+    /**
+     * OpportunisticNetworkService is disabled.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10;
+
+    /**
      * Set preferred opportunistic data subscription id.
      *
      * Switch internet data to preferred opportunistic data subscription id. This api
@@ -11285,7 +11299,11 @@
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     executor.execute(() -> {
-                        callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+                        if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
+                            callback.accept(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
+                        } else {
+                            callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+                        }
                     });
                 } finally {
                     Binder.restoreCallingIdentity(identity);
@@ -11379,9 +11397,12 @@
                 if (iOpportunisticNetworkService == null) {
                     final long identity = Binder.clearCallingIdentity();
                     try {
-                        /* Todo<b/130595455> passing unknown due to lack of good error codes */
                         executor.execute(() -> {
-                            callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+                            if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
+                                callback.accept(UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION);
+                            } else {
+                                callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+                            }
                         });
                     } finally {
                         Binder.restoreCallingIdentity(identity);
@@ -11654,6 +11675,88 @@
     }
 
     /**
+     * Returns a list of APNs set as overrides by the device policy manager via
+     * {@link #addDevicePolicyOverrideApn}.
+     * This method must only be called from the system or phone processes.
+     *
+     * @param context Context to use.
+     * @return {@link List} of APNs that have been set as overrides.
+     * @throws {@link SecurityException} if the caller is not the system or phone process.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    // TODO: add new permission tag indicating that this is system-only.
+    public @NonNull List<ApnSetting> getDevicePolicyOverrideApns(@NonNull Context context) {
+        try (Cursor cursor = context.getContentResolver().query(DPC_URI, null, null, null, null)) {
+            if (cursor == null) {
+                return Collections.emptyList();
+            }
+            List<ApnSetting> apnList = new ArrayList<ApnSetting>();
+            cursor.moveToPosition(-1);
+            while (cursor.moveToNext()) {
+                ApnSetting apn = ApnSetting.makeApnSetting(cursor);
+                apnList.add(apn);
+            }
+            return apnList;
+        }
+    }
+
+    /**
+     * Used by the device policy manager to add a new override APN.
+     * This method must only be called from the system or phone processes.
+     *
+     * @param context Context to use.
+     * @param apnSetting The {@link ApnSetting} describing the new APN.
+     * @return An integer, corresponding to a primary key in a database, that allows the caller to
+     *         modify the APN in the future via {@link #modifyDevicePolicyOverrideApn}, or
+     *         {@link android.provider.Telephony.Carriers.INVALID_APN_ID} if the override operation
+     *         failed.
+     * @throws {@link SecurityException} if the caller is not the system or phone process.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    // TODO: add new permission tag indicating that this is system-only.
+    public int addDevicePolicyOverrideApn(@NonNull Context context,
+            @NonNull ApnSetting apnSetting) {
+        Uri resultUri = context.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
+
+        int resultId = INVALID_APN_ID;
+        if (resultUri != null) {
+            try {
+                resultId = Integer.parseInt(resultUri.getLastPathSegment());
+            } catch (NumberFormatException e) {
+                Rlog.e(TAG, "Failed to parse inserted override APN id: "
+                        + resultUri.getLastPathSegment());
+            }
+        }
+        return resultId;
+    }
+
+    /**
+     * Used by the device policy manager to modify an override APN.
+     * This method must only be called from the system or phone processes.
+     *
+     * @param context Context to use.
+     * @param apnId The integer key of the APN to modify, as returned by
+     *              {@link #addDevicePolicyOverrideApn}
+     * @param apnSetting The {@link ApnSetting} describing the updated APN.
+     * @return {@code true} if successful, {@code false} otherwise.
+     * @throws {@link SecurityException} if the caller is not the system or phone process.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    // TODO: add new permission tag indicating that this is system-only.
+    public boolean modifyDevicePolicyOverrideApn(@NonNull Context context, int apnId,
+            @NonNull ApnSetting apnSetting) {
+        return context.getContentResolver().update(
+                Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
+                apnSetting.toContentValues(), null, null) > 0;
+    }
+
+    /**
      * Return whether data is enabled for certain APN type. This will tell if framework will accept
      * corresponding network requests on a subId.
      *
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 60774e7..034fc22 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -20,7 +20,7 @@
 import android.annotation.Nullable;
 import android.content.ContentValues;
 import android.database.Cursor;
-import android.hardware.radio.V1_4.ApnTypes;
+import android.hardware.radio.V1_5.ApnTypes;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -110,6 +110,8 @@
     public static final int TYPE_EMERGENCY = ApnTypes.EMERGENCY;
     /** APN type for MCX (Mission Critical Service) where X can be PTT/Video/Data */
     public static final int TYPE_MCX = ApnTypes.MCX;
+    /** APN type for XCAP. */
+    public static final int TYPE_XCAP = ApnTypes.XCAP;
 
     // Possible values for authentication types.
     /** No authentication type. */
@@ -198,6 +200,7 @@
         APN_TYPE_STRING_MAP.put("ia", TYPE_IA);
         APN_TYPE_STRING_MAP.put("emergency", TYPE_EMERGENCY);
         APN_TYPE_STRING_MAP.put("mcx", TYPE_MCX);
+        APN_TYPE_STRING_MAP.put("xcap", TYPE_XCAP);
         APN_TYPE_INT_MAP = new ArrayMap<Integer, String>();
         APN_TYPE_INT_MAP.put(TYPE_DEFAULT, "default");
         APN_TYPE_INT_MAP.put(TYPE_MMS, "mms");
@@ -210,6 +213,7 @@
         APN_TYPE_INT_MAP.put(TYPE_IA, "ia");
         APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, "emergency");
         APN_TYPE_INT_MAP.put(TYPE_MCX, "mcx");
+        APN_TYPE_INT_MAP.put(TYPE_XCAP, "xcap");
 
         PROTOCOL_STRING_MAP = new ArrayMap<String, Integer>();
         PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP);
@@ -1944,8 +1948,9 @@
          * {@link ApnSetting} built from this builder otherwise.
          */
         public ApnSetting build() {
-            if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI |
-                    TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX)) == 0
+            if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI
+                    | TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
+                    | TYPE_XCAP)) == 0
                 || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
                 return null;
             }
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 30c209b..96a5a81 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.ApnType;
@@ -31,6 +30,7 @@
 import android.text.TextUtils;
 
 import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -261,7 +261,7 @@
     @Override
     public String toString() {
         return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType
-                + "/" + (Build.IS_USER ? "***/***/***" :
+                + "/" + (TelephonyUtils.IS_USER ? "***/***/***" :
                          (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
                 + mMaxConnectionsTime + "/" + mMaxConnections + "/"
                 + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/"
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index b0ff5dc..87e5391 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -833,7 +834,7 @@
         }
 
         int startSize = extras.size();
-        Bundle filtered = extras.filterValues();
+        Bundle filtered = TelephonyUtils.filterValues(extras);
         int endSize = filtered.size();
         if (startSize != endSize) {
             Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were "
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 47c4681..5adc99e 100644
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -1173,18 +1173,8 @@
         public void callSessionMergeComplete(IImsCallSession newSession) {
             if (mListener != null) {
                 if (newSession != null) {
-                    // Check if the active session is the same session that was
-                    // active before the merge request was sent.
-                    ImsCallSession validActiveSession = ImsCallSession.this;
-                    try {
-                        if (!Objects.equals(miSession.getCallId(), newSession.getCallId())) {
-                            // New session created after conference
-                            validActiveSession = new ImsCallSession(newSession);
-                        }
-                    } catch (RemoteException rex) {
-                        Log.e(TAG, "callSessionMergeComplete: exception for getCallId!");
-                    }
-                    mListener.callSessionMergeComplete(validActiveSession);
+                    // New session created after conference
+                    mListener.callSessionMergeComplete(new ImsCallSession(newSession));
                } else {
                    // Session already exists. Hence no need to pass
                    mListener.callSessionMergeComplete(null);
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 21707b0..0c8dba6 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -20,6 +20,8 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -30,6 +32,7 @@
 import android.telephony.ims.aidl.IImsRcsController;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
 import java.util.concurrent.Executor;
@@ -42,6 +45,8 @@
  * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this manager.
  * @hide
  */
+@SystemApi
+@TestApi
 public class ImsRcsManager implements RegistrationManager {
     private static final String TAG = "ImsRcsManager";
 
@@ -101,7 +106,7 @@
          *
          * @param capabilities The new availability of the capabilities.
          */
-        public void onAvailabilityChanged(RcsFeature.RcsImsCapabilities capabilities) {
+        public void onAvailabilityChanged(@NonNull RcsFeature.RcsImsCapabilities capabilities) {
         }
 
         /**@hide*/
@@ -138,6 +143,7 @@
 
     /**{@inheritDoc}*/
     @Override
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerImsRegistrationCallback(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull RegistrationCallback c)
@@ -155,6 +161,7 @@
 
     /**{@inheritDoc}*/
     @Override
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterImsRegistrationCallback(
             @NonNull RegistrationManager.RegistrationCallback c) {
         if (c == null) {
@@ -166,6 +173,7 @@
 
     /**{@inheritDoc}*/
     @Override
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
             @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
         if (stateCallback == null) {
@@ -180,6 +188,7 @@
 
     /**{@inheritDoc}*/
     @Override
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
             @NonNull @AccessNetworkConstants.TransportType
                     Consumer<Integer> transportTypeCallback) {
@@ -215,7 +224,7 @@
      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void registerRcsAvailabilityCallback(@CallbackExecutor Executor executor,
+    public void registerRcsAvailabilityCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull AvailabilityCallback c) throws ImsException {
         if (c == null) {
             throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
@@ -227,13 +236,13 @@
         IImsRcsController imsRcsController = getIImsRcsController();
         if (imsRcsController == null) {
             Log.e(TAG, "Register availability callback: IImsRcsController is null");
-            throw new ImsException("Can not find remote IMS service",
+            throw new ImsException("Cannot find remote IMS service",
                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
 
         c.setExecutor(executor);
         try {
-            imsRcsController.registerRcsAvailabilityCallback(c.getBinder());
+            imsRcsController.registerRcsAvailabilityCallback(mSubId, c.getBinder());
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e);
             throw new ImsException("Remote IMS Service is not available",
@@ -263,12 +272,12 @@
         IImsRcsController imsRcsController = getIImsRcsController();
         if (imsRcsController == null) {
             Log.e(TAG, "Unregister availability callback: IImsRcsController is null");
-            throw new ImsException("Can not find remote IMS service",
+            throw new ImsException("Cannot find remote IMS service",
                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
 
         try {
-            imsRcsController.unregisterRcsAvailabilityCallback(c.getBinder());
+            imsRcsController.unregisterRcsAvailabilityCallback(mSubId, c.getBinder());
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e);
             throw new ImsException("Remote IMS Service is not available",
@@ -283,6 +292,9 @@
      * RCS capabilities provided over-the-top by applications.
      *
      * @param capability The RCS capability to query.
+     * @param radioTech The radio tech that this capability failed for, defined as
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
+     * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}.
      * @return true if the RCS capability is capable for this subscription, false otherwise. This
      * does not necessarily mean that we are registered for IMS and the capability is available, but
      * rather the subscription is capable of this service over IMS.
@@ -293,17 +305,17 @@
      * See {@link ImsException#getCode()} for more information on the error codes.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability)
-            throws ImsException {
+    public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException {
         IImsRcsController imsRcsController = getIImsRcsController();
         if (imsRcsController == null) {
             Log.e(TAG, "isCapable: IImsRcsController is null");
-            throw new ImsException("Can not find remote IMS service",
+            throw new ImsException("Cannot find remote IMS service",
                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
 
         try {
-            return imsRcsController.isCapable(mSubId, capability);
+            return imsRcsController.isCapable(mSubId, capability, radioTech);
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling IImsRcsController#isCapable", e);
             throw new ImsException("Remote IMS Service is not available",
@@ -332,7 +344,7 @@
         IImsRcsController imsRcsController = getIImsRcsController();
         if (imsRcsController == null) {
             Log.e(TAG, "isAvailable: IImsRcsController is null");
-            throw new ImsException("Can not find remote IMS service",
+            throw new ImsException("Cannot find remote IMS service",
                     ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
 
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 76b214b..f4b2cef 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -889,6 +889,12 @@
      */
     public static final int CODE_WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 1623;
 
+    /**
+     * The dialed RTT call should be retried without RTT
+     * @hide
+     */
+    public static final int CODE_RETRY_ON_IMS_WITHOUT_RTT = 3001;
+
     /*
      * OEM specific error codes. To be used by OEMs when they don't want to reveal error code which
      * would be replaced by ERROR_UNSPECIFIED.
@@ -1069,6 +1075,7 @@
             CODE_REJECT_VT_AVPF_NOT_ALLOWED,
             CODE_REJECT_ONGOING_ENCRYPTED_CALL,
             CODE_REJECT_ONGOING_CS_CALL,
+            CODE_RETRY_ON_IMS_WITHOUT_RTT,
             CODE_OEM_CAUSE_1,
             CODE_OEM_CAUSE_2,
             CODE_OEM_CAUSE_3,
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index b379bd0..e81bac0 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -26,9 +26,9 @@
  * {@hide}
  */
 interface IImsRcsController {
-    void registerRcsAvailabilityCallback(IImsCapabilityCallback c);
-    void unregisterRcsAvailabilityCallback(IImsCapabilityCallback c);
-    boolean isCapable(int subId, int capability);
+    void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback c);
+    void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback c);
+    boolean isCapable(int subId, int capability, int radioTech);
     boolean isAvailable(int subId, int capability);
 
     // ImsUceAdapter specific
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index e96d082..501e0e8 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -193,7 +193,6 @@
      * of the capability and notify the capability status as true using
      * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
      * framework that the capability is available for usage.
-     * @hide
      */
     public static class RcsImsCapabilities extends Capabilities {
         /** @hide*/
@@ -207,7 +206,6 @@
 
         /**
          * Undefined capability type for initialization
-         * @hide
          */
         public static final int CAPABILITY_TYPE_NONE = 0;
 
@@ -215,7 +213,6 @@
          * 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.
-         * @hide
          */
         public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0;
 
@@ -224,33 +221,27 @@
          * 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.
-         * @hide
          */
         public static final int CAPABILITY_TYPE_PRESENCE_UCE =  1 << 1;
 
-        /**@hide*/
         public RcsImsCapabilities(@RcsImsCapabilityFlag int capabilities) {
             super(capabilities);
         }
 
-        /**@hide*/
         private RcsImsCapabilities(Capabilities c) {
             super(c.getMask());
         }
 
-        /**@hide*/
         @Override
         public void addCapabilities(@RcsImsCapabilityFlag int capabilities) {
             super.addCapabilities(capabilities);
         }
 
-        /**@hide*/
         @Override
         public void removeCapabilities(@RcsImsCapabilityFlag int capabilities) {
             super.removeCapabilities(capabilities);
         }
 
-        /**@hide*/
         @Override
         public boolean isCapable(@RcsImsCapabilityFlag int capabilities) {
             return super.isCapable(capabilities);
@@ -295,10 +286,9 @@
      * set, the {@link RcsFeature} has brought up the capability and is ready for framework
      * requests. To change the status of the capabilities
      * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called.
-     * @hide
      */
     @Override
-    public final RcsImsCapabilities queryCapabilityStatus() {
+    public @NonNull final RcsImsCapabilities queryCapabilityStatus() {
         return new RcsImsCapabilities(super.queryCapabilityStatus());
     }
 
@@ -306,7 +296,6 @@
      * Notify the framework that the capabilities status has changed. If a capability is enabled,
      * this signals to the framework that the capability has been initialized and is ready.
      * Call {@link #queryCapabilityStatus()} to return the current capability status.
-     * @hide
      */
     public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities c) {
         if (c == null) {
@@ -321,7 +310,6 @@
      * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} to
      * enable or disable capability A, this method should return the correct configuration for
      * capability A afterwards (until it has changed).
-     * @hide
      */
     public boolean queryCapabilityConfiguration(
             @RcsImsCapabilities.RcsImsCapabilityFlag int capability,
@@ -343,11 +331,10 @@
      * If for some reason one or more of these capabilities can not be enabled/disabled,
      * {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError(int, int, int)} should
      * be called for each capability change that resulted in an error.
-     * @hide
      */
     @Override
-    public void changeEnabledCapabilities(CapabilityChangeRequest request,
-            CapabilityCallbackProxy c) {
+    public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
+            @NonNull CapabilityCallbackProxy c) {
         // Base Implementation - Override to provide functionality
     }
 
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index d4ed923..0630454 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -31,7 +31,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
+import com.android.internal.telephony.util.ArrayUtils;
 import com.android.server.SystemConfig;
 
 import java.util.ArrayList;
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 8e50a8f..4e79660 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -26,7 +26,7 @@
     @UnsupportedAppUsage
     PersistableBundle getConfigForSubId(int subId, String callingPackage);
 
-    void overrideConfig(int subId, in PersistableBundle overrides);
+    void overrideConfig(int subId, in PersistableBundle overrides, boolean persistent);
 
     void notifyConfigChangedForSubId(int subId);
 
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index c1d700a..2dc59e6 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -1,29 +1,28 @@
 /*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 package com.android.internal.telephony;
 
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
 import com.android.internal.telephony.SmsRawData;
 
 /**
- * Interface for applications to access the ICC phone book.
+ * Service interface to handle SMS API requests
  *
  * See also SmsManager.java.
  */
@@ -543,6 +542,13 @@
                 in List<PendingIntent> deliveryIntents);
 
     /**
+     * Get carrier-dependent configuration values.
+     *
+     * @param subId the subscription Id
+     */
+    Bundle getCarrierConfigValuesForSubscriber(int subId);
+
+    /**
      * Create an app-only incoming SMS request for the calling package.
      *
      * If an incoming text contains the token returned by this method the provided
@@ -570,17 +576,6 @@
             int subId, String callingPkg, String prefixes, in PendingIntent intent);
 
     /**
-     * Get sms inbox messages for the calling financial app.
-     *
-     * @param subId the SIM id.
-     * @param callingPkg the package name of the calling app.
-     * @param params parameters to filter the sms messages.
-     * @param callback the callback interface to deliver the result.
-     */
-    void getSmsMessagesForFinancialApp(
-        int subId, String callingPkg, in Bundle params, in IFinancialSmsCallback callback);
-
-    /**
      * Check if the destination is a possible premium short code.
      *
      * @param destAddress the destination address to test for possible short code
@@ -605,4 +600,12 @@
      * @return true for success, false otherwise.
      */
     boolean setSmscAddressOnIccEfForSubscriber(String smsc, int subId, String callingPackage);
+
+    /**
+     * Get the capacity count of sms on Icc card.
+     *
+     * @param subId for subId which getSmsCapacityOnIcc is queried.
+     * @return capacity of ICC
+     */
+    int getSmsCapacityOnIccForSubscriber(int subId);
 }
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index ff816f2..98095bb 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -19,7 +19,6 @@
 import android.app.PendingIntent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.IFinancialSmsCallback;
 
 import java.util.List;
 
@@ -187,6 +186,11 @@
     }
 
     @Override
+    public Bundle getCarrierConfigValuesForSubscriber(int subId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public String createAppSpecificSmsToken(int subId, String callingPkg, PendingIntent intent) {
         throw new UnsupportedOperationException();
     }
@@ -198,12 +202,6 @@
     }
 
     @Override
-    public void getSmsMessagesForFinancialApp(
-            int subId, String callingPkg, Bundle params, IFinancialSmsCallback callback) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public int checkSmsShortCodeDestination(
             int subid, String callingApk, String destAddress, String countryIso) {
         throw new UnsupportedOperationException();
@@ -219,4 +217,9 @@
             String smsc, int subId, String callingPackage) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public int getSmsCapacityOnIccForSubscriber(int subId) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index eedfc6a..feb1368 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -301,7 +301,7 @@
      * operator's MCC (Mobile Country Code).
      * @see android.telephony.TelephonyManager#getNetworkCountryIso
      */
-    String getNetworkCountryIsoForPhone(int phoneId);
+    String getNetworkCountryIsoForPhone(int phoneId, String callingPkg);
 
     /**
      * Returns the neighboring cell information of the device.
@@ -858,12 +858,13 @@
     /**
     *  @return true if the ImsService to bind to for the slot id specified was set, false otherwise.
     */
-    boolean setImsService(int slotId, boolean isCarrierImsService, String packageName);
+    boolean setBoundImsServiceOverride(int slotIndex, boolean isCarrierService,
+            in int[] featureTypes, in String packageName);
 
     /**
     * @return the package name of the carrier/device ImsService associated with this slot.
     */
-    String getImsService(int slotId, boolean isCarrierImsService);
+    String getBoundImsServicePackage(int slotIndex, boolean isCarrierImsService, int featureType);
 
     /**
      * Get the MmTelFeature state attached to this subscription id.
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index 6ff27b1..25f03c2 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -15,6 +15,7 @@
  */
 package com.android.internal.telephony;
 
+import android.content.Intent;
 import android.telephony.TelephonyManager;
 
 import dalvik.annotation.compat.UnsupportedAppUsage;
@@ -25,37 +26,38 @@
 public class IccCardConstants {
 
     /* The extra data for broadcasting intent INTENT_ICC_STATE_CHANGE */
-    public static final String INTENT_KEY_ICC_STATE = "ss";
+    public static final String INTENT_KEY_ICC_STATE = Intent.EXTRA_SIM_STATE;
     /* UNKNOWN means the ICC state is unknown */
-    public static final String INTENT_VALUE_ICC_UNKNOWN = "UNKNOWN";
+    public static final String INTENT_VALUE_ICC_UNKNOWN = Intent.SIM_STATE_UNKNOWN;
     /* NOT_READY means the ICC interface is not ready (eg, radio is off or powering on) */
-    public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
+    public static final String INTENT_VALUE_ICC_NOT_READY = Intent.SIM_STATE_NOT_READY;
     /* ABSENT means ICC is missing */
-    public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+    public static final String INTENT_VALUE_ICC_ABSENT = Intent.SIM_STATE_ABSENT;
     /* PRESENT means ICC is present */
-    public static final String INTENT_VALUE_ICC_PRESENT = "PRESENT";
+    public static final String INTENT_VALUE_ICC_PRESENT = Intent.SIM_STATE_PRESENT;
     /* CARD_IO_ERROR means for three consecutive times there was SIM IO error */
-    static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR";
+    static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = Intent.SIM_STATE_CARD_IO_ERROR;
     /* CARD_RESTRICTED means card is present but not usable due to carrier restrictions */
-    static public final String INTENT_VALUE_ICC_CARD_RESTRICTED = "CARD_RESTRICTED";
+    static public final String INTENT_VALUE_ICC_CARD_RESTRICTED = Intent.SIM_STATE_CARD_RESTRICTED;
     /* LOCKED means ICC is locked by pin or by network */
-    public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
+    public static final String INTENT_VALUE_ICC_LOCKED = Intent.SIM_STATE_LOCKED;
     /* READY means ICC is ready to access */
-    public static final String INTENT_VALUE_ICC_READY = "READY";
+    public static final String INTENT_VALUE_ICC_READY = Intent.SIM_STATE_READY;
     /* IMSI means ICC IMSI is ready in property */
-    public static final String INTENT_VALUE_ICC_IMSI = "IMSI";
+    public static final String INTENT_VALUE_ICC_IMSI = Intent.SIM_STATE_IMSI;
     /* LOADED means all ICC records, including IMSI, are loaded */
-    public static final String INTENT_VALUE_ICC_LOADED = "LOADED";
+    public static final String INTENT_VALUE_ICC_LOADED = Intent.SIM_STATE_LOADED;
     /* The extra data for broadcasting intent INTENT_ICC_STATE_CHANGE */
-    public static final String INTENT_KEY_LOCKED_REASON = "reason";
+    public static final String INTENT_KEY_LOCKED_REASON = Intent.EXTRA_SIM_LOCKED_REASON;
     /* PIN means ICC is locked on PIN1 */
-    public static final String INTENT_VALUE_LOCKED_ON_PIN = "PIN";
+    public static final String INTENT_VALUE_LOCKED_ON_PIN = Intent.SIM_LOCKED_ON_PIN;
     /* PUK means ICC is locked on PUK1 */
-    public static final String INTENT_VALUE_LOCKED_ON_PUK = "PUK";
+    public static final String INTENT_VALUE_LOCKED_ON_PUK = Intent.SIM_LOCKED_ON_PUK;
     /* NETWORK means ICC is locked on NETWORK PERSONALIZATION */
-    public static final String INTENT_VALUE_LOCKED_NETWORK = "NETWORK";
+    public static final String INTENT_VALUE_LOCKED_NETWORK = Intent.SIM_LOCKED_NETWORK;
     /* PERM_DISABLED means ICC is permanently disabled due to puk fails */
-    public static final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
+    public static final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED =
+            Intent.SIM_ABSENT_ON_PERM_DISABLED;
 
     /**
      * This is combination of IccCardStatus.CardState and IccCardApplicationStatus.AppState
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java b/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java
index f7f0f29..8640acc 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java
@@ -16,14 +16,10 @@
 
 package com.android.internal.telephony;
 
-import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
-import android.telephony.PreciseCallState;
 
 import com.android.internal.telephony.PhoneConstants;
 
-import java.util.List;
-
 public class PhoneConstantConversions {
     /**
      * Convert the {@link PhoneConstants.State} enum into the TelephonyManager.CALL_STATE_*
@@ -67,6 +63,8 @@
                 return TelephonyManager.DATA_CONNECTED;
             case SUSPENDED:
                 return TelephonyManager.DATA_SUSPENDED;
+            case DISCONNECTING:
+                return TelephonyManager.DATA_DISCONNECTING;
             default:
                 return TelephonyManager.DATA_DISCONNECTED;
         }
@@ -84,6 +82,8 @@
                 return PhoneConstants.DataState.CONNECTED;
             case TelephonyManager.DATA_SUSPENDED:
                 return PhoneConstants.DataState.SUSPENDED;
+            case TelephonyManager.DATA_DISCONNECTING:
+                return PhoneConstants.DataState.DISCONNECTING;
             default:
                 return PhoneConstants.DataState.DISCONNECTED;
         }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index e4397cd..888746a 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -49,6 +49,7 @@
       * <ul>
       * <li>CONNECTED = IP traffic should be available</li>
       * <li>CONNECTING = Currently setting up data connection</li>
+      * <li>DISCONNECTING = IP temporarily available</li>
       * <li>DISCONNECTED = IP not available</li>
       * <li>SUSPENDED = connection is created but IP traffic is
       *                 temperately not available. i.e. voice call is in place
@@ -65,7 +66,8 @@
         @UnsupportedAppUsage
         DISCONNECTED,
         @UnsupportedAppUsage
-        SUSPENDED;
+        SUSPENDED,
+        DISCONNECTING;
     };
 
     public static final String STATE_KEY = "state";
@@ -98,20 +100,12 @@
 
     public static final String PHONE_NAME_KEY = "phoneName";
     public static final String DATA_NETWORK_TYPE_KEY = "networkType";
-    public static final String DATA_FAILURE_CAUSE_KEY = "failCause";
     public static final String DATA_APN_TYPE_KEY = "apnType";
     public static final String DATA_APN_KEY = "apn";
-    public static final String DATA_LINK_PROPERTIES_KEY = "linkProperties";
-    public static final String DATA_NETWORK_CAPABILITIES_KEY = "networkCapabilities";
 
-    public static final String DATA_IFACE_NAME_KEY = "iface";
-    public static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable";
-    public static final String DATA_NETWORK_ROAMING_KEY = "networkRoaming";
     public static final String PHONE_IN_ECM_STATE = "phoneinECMState";
     public static final String PHONE_IN_EMERGENCY_CALL = "phoneInEmergencyCall";
 
-    public static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged";
-
     /**
      * Return codes for supplyPinReturnResult and
      * supplyPukReturnResult APIs
@@ -161,6 +155,8 @@
     public static final String APN_TYPE_EMERGENCY = "emergency";
     /** APN type for Mission Critical Services */
     public static final String APN_TYPE_MCX = "mcx";
+    /** APN type for XCAP */
+    public static final String APN_TYPE_XCAP = "xcap";
     /** Array of all APN types */
     public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
             APN_TYPE_MMS,
@@ -172,7 +168,8 @@
             APN_TYPE_CBS,
             APN_TYPE_IA,
             APN_TYPE_EMERGENCY,
-            APN_TYPE_MCX
+            APN_TYPE_MCX,
+            APN_TYPE_XCAP,
     };
 
     public static final int RIL_CARD_MAX_APPS    = 8;
@@ -189,10 +186,6 @@
 
     public static final String SLOT_KEY  = "slot";
 
-    /** Fired when a subscriptions phone state changes. */
-    public static final String ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED =
-        "android.intent.action.SUBSCRIPTION_PHONE_STATE";
-
     // FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
     // FIXME: extensive, and see if this should be an array of all active subId's or ...?
     /**
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 03ea920..9cbcd7f 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -16,10 +16,12 @@
 
 package com.android.internal.telephony;
 
-import android.telephony.TelephonyManager;
+import android.sysprop.TelephonyProperties;
 
 import dalvik.annotation.compat.UnsupportedAppUsage;
 
+import java.util.Optional;
+
 /**
  * {@hide}
  */
@@ -233,8 +235,10 @@
     int NETWORK_MODE_NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 33;
 
     @UnsupportedAppUsage
-    int PREFERRED_NETWORK_MODE = Integer.parseInt(TelephonyManager.getTelephonyProperty(0,
-            "ro.telephony.default_network", Integer.toString(NETWORK_MODE_WCDMA_PREF)));
+    int PREFERRED_NETWORK_MODE = Optional.of(TelephonyProperties.default_network())
+            .filter(list -> !list.isEmpty())
+            .map(list -> list.get(0))
+            .orElse(NETWORK_MODE_WCDMA_PREF);
 
     int BAND_MODE_UNSPECIFIED = 0;      //"unspecified" (selected by baseband automatically)
     int BAND_MODE_EURO = 1;             //"EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
@@ -485,6 +489,8 @@
     int RIL_REQUEST_EMERGENCY_DIAL = 205;
     int RIL_REQUEST_GET_PHONE_CAPABILITY = 206;
     int RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG = 207;
+    int RIL_REQUEST_ENABLE_UICC_APPLICATIONS = 208;
+    int RIL_REQUEST_GET_UICC_APPLICATIONS_ENABLEMENT = 209;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -548,4 +554,5 @@
     int RIL_UNSOL_ICC_SLOT_STATUS = 1100;
     int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1101;
     int RIL_UNSOL_EMERGENCY_NUMBER_LIST = 1102;
+    int RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED = 1103;
 }
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index 2cdf2f6..d672642 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -18,19 +18,19 @@
 
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
-import android.os.Build;
 import android.telephony.Rlog;
 import android.util.SparseIntArray;
 
 import com.android.internal.telephony.cdma.sms.UserData;
-import com.android.internal.util.XmlUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.internal.telephony.util.XmlUtils;
 
 import dalvik.annotation.compat.UnsupportedAppUsage;
 
 public class Sms7BitEncodingTranslator {
     private static final String TAG = "Sms7BitEncodingTranslator";
     @UnsupportedAppUsage
-    private static final boolean DBG = Build.IS_DEBUGGABLE ;
+    private static final boolean DBG = TelephonyUtils.IS_DEBUGGABLE;
     private static boolean mIs7BitTranslationTableLoaded = false;
     private static SparseIntArray mTranslationTable = null;
     @UnsupportedAppUsage
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index d36d95b..e396f0c 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -18,13 +18,16 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
-import android.provider.Telephony;
 import android.telephony.SmsMessage;
+import android.text.TextUtils;
+import android.util.Patterns;
 
 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
 
 import java.text.BreakIterator;
 import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Base class declaring the specific methods and members for SmsMessage.
@@ -32,6 +35,10 @@
  */
 public abstract class SmsMessageBase {
 
+    // Copied from Telephony.Mms.NAME_ADDR_EMAIL_PATTERN
+    public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+            Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
     @UnsupportedAppUsage
     public SmsMessageBase() {
     }
@@ -356,6 +363,31 @@
         }
     }
 
+    private static String extractAddrSpec(String messageHeader) {
+        Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(messageHeader);
+
+        if (match.matches()) {
+            return match.group(2);
+        }
+        return messageHeader;
+    }
+
+    /**
+     * Returns true if the message header string indicates that the message is from a email address.
+     *
+     * @param messageHeader message header
+     * @return {@code true} if it's a message from an email address, {@code false} otherwise.
+     */
+    public static boolean isEmailAddress(String messageHeader) {
+        if (TextUtils.isEmpty(messageHeader)) {
+            return false;
+        }
+
+        String s = extractAddrSpec(messageHeader);
+        Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+        return match.matches();
+    }
+
     /**
      * Try to parse this message as an email gateway message
      * There are two ways specified in TS 23.040 Section 3.8 :
@@ -376,11 +408,11 @@
          * -or-
          * 2. [x@y][ ]/[body]
          */
-         String[] parts = mMessageBody.split("( /)|( )", 2);
-         if (parts.length < 2) return;
-         mEmailFrom = parts[0];
-         mEmailBody = parts[1];
-         mIsEmail = Telephony.Mms.isEmailAddress(mEmailFrom);
+        String[] parts = mMessageBody.split("( /)|( )", 2);
+        if (parts.length < 2) return;
+        mEmailFrom = parts[0];
+        mEmailBody = parts[1];
+        mIsEmail = isEmailAddress(mEmailFrom);
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 8b62872..8e1a78c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -225,41 +225,6 @@
     public static final String EXTRA_REBROADCAST_ON_UNLOCK= "rebroadcastOnUnlock";
 
     /**
-     * Broadcast Action: The time was set by the carrier (typically by the NITZ string).
-     * This is a sticky broadcast.
-     * The intent will have the following extra values:</p>
-     * <ul>
-     *   <li><em>time</em> - The time as a long in UTC milliseconds.</li>
-     * </ul>
-     *
-     * <p class="note">
-     * Requires the READ_PHONE_STATE permission.
-     *
-     * <p class="note">This is a protected intent that can only be sent
-     * by the system.
-     */
-    public static final String ACTION_NETWORK_SET_TIME = "android.intent.action.NETWORK_SET_TIME";
-
-
-    /**
-     * Broadcast Action: The timezone was set by the carrier (typically by the NITZ string).
-     * This is a sticky broadcast.
-     * The intent will have the following extra values:</p>
-     * <ul>
-     *   <li><em>time-zone</em> - The java.util.TimeZone.getID() value identifying the new time
-     *          zone.</li>
-     * </ul>
-     *
-     * <p class="note">
-     * Requires the READ_PHONE_STATE permission.
-     *
-     * <p class="note">This is a protected intent that can only be sent
-     * by the system.
-     */
-    public static final String ACTION_NETWORK_SET_TIMEZONE
-            = "android.intent.action.NETWORK_SET_TIMEZONE";
-
-    /**
      * <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
      * <p class="note">.
      * This is to pop up a notice to show user that the phone is in emergency callback mode
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 8b95617..1f7715b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -16,10 +16,8 @@
 
 package com.android.internal.telephony.cdma;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
-
 import android.content.res.Resources;
-import android.os.SystemProperties;
+import android.sysprop.TelephonyProperties;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.Rlog;
 import android.telephony.SmsCbLocation;
@@ -34,7 +32,6 @@
 import com.android.internal.telephony.SmsConstants;
 import com.android.internal.telephony.SmsHeader;
 import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.cdma.sms.BearerData;
 import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
 import com.android.internal.telephony.cdma.sms.CdmaSmsSubaddress;
@@ -862,7 +859,7 @@
         // TODO: Skip it for EF SMS(SUBMIT and DELIVER) because the IDD depends on current network?
         // 2) Adds the '+' prefix if TON is International
         // 3) Keeps the '+' if address starts with the '+'
-        String idd = SystemProperties.get(PROPERTY_OPERATOR_IDP_STRING, null);
+        String idd = TelephonyProperties.operator_idp_string().orElse(null);
         addr.address = new String(addr.origBytes);
         if (!TextUtils.isEmpty(idd) && addr.address.startsWith(idd)) {
             addr.address = "+" + addr.address.substring(idd.length());
@@ -940,14 +937,13 @@
         // msgId==0 is (sometimes?) treated specially by lower levels.
         // Specifically, the ID is not preserved for delivery ACKs.
         // Hence, avoid 0 -- constraining the range to 1..65535.
-        int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 1);
-        String nextMsgId = Integer.toString((msgId % 0xFFFF) + 1);
+        int msgId = TelephonyProperties.cdma_msg_id().orElse(1);
+        int nextMsgId = msgId % 0xFFFF + 1;
         try{
-            SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
+            TelephonyProperties.cdma_msg_id(nextMsgId);
             if (Rlog.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
-                Rlog.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
-                Rlog.d(LOG_TAG, "readback gets " +
-                        SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
+                Rlog.d(LOG_TAG, "next persist.radio.cdma.msgid = " + nextMsgId);
+                Rlog.d(LOG_TAG, "readback gets " + TelephonyProperties.cdma_msg_id().orElse(1));
             }
         } catch(RuntimeException ex) {
             Rlog.e(LOG_TAG, "set nextMessage ID failed: " + ex);
diff --git a/telephony/java/com/android/internal/telephony/util/ArrayUtils.java b/telephony/java/com/android/internal/telephony/util/ArrayUtils.java
new file mode 100644
index 0000000..2905125
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/ArrayUtils.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Objects;
+
+/** Utility methods for array operations. */
+public final class ArrayUtils {
+    private ArrayUtils() { /* cannot be instantiated */ }
+
+    /**
+     * Adds value to given array if not already present, providing set-like behavior.
+     */
+    @SuppressWarnings("unchecked")
+    public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
+        return appendElement(kind, array, element, false);
+    }
+
+    /**
+     * Adds value to given array.
+     */
+    @SuppressWarnings("unchecked")
+    public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
+            boolean allowDuplicates) {
+        final T[] result;
+        final int end;
+        if (array != null) {
+            if (!allowDuplicates && contains(array, element)) return array;
+            end = array.length;
+            result = (T[]) Array.newInstance(kind, end + 1);
+            System.arraycopy(array, 0, result, 0, end);
+        } else {
+            end = 0;
+            result = (T[]) Array.newInstance(kind, 1);
+        }
+        result[end] = element;
+        return result;
+    }
+
+    /**
+     * Combine multiple arrays into a single array.
+     *
+     * @param kind The class of the array elements
+     * @param arrays The arrays to combine
+     * @param <T> The class of the array elements (inferred from kind).
+     * @return A single array containing all the elements of the parameter arrays.
+     */
+    @SuppressWarnings("unchecked")
+    public static @NonNull <T> T[] concatElements(Class<T> kind, @Nullable T[]... arrays) {
+        if (arrays == null || arrays.length == 0) {
+            return createEmptyArray(kind);
+        }
+
+        int totalLength = 0;
+        for (T[] item : arrays) {
+            if (item == null) {
+                continue;
+            }
+
+            totalLength += item.length;
+        }
+
+        // Optimization for entirely empty arrays.
+        if (totalLength == 0) {
+            return createEmptyArray(kind);
+        }
+
+        final T[] all = (T[]) Array.newInstance(kind, totalLength);
+        int pos = 0;
+        for (T[] item : arrays) {
+            if (item == null || item.length == 0) {
+                continue;
+            }
+            System.arraycopy(item, 0, all, pos, item.length);
+            pos += item.length;
+        }
+        return all;
+    }
+
+    private static @NonNull <T> T[] createEmptyArray(Class<T> kind) {
+        if (kind == String.class) {
+            return (T[]) EmptyArray.STRING;
+        } else if (kind == Object.class) {
+            return (T[]) EmptyArray.OBJECT;
+        }
+
+        return (T[]) Array.newInstance(kind, 0);
+    }
+
+    private static final class EmptyArray {
+        private EmptyArray() {}
+
+        public static final Object[] OBJECT = new Object[0];
+        public static final String[] STRING = new String[0];
+    }
+
+    /**
+     * Checks if {@code value} is in {@code array}.
+     */
+    public static boolean contains(@Nullable char[] array, char value) {
+        if (array == null) return false;
+        for (char element : array) {
+            if (element == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if {@code value} is in {@code array}.
+     */
+    public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
+        return (cur != null) ? cur.contains(val) : false;
+    }
+
+    /**
+     * Checks if {@code value} is in {@code array}.
+     */
+    public static boolean contains(@Nullable int[] array, int value) {
+        if (array == null) return false;
+        for (int element : array) {
+            if (element == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if {@code value} is in {@code array}.
+     */
+    public static boolean contains(@Nullable long[] array, long value) {
+        if (array == null) return false;
+        for (long element : array) {
+            if (element == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if {@code value} is in {@code array}.
+     */
+    public static <T> boolean contains(@Nullable T[] array, T value) {
+        return indexOf(array, value) != -1;
+    }
+
+    /**
+     * Return first index of {@code value} in {@code array}, or {@code -1} if
+     * not found.
+     */
+    public static <T> int indexOf(@Nullable T[] array, T value) {
+        if (array == null) return -1;
+        for (int i = 0; i < array.length; i++) {
+            if (Objects.equals(array[i], value)) return i;
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
+    public static boolean isEmpty(@Nullable Collection<?> array) {
+        return array == null || array.isEmpty();
+    }
+
+    /**
+     * Checks if given map is null or has zero elements.
+     */
+    public static boolean isEmpty(@Nullable Map<?, ?> map) {
+        return map == null || map.isEmpty();
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
+    public static <T> boolean isEmpty(@Nullable T[] array) {
+        return array == null || array.length == 0;
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
+    public static boolean isEmpty(@Nullable int[] array) {
+        return array == null || array.length == 0;
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
+    public static boolean isEmpty(@Nullable long[] array) {
+        return array == null || array.length == 0;
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
+    public static boolean isEmpty(@Nullable byte[] array) {
+        return array == null || array.length == 0;
+    }
+
+    /**
+     * Checks if given array is null or has zero elements.
+     */
+    public static boolean isEmpty(@Nullable boolean[] array) {
+        return array == null || array.length == 0;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
new file mode 100644
index 0000000..0498d7c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+
+import java.io.PrintWriter;
+
+/**
+ * This class provides various util functions
+ */
+public final class TelephonyUtils {
+    public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
+    public static boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+    /**
+     * Verify that caller holds {@link android.Manifest.permission#DUMP}.
+     *
+     * @return true if access should be granted.
+     */
+    public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+        if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump " + tag + " from from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                    + " due to missing android.permission.DUMP permission");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /** Returns an empty string if the input is {@code null}. */
+    public static String emptyIfNull(@Nullable String str) {
+        return str == null ? "" : str;
+    }
+
+    /** Throws a {@link RuntimeException} that wrapps the {@link RemoteException}. */
+    public static RuntimeException rethrowAsRuntimeException(RemoteException remoteException) {
+        throw new RuntimeException(remoteException);
+    }
+
+    /**
+     * Returns a {@link ComponentInfo} from the {@link ResolveInfo},
+     * or throws an {@link IllegalStateException} if not available.
+     */
+    public static ComponentInfo getComponentInfo(@NonNull ResolveInfo resolveInfo) {
+        if (resolveInfo.activityInfo != null) return resolveInfo.activityInfo;
+        if (resolveInfo.serviceInfo != null) return resolveInfo.serviceInfo;
+        if (resolveInfo.providerInfo != null) return resolveInfo.providerInfo;
+        throw new IllegalStateException("Missing ComponentInfo!");
+    }
+
+    /**
+     * Filter values in bundle to only basic types.
+     */
+    public static Bundle filterValues(Bundle bundle) {
+        Bundle ret = new Bundle(bundle);
+        for (String key : bundle.keySet()) {
+            Object value = bundle.get(key);
+            if ((value instanceof Integer) || (value instanceof Long)
+                    || (value instanceof Double) || (value instanceof String)
+                    || (value instanceof int[]) || (value instanceof long[])
+                    || (value instanceof double[]) || (value instanceof String[])
+                    || (value instanceof PersistableBundle) || (value == null)
+                    || (value instanceof Boolean) || (value instanceof boolean[])) {
+                continue;
+            }
+            if (value instanceof Bundle) {
+                ret.putBundle(key, filterValues((Bundle) value));
+                continue;
+            }
+            if (value.getClass().getName().startsWith("android.")) {
+                continue;
+            }
+            ret.remove(key);
+        }
+        return ret;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/util/XmlUtils.java b/telephony/java/com/android/internal/telephony/util/XmlUtils.java
new file mode 100644
index 0000000..72c5d3a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/XmlUtils.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** Utility methods for XML operations. */
+public final class XmlUtils {
+    private XmlUtils() {}
+
+    /**
+     * Moves parser to the first start tag, and expects the tag name being {@code firstElementName}.
+     */
+    public static void beginDocument(XmlPullParser parser, String firstElementName)
+            throws XmlPullParserException, IOException {
+        int type;
+        while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+            // no-op
+        }
+
+        if (type != parser.START_TAG) {
+            throw new XmlPullParserException("No start tag found");
+        }
+
+        if (!parser.getName().equals(firstElementName)) {
+            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
+                    + ", expected " + firstElementName);
+        }
+    }
+
+    /**
+     * Moves parser to the next start tag.
+     */
+    public static void nextElement(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        int type;
+        while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
+            // no-op
+        }
+    }
+
+    /**
+     * Moves parser to the next start tag within the {@code outerDepth}.
+     */
+    public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
+            throws IOException, XmlPullParserException {
+        for (;;) {
+            int type = parser.next();
+            if (type == XmlPullParser.END_DOCUMENT
+                    || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
+                return false;
+            }
+            if (type == XmlPullParser.START_TAG && parser.getDepth() == outerDepth + 1) {
+                return true;
+            }
+        }
+    }
+}
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index aa4174a..616b6b0 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -30,6 +30,7 @@
     libs: [
         "framework-all",
         "app-compat-annotations",
+        "unsupportedappusage",
     ],
 
     api_packages: [
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index d433df5..d1da47f 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -25,6 +25,6 @@
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="directory-keys" value="/sdcard/flicker" />
         <option name="collect-on-run-ended-only" value="true" />
-        <option name="clean-up" value="false" />
+        <option name="clean-up" value="true" />
     </metrics_collector>
 </configuration>
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
new file mode 100644
index 0000000..16189c8
--- /dev/null
+++ b/tests/TelephonyCommonTests/Android.bp
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+    name: "TelephonyCommonTests",
+    srcs: [
+        ":framework-telephony-common-sources",
+        "**/*.java",
+    ],
+    static_libs: [
+        "mockito-target-extended",
+        "androidx.test.rules",
+        "truth-prebuilt",
+        "platform-test-annotations",
+        "androidx.core_core",
+        "androidx.fragment_fragment",
+        "androidx.test.ext.junit"
+    ],
+
+    jni_libs: ["libdexmakerjvmtiagent"],
+
+    // We need to rename SmsApplication to the test package or else it'll get clobbered by the
+    // hidden api checker
+    jarjar_rules: "jarjar-rules.txt",
+
+    // Uncomment this and comment out the jarjar rule if you want to attach a debugger and step
+    // through the renamed classes.
+    //platform_apis: true,
+
+    libs: [
+        "android.test.runner",
+        "android.test.mock",
+        "android.test.base",
+    ],
+}
diff --git a/apex/sdkext/framework/tests/AndroidManifest.xml b/tests/TelephonyCommonTests/AndroidManifest.xml
similarity index 64%
rename from apex/sdkext/framework/tests/AndroidManifest.xml
rename to tests/TelephonyCommonTests/AndroidManifest.xml
index 831f132..63f38c6 100644
--- a/apex/sdkext/framework/tests/AndroidManifest.xml
+++ b/tests/TelephonyCommonTests/AndroidManifest.xml
@@ -15,13 +15,16 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.sdkext.tests">
+          package="com.android.internal.telephony.tests"
+          android:debuggable="true">
 
-    <application>
+    <application android:label="TelephonyCommonTests"
+                 android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-            android:targetPackage="com.android.sdkext.tests" />
-
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.internal.telephony.tests"
+                     android:label="Telephony common tests"
+                     android:debuggable="true"/>
 </manifest>
diff --git a/tests/TelephonyCommonTests/AndroidTest.xml b/tests/TelephonyCommonTests/AndroidTest.xml
new file mode 100644
index 0000000..e9fdabc
--- /dev/null
+++ b/tests/TelephonyCommonTests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<configuration description="Runs Telephony Common 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="TelephonyCommonTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="TelephonyCommonTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.internal.telephony.tests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/TelephonyCommonTests/jarjar-rules.txt b/tests/TelephonyCommonTests/jarjar-rules.txt
new file mode 100644
index 0000000..fe34719
--- /dev/null
+++ b/tests/TelephonyCommonTests/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
new file mode 100644
index 0000000..6d0ee18
--- /dev/null
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.AppOpsManager;
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
+import android.provider.Telephony;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.SmsApplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Unit tests for the {@link SmsApplication} utility class
+ */
+@RunWith(AndroidJUnit4.class)
+public class SmsApplicationTest {
+    private static final ComponentName TEST_COMPONENT_NAME =
+            ComponentName.unflattenFromString("com.android.test/.TestSmsApp");
+    private static final String MMS_RECEIVER_NAME = "TestMmsReceiver";
+    private static final String RESPOND_VIA_SMS_NAME = "TestRespondViaSmsHandler";
+    private static final String SEND_TO_NAME = "TestSendTo";
+    private static final int SMS_APP_UID = 10001;
+
+    private static final int FAKE_PHONE_UID = 10002;
+    private static final int FAKE_MMS_UID = 10003;
+    private static final int FAKE_BT_UID = 10004;
+    private static final int FAKE_TELEPHONY_PROVIDER_UID = 10005;
+
+    private static final String[] APP_OPS_TO_CHECK = {
+            AppOpsManager.OPSTR_READ_SMS,
+            AppOpsManager.OPSTR_WRITE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_SMS,
+            AppOpsManager.OPSTR_RECEIVE_WAP_PUSH,
+            AppOpsManager.OPSTR_SEND_SMS,
+            AppOpsManager.OPSTR_READ_CELL_BROADCASTS
+    };
+
+    @Mock private Context mContext;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private RoleManager mRoleManager;
+    @Mock private PackageManager mPackageManager;
+    @Mock private AppOpsManager mAppOpsManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+        when(mContext.getSystemService(Context.ROLE_SERVICE)).thenReturn(mRoleManager);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
+        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+
+        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+                .when(mPackageManager)
+                .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(), anyInt());
+        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+                .when(mPackageManager)
+                .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(), anyInt());
+        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+                .when(mPackageManager)
+                .queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
+                        nullable(UserHandle.class));
+
+        when(mTelephonyManager.isSmsCapable()).thenReturn(true);
+        when(mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)).thenReturn(true);
+        when(mRoleManager.getDefaultSmsPackage(anyInt()))
+                .thenReturn(TEST_COMPONENT_NAME.getPackageName());
+
+        for (String opStr : APP_OPS_TO_CHECK) {
+            when(mAppOpsManager.unsafeCheckOp(
+                    opStr, SMS_APP_UID, TEST_COMPONENT_NAME.getPackageName()))
+                    .thenReturn(AppOpsManager.MODE_ALLOWED);
+        }
+    }
+
+    @Test
+    public void testGetDefaultSmsApplication() {
+        assertEquals(TEST_COMPONENT_NAME,
+                SmsApplication.getDefaultSmsApplicationAsUser(mContext, false, 0));
+    }
+
+    @Test
+    public void testGetDefaultSmsApplicationWithAppOpsFix() throws Exception {
+        when(mAppOpsManager.unsafeCheckOp(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID,
+                TEST_COMPONENT_NAME.getPackageName()))
+                .thenReturn(AppOpsManager.MODE_IGNORED);
+        setupPackageInfosForCoreApps();
+
+        assertEquals(TEST_COMPONENT_NAME,
+                SmsApplication.getDefaultSmsApplicationAsUser(mContext, true, 0));
+        verify(mAppOpsManager, atLeastOnce()).setUidMode(AppOpsManager.OPSTR_READ_SMS, SMS_APP_UID,
+                AppOpsManager.MODE_ALLOWED);
+    }
+
+    private void setupPackageInfosForCoreApps() throws Exception {
+        PackageInfo phonePackageInfo = new PackageInfo();
+        ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
+        phoneApplicationInfo.uid = FAKE_PHONE_UID;
+        phonePackageInfo.applicationInfo = phoneApplicationInfo;
+        when(mPackageManager.getPackageInfo(eq(SmsApplication.PHONE_PACKAGE_NAME), anyInt()))
+                .thenReturn(phonePackageInfo);
+
+        PackageInfo mmsPackageInfo = new PackageInfo();
+        ApplicationInfo mmsApplicationInfo = new ApplicationInfo();
+        mmsApplicationInfo.uid = FAKE_MMS_UID;
+        mmsPackageInfo.applicationInfo = mmsApplicationInfo;
+        when(mPackageManager.getPackageInfo(eq(SmsApplication.MMS_SERVICE_PACKAGE_NAME), anyInt()))
+                .thenReturn(mmsPackageInfo);
+
+        PackageInfo bluetoothPackageInfo = new PackageInfo();
+        ApplicationInfo bluetoothApplicationInfo = new ApplicationInfo();
+        bluetoothApplicationInfo.uid = FAKE_BT_UID;
+        bluetoothPackageInfo.applicationInfo = bluetoothApplicationInfo;
+        when(mPackageManager.getPackageInfo(eq(SmsApplication.BLUETOOTH_PACKAGE_NAME), anyInt()))
+                .thenReturn(bluetoothPackageInfo);
+
+        PackageInfo telephonyProviderPackageInfo = new PackageInfo();
+        ApplicationInfo telephonyProviderApplicationInfo = new ApplicationInfo();
+        telephonyProviderApplicationInfo.uid = FAKE_TELEPHONY_PROVIDER_UID;
+        telephonyProviderPackageInfo.applicationInfo = telephonyProviderApplicationInfo;
+        when(mPackageManager.getPackageInfo(
+                eq(SmsApplication.TELEPHONY_PROVIDER_PACKAGE_NAME), anyInt()))
+                .thenReturn(telephonyProviderPackageInfo);
+    }
+
+    private List<ResolveInfo> getResolveInfosForIntent(Intent intent) {
+        switch (intent.getAction()) {
+            case Telephony.Sms.Intents.SMS_DELIVER_ACTION:
+                return Collections.singletonList(makeSmsDeliverResolveInfo());
+            case Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION:
+                return Collections.singletonList(makeWapPushResolveInfo());
+            case TelephonyManager.ACTION_RESPOND_VIA_MESSAGE:
+                return Collections.singletonList(makeRespondViaMessageResolveInfo());
+            case Intent.ACTION_SENDTO:
+                return Collections.singletonList(makeSendToResolveInfo());
+        }
+        return Collections.emptyList();
+    }
+
+    private ApplicationInfo makeSmsApplicationInfo() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = SMS_APP_UID;
+        return applicationInfo;
+    }
+
+    private ResolveInfo makeSmsDeliverResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.applicationInfo = makeSmsApplicationInfo();
+
+        activityInfo.permission = Manifest.permission.BROADCAST_SMS;
+        activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        activityInfo.name = TEST_COMPONENT_NAME.getClassName();
+
+        info.activityInfo = activityInfo;
+        return info;
+    }
+
+    private ResolveInfo makeWapPushResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+
+        activityInfo.permission = Manifest.permission.BROADCAST_WAP_PUSH;
+        activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        activityInfo.name = MMS_RECEIVER_NAME;
+
+        info.activityInfo = activityInfo;
+        return info;
+    }
+
+    private ResolveInfo makeRespondViaMessageResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+
+        serviceInfo.permission = Manifest.permission.SEND_RESPOND_VIA_MESSAGE;
+        serviceInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        serviceInfo.name = RESPOND_VIA_SMS_NAME;
+
+        info.serviceInfo = serviceInfo;
+        return info;
+    }
+
+    private ResolveInfo makeSendToResolveInfo() {
+        ResolveInfo info = new ResolveInfo();
+        ActivityInfo activityInfo = new ActivityInfo();
+
+        activityInfo.packageName = TEST_COMPONENT_NAME.getPackageName();
+        activityInfo.name = SEND_TO_NAME;
+
+        info.activityInfo = activityInfo;
+        return info;
+    }
+}
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index ae8285b..a7eef05 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -16,7 +16,9 @@
 
 package android.net;
 
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
 import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
+import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -47,25 +49,22 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class LinkPropertiesTest {
-    private static final InetAddress ADDRV4 = InetAddresses.parseNumericAddress("75.208.6.1");
-    private static final InetAddress ADDRV6 = InetAddresses.parseNumericAddress(
-            "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
-    private static final InetAddress DNS1 = InetAddresses.parseNumericAddress("75.208.7.1");
-    private static final InetAddress DNS2 = InetAddresses.parseNumericAddress("69.78.7.1");
-    private static final InetAddress DNS6 = InetAddresses.parseNumericAddress(
-            "2001:4860:4860::8888");
-    private static final InetAddress PRIVDNS1 = InetAddresses.parseNumericAddress("1.1.1.1");
-    private static final InetAddress PRIVDNS2 = InetAddresses.parseNumericAddress("1.0.0.1");
-    private static final InetAddress PRIVDNS6 = InetAddresses.parseNumericAddress(
-            "2606:4700:4700::1111");
-    private static final InetAddress PCSCFV4 = InetAddresses.parseNumericAddress("10.77.25.37");
-    private static final InetAddress PCSCFV6 = InetAddresses.parseNumericAddress(
-            "2001:0db8:85a3:0000:0000:8a2e:0370:1");
-    private static final InetAddress GATEWAY1 = InetAddresses.parseNumericAddress("75.208.8.1");
-    private static final InetAddress GATEWAY2 = InetAddresses.parseNumericAddress("69.78.8.1");
-    private static final InetAddress GATEWAY61 = InetAddresses.parseNumericAddress(
-            "fe80::6:0000:613");
-    private static final InetAddress GATEWAY62 = InetAddresses.parseNumericAddress("fe80::6:2222");
+    private static final InetAddress ADDRV4 = address("75.208.6.1");
+    private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
+    private static final InetAddress DNS1 = address("75.208.7.1");
+    private static final InetAddress DNS2 = address("69.78.7.1");
+    private static final InetAddress DNS6 = address("2001:4860:4860::8888");
+    private static final InetAddress PRIVDNS1 = address("1.1.1.1");
+    private static final InetAddress PRIVDNS2 = address("1.0.0.1");
+    private static final InetAddress PRIVDNS6 = address("2606:4700:4700::1111");
+    private static final InetAddress PCSCFV4 = address("10.77.25.37");
+    private static final InetAddress PCSCFV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:1");
+    private static final InetAddress GATEWAY1 = address("75.208.8.1");
+    private static final InetAddress GATEWAY2 = address("69.78.8.1");
+    private static final InetAddress GATEWAY61 = address("fe80::6:0000:613");
+    private static final InetAddress GATEWAY62 = address("fe80::6:22%lo");
+    private static final InetAddress TESTIPV4ADDR = address("192.168.47.42");
+    private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43");
     private static final String NAME = "qmi0";
     private static final String DOMAINS = "google.com";
     private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
@@ -75,8 +74,7 @@
     private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
     private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
 
-    // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
-    private InetAddress Address(String addrString) {
+    private static InetAddress address(String addrString) {
         return InetAddresses.parseNumericAddress(addrString);
     }
 
@@ -228,7 +226,7 @@
         target.clear();
         target.setInterfaceName(NAME);
         // change link addresses
-        target.addLinkAddress(new LinkAddress(Address("75.208.6.2"), 32));
+        target.addLinkAddress(new LinkAddress(address("75.208.6.2"), 32));
         target.addLinkAddress(LINKADDRV6);
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
@@ -243,7 +241,7 @@
         target.addLinkAddress(LINKADDRV4);
         target.addLinkAddress(LINKADDRV6);
         // change dnses
-        target.addDnsServer(Address("75.208.7.2"));
+        target.addDnsServer(address("75.208.7.2"));
         target.addDnsServer(DNS2);
         target.addPcscfServer(PCSCFV6);
         target.addRoute(new RouteInfo(GATEWAY1));
@@ -255,10 +253,10 @@
         target.setInterfaceName(NAME);
         target.addLinkAddress(LINKADDRV4);
         target.addLinkAddress(LINKADDRV6);
-        target.addDnsServer(Address("75.208.7.2"));
+        target.addDnsServer(address("75.208.7.2"));
         target.addDnsServer(DNS2);
         // change pcscf
-        target.addPcscfServer(Address("2001::1"));
+        target.addPcscfServer(address("2001::1"));
         target.addRoute(new RouteInfo(GATEWAY1));
         target.addRoute(new RouteInfo(GATEWAY2));
         target.setMtu(MTU);
@@ -271,9 +269,9 @@
         target.addDnsServer(DNS1);
         target.addDnsServer(DNS2);
         // change gateway
-        target.addRoute(new RouteInfo(Address("75.208.8.2")));
-        target.addRoute(new RouteInfo(GATEWAY2));
+        target.addRoute(new RouteInfo(address("75.208.8.2")));
         target.setMtu(MTU);
+        target.addRoute(new RouteInfo(GATEWAY2));
         assertFalse(source.equals(target));
 
         target.clear();
@@ -349,7 +347,7 @@
 
     @Test
     public void testRouteInterfaces() {
-        LinkAddress prefix = new LinkAddress(Address("2001:db8::"), 32);
+        LinkAddress prefix = new LinkAddress(address("2001:db8::"), 32);
         InetAddress address = ADDRV6;
 
         // Add a route with no interface to a LinkProperties with no interface. No errors.
@@ -739,8 +737,7 @@
 
         // Add an on-link route, making the on-link DNS server reachable,
         // but there is still no IPv4 address.
-        assertTrue(v4lp.addRoute(new RouteInfo(
-                new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
+        assertTrue(v4lp.addRoute(new RouteInfo(new IpPrefix(address("75.208.0.0"), 16))));
         assertFalse(v4lp.isReachable(DNS1));
         assertFalse(v4lp.isReachable(DNS2));
 
@@ -756,9 +753,9 @@
         assertTrue(v4lp.isReachable(DNS2));
 
         final LinkProperties v6lp = new LinkProperties();
-        final InetAddress kLinkLocalDns = Address("fe80::6:1");
-        final InetAddress kLinkLocalDnsWithScope = Address("fe80::6:2%43");
-        final InetAddress kOnLinkDns = Address("2001:db8:85a3::53");
+        final InetAddress kLinkLocalDns = address("fe80::6:1");
+        final InetAddress kLinkLocalDnsWithScope = address("fe80::6:2%43");
+        final InetAddress kOnLinkDns = address("2001:db8:85a3::53");
         assertFalse(v6lp.isReachable(kLinkLocalDns));
         assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
         assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -767,7 +764,7 @@
         // Add a link-local route, making the link-local DNS servers reachable. Because
         // we assume the presence of an IPv6 link-local address, link-local DNS servers
         // are considered reachable, but only those with a non-zero scope identifier.
-        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("fe80::"), 64))));
+        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("fe80::"), 64))));
         assertFalse(v6lp.isReachable(kLinkLocalDns));
         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
         assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -783,7 +780,7 @@
         // Add a global route on link, but no global address yet. DNS servers reachable
         // via a route that doesn't require a gateway: give them the benefit of the
         // doubt and hope the link-local source address suffices for communication.
-        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("2001:db8:85a3::"), 64))));
+        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("2001:db8:85a3::"), 64))));
         assertFalse(v6lp.isReachable(kLinkLocalDns));
         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
         assertTrue(v6lp.isReachable(kOnLinkDns));
@@ -812,7 +809,7 @@
         stacked.setInterfaceName("v4-test0");
         v6lp.addStackedLink(stacked);
 
-        InetAddress stackedAddress = Address("192.0.0.4");
+        InetAddress stackedAddress = address("192.0.0.4");
         LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
         assertFalse(v6lp.isReachable(stackedAddress));
         stacked.addLinkAddress(stackedLinkAddress);
@@ -845,7 +842,7 @@
         LinkProperties rmnet1 = new LinkProperties();
         rmnet1.setInterfaceName("rmnet1");
         rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
-        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, Address("10.0.0.1"),
+        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, address("10.0.0.1"),
                 rmnet1.getInterfaceName());
         RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
                 rmnet1.getInterfaceName());
@@ -864,7 +861,7 @@
         rmnet2.setInterfaceName("rmnet2");
         rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
         rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
-        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, Address("2001:db8::1"),
+        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, address("2001:db8::1"),
                 rmnet2.getInterfaceName());
         RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
                 rmnet2.getInterfaceName());
@@ -930,24 +927,54 @@
     public void testLinkPropertiesParcelable() throws Exception {
         LinkProperties source = new LinkProperties();
         source.setInterfaceName(NAME);
-        // set 2 link addresses
+
         source.addLinkAddress(LINKADDRV4);
         source.addLinkAddress(LINKADDRV6);
-        // set 2 dnses
+
         source.addDnsServer(DNS1);
         source.addDnsServer(DNS2);
-        // set 2 gateways
+        source.addDnsServer(GATEWAY62);
+
+        source.addPcscfServer(TESTIPV4ADDR);
+        source.addPcscfServer(TESTIPV6ADDR);
+
+        source.setUsePrivateDns(true);
+        source.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);
+
+        source.setDomains(DOMAINS);
+
         source.addRoute(new RouteInfo(GATEWAY1));
         source.addRoute(new RouteInfo(GATEWAY2));
-        // set 2 validated private dnses
+
         source.addValidatedPrivateDnsServer(DNS6);
         source.addValidatedPrivateDnsServer(GATEWAY61);
+        source.addValidatedPrivateDnsServer(TESTIPV6ADDR);
+
+        source.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));
 
         source.setMtu(MTU);
 
+        source.setTcpBufferSizes(TCP_BUFFER_SIZES);
+
         source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
 
-        assertParcelingIsLossless(source);
+        source.setWakeOnLanSupported(true);
+
+        final LinkProperties stacked = new LinkProperties();
+        stacked.setInterfaceName("test-stacked");
+        source.addStackedLink(stacked);
+
+        assertParcelSane(source, 15 /* fieldCount */);
+    }
+
+    @Test
+    public void testLinkLocalDnsServerParceling() throws Exception {
+        final String strAddress = "fe80::1%lo";
+        final LinkProperties lp = new LinkProperties();
+        lp.addDnsServer(address(strAddress));
+        final LinkProperties unparceled = parcelingRoundTrip(lp);
+        // Inet6Address#equals does not test for the scope id
+        assertEquals(strAddress, unparceled.getDnsServers().get(0).getHostAddress());
     }
 
     @Test
diff --git a/tests/net/integration/AndroidManifest.xml b/tests/net/integration/AndroidManifest.xml
index 4dd3b5a..09c0e48 100644
--- a/tests/net/integration/AndroidManifest.xml
+++ b/tests/net/integration/AndroidManifest.xml
@@ -28,7 +28,9 @@
     <!-- Reading network status -->
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.NETWORK_FACTORY" />
+    <uses-permission android:name="android.permission.NETWORK_STACK" />
+    <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <!-- Reading DeviceConfig flags -->
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 25028fb..c4801aa 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -32,7 +32,6 @@
 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
 import android.net.NetworkRequest
 import android.net.TestNetworkStackClient
-import android.net.TetheringManager
 import android.net.metrics.IpConnectivityLog
 import android.os.ConditionVariable
 import android.os.IBinder
@@ -169,7 +168,6 @@
         val deps = spy(ConnectivityService.Dependencies())
         doReturn(networkStackClient).`when`(deps).networkStack
         doReturn(metricsLogger).`when`(deps).metricsLogger
-        doReturn(mock(TetheringManager::class.java)).`when`(deps).getTetheringManager()
         doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
         doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
         doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a24426b..b2d363e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -164,7 +164,6 @@
 import android.net.ResolverParamsParcel;
 import android.net.RouteInfo;
 import android.net.SocketKeepalive;
-import android.net.TetheringManager;
 import android.net.UidRange;
 import android.net.metrics.IpConnectivityLog;
 import android.net.shared.NetworkMonitorUtils;
@@ -1133,7 +1132,6 @@
         doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
         doReturn(mNetworkStack).when(deps).getNetworkStack();
         doReturn(systemProperties).when(deps).getSystemProperties();
-        doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager();
         doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
         doReturn(mMetricsService).when(deps).getMetricsLogger();
         doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
diff --git a/tools/localedata/extract_icu_data.py b/tools/localedata/extract_icu_data.py
index 6b4c346..ca1847a 100755
--- a/tools/localedata/extract_icu_data.py
+++ b/tools/localedata/extract_icu_data.py
@@ -176,6 +176,9 @@
     dump_representative_locales(representative_locales)
     return likely_script_dict
 
+def escape_script_variable_name(script):
+    """Escape characters, e.g. '~', in a C++ variable name"""
+    return script.replace("~", "_")
 
 def read_parent_data(icu_data_dir):
     """Read locale parent data from ICU data files."""
@@ -221,7 +224,7 @@
     for script in sorted_scripts:
         parent_dict = script_organized_dict[script]
         print ('const std::unordered_map<uint32_t, uint32_t> %s_PARENTS({'
-            % script.upper())
+            % escape_script_variable_name(script.upper()))
         for locale in sorted(parent_dict.keys()):
             parent = parent_dict[locale]
             print '    {0x%08Xu, 0x%08Xu}, // %s -> %s' % (
@@ -239,7 +242,7 @@
     for script in sorted_scripts:
         print "    {{'%c', '%c', '%c', '%c'}, &%s_PARENTS}," % (
             script[0], script[1], script[2], script[3],
-            script.upper())
+            escape_script_variable_name(script.upper()))
     print '};'