Merge "Handle 5G meteredness in telephony framework"
diff --git a/Android.bp b/Android.bp
index 7d95b9a..27f22bd 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",
]
}
@@ -370,6 +371,7 @@
"ext",
"unsupportedappusage",
"updatable_media_stubs",
+ "framework-tethering",
],
jarjar_rules: ":framework-jarjar-rules",
@@ -442,6 +444,7 @@
],
// For backwards compatibility.
stem: "framework",
+ apex_available: ["//apex_available:platform"],
}
// This "framework" module is NOT installed to the device. It's
@@ -459,10 +462,12 @@
installable: false, // this lib is a build-only library
static_libs: [
"framework-minus-apex",
+ "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 {
@@ -470,6 +475,7 @@
defaults: ["framework-defaults"],
srcs: [":framework-all-sources"],
installable: false,
+ apex_available: ["//apex_available:platform"],
}
java_library {
@@ -597,14 +603,31 @@
"core/java/com/android/internal/util/StateMachine.java",
"core/java/com/android/internal/util/TrafficStatsConstants.java",
"core/java/com/android/internal/util/WakeupMessage.java",
+ "core/java/com/android/internal/util/TokenBucket.java",
"core/java/android/net/shared/*.java",
],
}
+// 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/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",
+ "core/java/android/net/shared/Inet4AddressUtils.java",
+ ],
+}
+
+filegroup {
+ name: "framework-tethering-annotations",
+ srcs: [
+ "core/java/android/annotation/NonNull.java",
+ "core/java/android/annotation/SystemApi.java",
],
}
// Build ext.jar
@@ -914,653 +937,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: [
@@ -1629,6 +1005,8 @@
"core/java/android/util/LocalLog.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",
@@ -1639,3 +1017,20 @@
"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..d195047
--- /dev/null
+++ b/StubLibraries.bp
@@ -0,0 +1,325 @@
+// 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"],
+}
+
+/////////////////////////////////////////////////////////////////////
+// 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/apex/sdkext/Android.bp b/apex/sdkext/Android.bp
index 5369a96..f62f167 100644
--- a/apex/sdkext/Android.bp
+++ b/apex/sdkext/Android.bp
@@ -32,7 +32,7 @@
sdk {
name: "sdkext-sdk",
- java_libs: [ "framework-sdkext-stubs-systemapi" ],
+ java_header_libs: [ "framework-sdkext-stubs-systemapi" ],
}
apex_key {
diff --git a/apex/sdkext/derive_sdk/derive_sdk.cpp b/apex/sdkext/derive_sdk/derive_sdk.cpp
index 7536def..0a97116 100644
--- a/apex/sdkext/derive_sdk/derive_sdk.cpp
+++ b/apex/sdkext/derive_sdk/derive_sdk.cpp
@@ -63,6 +63,7 @@
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());
@@ -73,5 +74,6 @@
return EXIT_FAILURE;
}
+ LOG(INFO) << "R extension version is " << prop_value;
return EXIT_SUCCESS;
}
diff --git a/api/current.txt b/api/current.txt
index b33ab56..7e2b1c6 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
@@ -28130,7 +28327,10 @@
method public int getVideoHeight();
method public float getVideoPixelAspectRatio();
method public int getVideoWidth();
+ method public boolean isAudioDescription();
method public boolean isEncrypted();
+ method public boolean isHardOfHearing();
+ method public boolean isSpokenSubtitle();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR;
field public static final int TYPE_AUDIO = 0; // 0x0
@@ -28142,11 +28342,14 @@
ctor public TvTrackInfo.Builder(int, @NonNull String);
method public android.media.tv.TvTrackInfo build();
method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setAudioDescription(boolean);
method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
method public android.media.tv.TvTrackInfo.Builder setDescription(CharSequence);
method @NonNull public android.media.tv.TvTrackInfo.Builder setEncrypted(boolean);
method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setHardOfHearing(boolean);
method public android.media.tv.TvTrackInfo.Builder setLanguage(String);
+ method @NonNull public android.media.tv.TvTrackInfo.Builder setSpokenSubtitle(boolean);
method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
method public android.media.tv.TvTrackInfo.Builder setVideoFrameRate(float);
method public android.media.tv.TvTrackInfo.Builder setVideoHeight(int);
@@ -28458,6 +28661,37 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortal> CREATOR;
}
+ public class ConnectivityDiagnosticsManager {
+ method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+ method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+ field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
+ field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
+ }
+
+ public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
+ ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
+ method public void onConnectivityReport(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
+ method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
+ method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
+ }
+
+ public static class ConnectivityDiagnosticsManager.ConnectivityReport {
+ ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+ field @NonNull public final android.os.PersistableBundle additionalInfo;
+ field @NonNull public final android.net.LinkProperties linkProperties;
+ field @NonNull public final android.net.Network network;
+ field @NonNull public final android.net.NetworkCapabilities networkCapabilities;
+ field public final long reportTimestamp;
+ }
+
+ public static class ConnectivityDiagnosticsManager.DataStallReport {
+ ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.os.PersistableBundle);
+ field public final int detectionMethod;
+ field @NonNull public final android.net.Network network;
+ field public final long reportTimestamp;
+ field @NonNull public final android.os.PersistableBundle stallDetails;
+ }
+
public class ConnectivityManager {
method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public boolean bindProcessToNetwork(@Nullable android.net.Network);
@@ -28691,6 +28925,7 @@
method public boolean addRoute(@NonNull android.net.RouteInfo);
method public void clear();
method public int describeContents();
+ method @Nullable public java.net.Inet4Address getDhcpServerAddress();
method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
method @Nullable public String getDomains();
method @Nullable public android.net.ProxyInfo getHttpProxy();
@@ -28702,6 +28937,7 @@
method @NonNull public java.util.List<android.net.RouteInfo> getRoutes();
method public boolean isPrivateDnsActive();
method public boolean isWakeOnLanSupported();
+ method public void setDhcpServerAddress(@Nullable java.net.Inet4Address);
method public void setDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
method public void setDomains(@Nullable String);
method public void setHttpProxy(@Nullable android.net.ProxyInfo);
@@ -28814,14 +29050,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
@@ -28915,6 +29162,7 @@
method public android.net.NetworkRequest.Builder addCapability(int);
method public android.net.NetworkRequest.Builder addTransportType(int);
method public android.net.NetworkRequest build();
+ method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
method public android.net.NetworkRequest.Builder removeCapability(int);
method public android.net.NetworkRequest.Builder removeTransportType(int);
method public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
@@ -30708,6 +30956,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";
@@ -30716,6 +30965,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";
@@ -30726,6 +30976,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
@@ -30781,8 +31034,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);
@@ -35002,7 +35258,9 @@
method public int describeContents();
method @Nullable public android.os.PersistableBundle getPersistableBundle(@Nullable String);
method public void putPersistableBundle(@Nullable String, @Nullable android.os.PersistableBundle);
+ method @NonNull public static android.os.PersistableBundle readFromStream(@NonNull java.io.InputStream) throws java.io.IOException;
method public void writeToParcel(android.os.Parcel, int);
+ method public void writeToStream(@NonNull java.io.OutputStream) throws java.io.IOException;
field @NonNull public static final android.os.Parcelable.Creator<android.os.PersistableBundle> CREATOR;
field public static final android.os.PersistableBundle EMPTY;
}
@@ -35016,11 +35274,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";
@@ -42358,6 +42617,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;
@@ -43878,19 +44138,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";
@@ -44191,7 +44459,9 @@
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";
@@ -44232,6 +44502,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";
@@ -44317,6 +44589,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.";
}
@@ -44750,6 +45027,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>);
@@ -44757,12 +45035,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
@@ -44770,14 +45051,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();
@@ -44837,6 +45130,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
}
@@ -44845,7 +45139,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);
@@ -45054,6 +45348,7 @@
public class SubscriptionManager {
method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void addOnSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
@@ -45281,6 +45576,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";
@@ -45335,6 +45631,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
@@ -45351,8 +45649,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
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
index 7a379d56..07a4ef4 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -596,6 +596,7 @@
public class StatusBarManager {
method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
+ method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSimNetworkLock(boolean);
}
public static final class StatusBarManager.DisableInfo {
@@ -1162,6 +1163,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);
@@ -1411,6 +1413,14 @@
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
}
+ public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile {
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
+ method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
+ field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
+ }
+
public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
method protected void finalize();
method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
@@ -1428,6 +1438,7 @@
public class BluetoothPbap implements android.bluetooth.BluetoothProfile {
method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
}
@@ -1543,6 +1554,7 @@
field public static final String EUICC_CARD_SERVICE = "euicc_card";
field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final String NETD_SERVICE = "netd";
+ field public static final String NETWORK_POLICY_SERVICE = "netpolicy";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
field public static final String PERMISSION_SERVICE = "permission";
@@ -1554,6 +1566,7 @@
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";
@@ -1573,6 +1586,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";
@@ -3227,9 +3241,17 @@
}
public class UsbManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List<android.hardware.usb.UsbPort> getPorts();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
+ field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
+ field public static final long FUNCTION_NONE = 0L; // 0x0L
+ field public static final long FUNCTION_RNDIS = 32L; // 0x20L
+ field public static final String USB_CONFIGURED = "configured";
+ field public static final String USB_CONNECTED = "connected";
+ field public static final String USB_FUNCTION_RNDIS = "rndis";
}
public final class UsbPort {
@@ -3730,6 +3752,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
@@ -3969,6 +3992,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();
@@ -4083,12 +4115,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);
@@ -4319,12 +4353,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();
@@ -4339,6 +4381,14 @@
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 boolean satisfiedBy(android.net.NetworkSpecifier);
+ 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();
@@ -4348,6 +4398,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
}
@@ -4396,6 +4448,12 @@
method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>);
}
+ public abstract class NetworkSpecifier {
+ method public void assertValidFromUid(int);
+ method @Nullable public android.net.NetworkSpecifier redact();
+ method public abstract boolean satisfiedBy(@Nullable android.net.NetworkSpecifier);
+ }
+
public class NetworkStack {
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
@@ -4463,6 +4521,15 @@
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 boolean satisfiedBy(android.net.NetworkSpecifier);
+ 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();
@@ -5331,6 +5398,10 @@
field public int numUsage;
}
+ public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
+ }
+
public class WifiScanner {
method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]);
method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
@@ -5495,6 +5566,10 @@
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
+ public final class WifiAwareNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public boolean satisfiedBy(android.net.NetworkSpecifier);
+ }
+
public static final class WifiAwareNetworkSpecifier.Builder {
method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPmk(@NonNull byte[]);
}
@@ -5986,6 +6061,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
@@ -6070,11 +6146,13 @@
public class UpdateEngine {
ctor public UpdateEngine();
+ method @NonNull public android.os.UpdateEngine.AllocateSpaceResult allocateSpace(@NonNull String, @NonNull String[]);
method public void applyPayload(String, long, long, String[]);
method public void applyPayload(@NonNull android.os.ParcelFileDescriptor, long, long, @NonNull String[]);
method public boolean bind(android.os.UpdateEngineCallback, android.os.Handler);
method public boolean bind(android.os.UpdateEngineCallback);
method public void cancel();
+ method public int cleanupAppliedPayload();
method public void resetStatus();
method public void resume();
method public void suspend();
@@ -6082,14 +6160,21 @@
method public boolean verifyPayloadMetadata(String);
}
+ public static final class UpdateEngine.AllocateSpaceResult {
+ method public int errorCode();
+ method public long freeSpaceRequired();
+ }
+
public static final class UpdateEngine.ErrorCodeConstants {
ctor public UpdateEngine.ErrorCodeConstants();
+ field public static final int DEVICE_CORRUPTED = 61; // 0x3d
field public static final int DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 12; // 0xc
field public static final int DOWNLOAD_TRANSFER_ERROR = 9; // 0x9
field public static final int ERROR = 1; // 0x1
field public static final int FILESYSTEM_COPIER_ERROR = 4; // 0x4
field public static final int INSTALL_DEVICE_OPEN_ERROR = 7; // 0x7
field public static final int KERNEL_DEVICE_OPEN_ERROR = 8; // 0x8
+ field public static final int NOT_ENOUGH_SPACE = 60; // 0x3c
field public static final int PAYLOAD_HASH_MISMATCH_ERROR = 10; // 0xa
field public static final int PAYLOAD_MISMATCHED_TYPE_ERROR = 6; // 0x6
field public static final int PAYLOAD_SIZE_MISMATCH_ERROR = 11; // 0xb
@@ -6634,6 +6719,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";
@@ -6705,7 +6791,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";
@@ -7831,6 +7919,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();
@@ -7902,6 +7991,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);
@@ -7937,6 +8027,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);
}
@@ -7949,6 +8046,12 @@
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);
}
@@ -8424,6 +8527,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();
@@ -8522,28 +8643,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();
@@ -8563,13 +8679,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 {
@@ -8670,6 +8785,9 @@
}
public class ServiceState implements android.os.Parcelable {
+ method @NonNull public android.telephony.ServiceState createLocationInfoSanitizedCopy(boolean);
+ method public void fillInNotifierBundle(@NonNull android.os.Bundle);
+ method public int getDataRegistrationState();
method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int);
@@ -8677,6 +8795,7 @@
method public int getNrFrequencyRange();
method @Nullable public String getOperatorAlphaLongRaw();
method @Nullable public String getOperatorAlphaShortRaw();
+ method @NonNull public static android.telephony.ServiceState newFromBundle(@NonNull android.os.Bundle);
field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
@@ -8808,11 +8927,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();
@@ -8820,6 +8941,8 @@
public class SubscriptionManager {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription();
+ method public boolean canManageSubscription(@Nullable android.telephony.SubscriptionInfo, @Nullable String);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String);
method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int);
@@ -8831,6 +8954,8 @@
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);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(boolean, int);
+ 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
@@ -8871,6 +8996,7 @@
}
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 public int checkCarrierPrivilegesForPackage(String);
method public int checkCarrierPrivilegesForPackageAnyPhone(String);
@@ -8897,6 +9023,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();
@@ -8931,15 +9058,17 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isManualNetworkSelectionAllowed();
method public boolean isModemEnabledForSlot(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetheringApnRequired();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_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();
@@ -8977,6 +9106,7 @@
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";
diff --git a/api/test-current.txt b/api/test-current.txt
index 44498dd..8de2bec 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -352,6 +352,7 @@
public class StatusBarManager {
method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
+ method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSimNetworkLock(boolean);
}
public static final class StatusBarManager.DisableInfo {
@@ -3004,6 +3005,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);
@@ -3036,14 +3041,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 @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);
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 b4dbd1d..0000000
--- a/cmds/svc/src/com/android/commands/svc/DataCommand.java
+++ /dev/null
@@ -1,46 +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;
-
-/**
- * @deprecated Please use adb shell cmd phone data enabled/disable instead.
- */
-@Deprecated
-public class DataCommand extends Svc.Command {
-
- private static final String DECPRECATED_MESSAGE =
- "adb shell svc data enable/disable is deprecated;"
- + "please use adb shell cmd phone data enable/disable instead.";
-
- public DataCommand() {
- super("data");
- }
-
- public String shortHelp() {
- return "Control mobile data connectivity";
- }
-
- public String longHelp() {
- return shortHelp() + "\n"
- + "\n"
- + DECPRECATED_MESSAGE;
- }
-
- public void run(String[] args) {
- System.err.println(DECPRECATED_MESSAGE);
- }
-}
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 9061ed1..1987440 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -25,8 +25,8 @@
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;
@@ -35,7 +35,6 @@
import com.android.internal.os.BaseCommand;
import com.android.internal.telecom.ITelecomService;
-import com.android.internal.telephony.TelephonyProperties;
import java.io.PrintStream;
@@ -363,7 +362,7 @@
* "" (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 {
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 2ac8409..773942c 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -14142,7 +14142,6 @@
HSPLandroid/telephony/ServiceState;->copyFrom(Landroid/telephony/ServiceState;)V
HSPLandroid/telephony/ServiceState;->describeContents()I
HSPLandroid/telephony/ServiceState;->equals(Ljava/lang/Object;)Z
-HSPLandroid/telephony/ServiceState;->fillInNotifierBundle(Landroid/os/Bundle;)V
HSPLandroid/telephony/ServiceState;->getCdmaDefaultRoamingIndicator()I
HSPLandroid/telephony/ServiceState;->getCdmaEriIconIndex()I
HSPLandroid/telephony/ServiceState;->getCdmaEriIconMode()I
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/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 28413be..dc24467 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -153,6 +153,11 @@
*/
public static final int DEFAULT_SETUP_DISABLE2_FLAGS = DISABLE2_ROTATE_SUGGESTIONS;
+ /**
+ * disable flags to be applied when the device is sim-locked.
+ */
+ private static final int DEFAULT_SIM_LOCKED_DISABLED_FLAGS = DISABLE_EXPAND;
+
/** @hide */
public static final int NAVIGATION_HINT_BACK_ALT = 1 << 0;
/** @hide */
@@ -385,6 +390,30 @@
}
/**
+ * Enable or disable expansion of the status bar. When the device is SIM-locked, the status
+ * bar should not be expandable.
+ *
+ * @param disabled If {@code true}, the status bar will be set to non-expandable. If
+ * {@code false}, re-enables expansion of the status bar.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.STATUS_BAR)
+ public void setDisabledForSimNetworkLock(boolean disabled) {
+ try {
+ final int userId = Binder.getCallingUserHandle().getIdentifier();
+ final IStatusBarService svc = getService();
+ if (svc != null) {
+ svc.disableForUser(disabled ? DEFAULT_SIM_LOCKED_DISABLED_FLAGS : DISABLE_NONE,
+ mToken, mContext.getPackageName(), userId);
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Get this app's currently requested disabled components
*
* @return a new DisableInfo
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index c56e8d8..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
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/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index 9877fc7..de8f470 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -17,6 +17,7 @@
package android.app.timedetector;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
/**
@@ -35,4 +36,5 @@
interface ITimeDetectorService {
void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
void suggestManualTime(in ManualTimeSuggestion timeSuggestion);
+ void suggestNetworkTime(in NetworkTimeSuggestion timeSuggestion);
}
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/core/java/android/app/timedetector/NetworkTimeSuggestion.aidl
similarity index 73%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to core/java/android/app/timedetector/NetworkTimeSuggestion.aidl
index d502088..731c907 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.aidl
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package android.app.timedetector;
-import android.net.Network;
-
-/**
- * Callback class for receiving tethering changed events
- * @hide
- */
-oneway interface ITetheringEventCallback
-{
- void onUpstreamChanged(in Network network);
-}
+parcelable NetworkTimeSuggestion;
diff --git a/core/java/android/app/timedetector/NetworkTimeSuggestion.java b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
new file mode 100644
index 0000000..4c55ba1
--- /dev/null
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.TimestampedValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A time signal from a network time source like NTP. The value consists of the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime
+ * clock when that number was established. The elapsed realtime clock is considered accurate but
+ * volatile, so time signals must not be persisted across device resets.
+ *
+ * @hide
+ */
+public final class NetworkTimeSuggestion implements Parcelable {
+
+ public static final @NonNull Creator<NetworkTimeSuggestion> CREATOR =
+ new Creator<NetworkTimeSuggestion>() {
+ public NetworkTimeSuggestion createFromParcel(Parcel in) {
+ return NetworkTimeSuggestion.createFromParcel(in);
+ }
+
+ public NetworkTimeSuggestion[] newArray(int size) {
+ return new NetworkTimeSuggestion[size];
+ }
+ };
+
+ @NonNull
+ private final TimestampedValue<Long> mUtcTime;
+ @Nullable
+ private ArrayList<String> mDebugInfo;
+
+ public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
+ mUtcTime = Objects.requireNonNull(utcTime);
+ Objects.requireNonNull(utcTime.getValue());
+ }
+
+ private static NetworkTimeSuggestion createFromParcel(Parcel in) {
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
+ NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(utcTime);
+ @SuppressWarnings("unchecked")
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
+ suggestion.mDebugInfo = debugInfo;
+ return suggestion;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mUtcTime, 0);
+ dest.writeList(mDebugInfo);
+ }
+
+ @NonNull
+ public TimestampedValue<Long> getUtcTime() {
+ return mUtcTime;
+ }
+
+ @NonNull
+ public List<String> getDebugInfo() {
+ return mDebugInfo == null
+ ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(String... debugInfos) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.addAll(Arrays.asList(debugInfos));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ NetworkTimeSuggestion that = (NetworkTimeSuggestion) o;
+ return Objects.equals(mUtcTime, that.mUtcTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUtcTime);
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkTimeSuggestion{"
+ + "mUtcTime=" + mUtcTime
+ + ", mDebugInfo=" + mDebugInfo
+ + '}';
+ }
+}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 48d5cd2..af9ece0 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);
@@ -85,4 +85,19 @@
manualTimeSuggestion.addDebugInfo(why);
return manualTimeSuggestion;
}
+
+ /**
+ * Suggests the time according to a network time source like NTP.
+ */
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
+ public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
+ if (DEBUG) {
+ Log.d(TAG, "suggestNetworkTime called: " + timeSuggestion);
+ }
+ try {
+ mITimeDetectorService.suggestNetworkTime(timeSuggestion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
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/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index b4521c6..a65162a 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -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
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 8f5cdf0..c1233b8 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -17,9 +17,12 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Binder;
@@ -43,6 +46,7 @@
*
* @hide
*/
+@SystemApi
public final class BluetoothHidHost implements BluetoothProfile {
private static final String TAG = "BluetoothHidHost";
private static final boolean DBG = true;
@@ -66,6 +70,7 @@
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
* receive.
*/
+ @SuppressLint("ActionValue")
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
@@ -325,7 +330,7 @@
* {@inheritDoc}
*/
@Override
- public List<BluetoothDevice> getConnectedDevices() {
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
@@ -342,6 +347,8 @@
/**
* {@inheritDoc}
+ *
+ * @hide
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
@@ -363,7 +370,7 @@
* {@inheritDoc}
*/
@Override
- public int getConnectionState(BluetoothDevice device) {
+ public int getConnectionState(@Nullable BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -409,7 +416,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 IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -457,7 +464,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public int getConnectionPolicy(BluetoothDevice device) {
+ public int getConnectionPolicy(@Nullable BluetoothDevice device) {
if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index df02896..2910150 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -16,7 +16,10 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -271,6 +274,42 @@
}
/**
+ * Pbap does not store connection policy, so this function only disconnects Pbap if
+ * connectionPolicy is CONNECTION_POLICY_FORBIDDEN.
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if pbap is successfully disconnected, false otherwise
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+ @ConnectionPolicy int connectionPolicy) {
+ if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+ try {
+ final IBluetoothPbap service = mService;
+ if (service != null && isEnabled()
+ && isValidDevice(device)) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
* 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.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 39a7115..f359641 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.
@@ -3909,6 +3918,7 @@
*/
public static final String NETWORK_STATS_SERVICE = "netstats";
/** {@hide} */
+ @SystemApi
public static final String NETWORK_POLICY_SERVICE = "netpolicy";
/** {@hide} */
public static final String NETWORK_WATCHLIST_SERVICE = "network_watchlist";
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 e9a4762..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
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index cc5d3b1..3e10a6c 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -17,7 +17,7 @@
package android.database;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Build;
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
index a988f068..daf7d2b 100644
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ b/core/java/android/database/AbstractWindowedCursor.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A base class for Cursors that store their data in {@link CursorWindow}s.
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index 77a13cf..8ea450c 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java
index 798b783..69ca581 100644
--- a/core/java/android/database/ContentObserver.java
+++ b/core/java/android/database/ContentObserver.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 6873577..063a2d0 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -17,7 +17,7 @@
package android.database;
import android.annotation.BytesLong;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.database.sqlite.SQLiteClosable;
import android.database.sqlite.SQLiteException;
diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java
index c9cafaf..4496f80 100644
--- a/core/java/android/database/CursorWrapper.java
+++ b/core/java/android/database/CursorWrapper.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Bundle;
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 992da31..4246b84 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -17,7 +17,7 @@
package android.database;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index b0d399c..050a49a 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -16,7 +16,7 @@
package android.database;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.util.ArrayList;
diff --git a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
index 2af06e1..ba546f3 100644
--- a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
+++ b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* An exception that indicates that garbage-collector is finalizing a database object
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index d6a71da..2fca729 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -16,7 +16,8 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.Closeable;
/**
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index e3c4098..4559e91 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.AbstractWindowedCursor;
import android.database.CursorWindow;
import android.database.DatabaseUtils;
diff --git a/core/java/android/database/sqlite/SQLiteCustomFunction.java b/core/java/android/database/sqlite/SQLiteCustomFunction.java
index 41b78d3..1ace40d 100644
--- a/core/java/android/database/sqlite/SQLiteCustomFunction.java
+++ b/core/java/android/database/sqlite/SQLiteCustomFunction.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index caf3e93..7a0e183 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -20,9 +20,9 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index fcdaf0a..6a52b72 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.ArrayList;
import java.util.Locale;
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index 3d0ac61..165f863 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -17,14 +17,13 @@
package android.database.sqlite;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Process;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Printer;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.ArrayList;
/**
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 62cec0e..943afc7 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.SQLException;
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 8304133..de1c543 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.DatabaseUtils;
import android.os.CancellationSignal;
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 5890179..02c8a97 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.DatabaseUtils;
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index a9ac9e7..24b62b8 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.database.CursorWindow;
import android.database.DatabaseUtils;
import android.os.CancellationSignal;
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 42e7ac7..9fda8b0 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -16,7 +16,7 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
/**
diff --git a/core/java/android/database/sqlite/SqliteWrapper.java b/core/java/android/database/sqlite/SqliteWrapper.java
index e317164..f335fbd 100644
--- a/core/java/android/database/sqlite/SqliteWrapper.java
+++ b/core/java/android/database/sqlite/SqliteWrapper.java
@@ -17,12 +17,11 @@
package android.database.sqlite;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
index 9560787..e6fb4ec 100644
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ b/core/java/android/ddm/DdmHandleAppName.java
@@ -16,11 +16,13 @@
package android.ddm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.util.Log;
+
import org.apache.harmony.dalvik.ddmc.Chunk;
import org.apache.harmony.dalvik.ddmc.ChunkHandler;
import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Log;
+
import java.nio.ByteBuffer;
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 33e51c9..c847f86 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -16,14 +16,20 @@
package android.hardware;
-import static android.system.OsConstants.*;
+import static android.system.OsConstants.EACCES;
+import static android.system.OsConstants.EBUSY;
+import static android.system.OsConstants.EINVAL;
+import static android.system.OsConstants.ENODEV;
+import static android.system.OsConstants.ENOSYS;
+import static android.system.OsConstants.EOPNOTSUPP;
+import static android.system.OsConstants.EUSERS;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index c569e05..6779751 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.LongDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.GraphicBuffer;
import android.os.Build;
import android.os.Parcel;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e78fb7f..a71a7b6 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -18,7 +18,7 @@
package android.hardware;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 8c910b2..64c45bf 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -16,7 +16,7 @@
package android.hardware;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* This class represents a {@link android.hardware.Sensor Sensor} event and
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 3250428..6036d79 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -18,7 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index 571c3cc..b51382e 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -17,7 +17,7 @@
package android.hardware;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
diff --git a/core/java/android/hardware/SerialPort.java b/core/java/android/hardware/SerialPort.java
index 78ac3c0..0fcaa49 100644
--- a/core/java/android/hardware/SerialPort.java
+++ b/core/java/android/hardware/SerialPort.java
@@ -16,12 +16,11 @@
package android.hardware;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelFileDescriptor;
import java.io.FileDescriptor;
import java.io.IOException;
-
import java.nio.ByteBuffer;
/**
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 7abfabf..974913b 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -16,7 +16,7 @@
package android.hardware;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 27c04b4..2333251 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -16,8 +16,8 @@
package android.hardware.biometrics;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
/**
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index b025508..5c74456 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -16,8 +16,8 @@
package android.hardware.biometrics;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.fingerprint.FingerprintManager;
/**
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 48588e6..c697d4c 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
import android.hardware.camera2.impl.SyntheticKey;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 6a2fc8a..d027de8 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.PublicKey;
import android.hardware.camera2.impl.SyntheticKey;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index ba451e5..af05b29 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.impl.PublicKey;
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index e909c00..706aa4ef 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -16,12 +16,11 @@
package android.hardware.camera2.impl;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.marshal.MarshalQueryable;
@@ -52,7 +51,6 @@
import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.MandatoryStreamCombination;
-import android.hardware.camera2.params.MandatoryStreamCombination.MandatoryStreamInformation;
import android.hardware.camera2.params.OisSample;
import android.hardware.camera2.params.RecommendedStreamConfiguration;
import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
index 526f086..16f3f2a 100644
--- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
+++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.utils;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Provide hashing functions using the Modified Bernstein hash
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index d3c4505..abe1372 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.utils;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.ImageFormat;
import android.hardware.camera2.legacy.LegacyCameraDevice;
import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
diff --git a/core/java/android/hardware/camera2/utils/TypeReference.java b/core/java/android/hardware/camera2/utils/TypeReference.java
index d9ba31b..435ed15 100644
--- a/core/java/android/hardware/camera2/utils/TypeReference.java
+++ b/core/java/android/hardware/camera2/utils/TypeReference.java
@@ -16,7 +16,10 @@
package android.hardware.camera2.utils;
-import android.annotation.UnsupportedAppUsage;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
@@ -24,8 +27,6 @@
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
-import static com.android.internal.util.Preconditions.*;
-
/**
* Super type token; allows capturing generic types at runtime by forcing them to be reified.
*
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 0b25dbd..799dff9 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -23,8 +23,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Point;
import android.media.projection.MediaProjection;
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index ea63776..2a58495 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index 55e6051..5bbbbf9 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -16,7 +16,7 @@
package android.hardware.display;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/hardware/display/WifiDisplayStatus.java b/core/java/android/hardware/display/WifiDisplayStatus.java
index 1973e51..e2a825f 100644
--- a/core/java/android/hardware/display/WifiDisplayStatus.java
+++ b/core/java/android/hardware/display/WifiDisplayStatus.java
@@ -16,7 +16,7 @@
package android.hardware.display;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d0622c8..315af32 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -26,8 +26,8 @@
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 0c0f248..8d32db0 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -20,7 +20,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Binder;
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 23d8d01..a1866af 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -16,7 +16,7 @@
package android.hardware.location;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.location.Location;
import android.os.Build;
import android.os.RemoteException;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index f96f47d..2f0265a 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -25,8 +25,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioFormat;
import android.os.Handler;
import android.os.Parcel;
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index 9113548..694d605 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -16,7 +16,7 @@
package android.hardware.soundtrigger;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 08c9eea..fdb4cc07 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 71297c1..215ac24 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index eb148b9..67fdda3 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -26,8 +26,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -91,7 +91,7 @@
*
* {@hide}
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final String ACTION_USB_STATE =
"android.hardware.usb.action.USB_STATE";
@@ -164,7 +164,7 @@
*
* {@hide}
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final String USB_CONNECTED = "connected";
/**
@@ -181,6 +181,7 @@
*
* {@hide}
*/
+ @SystemApi
public static final String USB_CONFIGURED = "configured";
/**
@@ -217,6 +218,7 @@
*
* {@hide}
*/
+ @SystemApi
public static final String USB_FUNCTION_RNDIS = "rndis";
/**
@@ -319,6 +321,7 @@
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
* {@hide}
*/
+ @SystemApi
public static final long FUNCTION_NONE = 0;
/**
@@ -337,6 +340,7 @@
* Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
* {@hide}
*/
+ @SystemApi
public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
/**
@@ -698,6 +702,8 @@
*
* {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
public void setCurrentFunctions(long functions) {
try {
mService.setCurrentFunctions(functions);
@@ -737,6 +743,8 @@
*
* {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
public long getCurrentFunctions() {
try {
return mService.getCurrentFunctions();
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index 7abf3e9..fab2c0b 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -17,7 +17,7 @@
package android.hardware.usb;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.util.Log;
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 7d4849f..9327b24 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -16,7 +16,7 @@
package android.inputmethodservice;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index a47f601..69b93b1 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -18,7 +18,7 @@
import android.annotation.BinderThread;
import android.annotation.MainThread;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 82d4d1d..44825a8 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -30,9 +30,9 @@
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Dialog;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 3f25113..c85fcd9 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -16,8 +16,8 @@
package android.inputmethodservice;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.XmlRes;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 45f067b..b780b21 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -16,7 +16,7 @@
package android.inputmethodservice;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
new file mode 100644
index 0000000..6afdb5e
--- /dev/null
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * Class that provides utilities for collecting network connectivity diagnostics information.
+ * Connectivity information is made available through triggerable diagnostics tools and by listening
+ * to System validations. Some diagnostics information may be permissions-restricted.
+ *
+ * <p>ConnectivityDiagnosticsManager is intended for use by applications offering network
+ * connectivity on a user device. These tools will provide several mechanisms for these applications
+ * to be alerted to network conditions as well as diagnose potential network issues themselves.
+ *
+ * <p>The primary responsibilities of this class are to:
+ *
+ * <ul>
+ * <li>Allow permissioned applications to register and unregister callbacks for network event
+ * notifications
+ * <li>Invoke callbacks for network event notifications, including:
+ * <ul>
+ * <li>Network validations
+ * <li>Data stalls
+ * <li>Connectivity reports from applications
+ * </ul>
+ * </ul>
+ */
+public class ConnectivityDiagnosticsManager {
+ public static final int DETECTION_METHOD_DNS_EVENTS = 1;
+ public static final int DETECTION_METHOD_TCP_METRICS = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = {"DETECTION_METHOD_"},
+ value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS})
+ public @interface DetectionMethod {}
+
+ /** @hide */
+ public ConnectivityDiagnosticsManager() {}
+
+ /** Class that includes connectivity information for a specific Network at a specific time. */
+ public static class ConnectivityReport {
+ /** The Network for which this ConnectivityReport applied */
+ @NonNull public final Network network;
+
+ /**
+ * The timestamp for the report. The timestamp is taken from {@link
+ * System#currentTimeMillis}.
+ */
+ public final long reportTimestamp;
+
+ /** LinkProperties available on the Network at the reported timestamp */
+ @NonNull public final LinkProperties linkProperties;
+
+ /** NetworkCapabilities available on the Network at the reported timestamp */
+ @NonNull public final NetworkCapabilities networkCapabilities;
+
+ /** PersistableBundle that may contain additional info about the report */
+ @NonNull public final PersistableBundle additionalInfo;
+
+ /**
+ * Constructor for ConnectivityReport.
+ *
+ * <p>Apps should obtain instances through {@link
+ * ConnectivityDiagnosticsCallback#onConnectivityReport} instead of instantiating their own
+ * instances (unless for testing purposes).
+ *
+ * @param network The Network for which this ConnectivityReport applies
+ * @param reportTimestamp The timestamp for the report
+ * @param linkProperties The LinkProperties available on network at reportTimestamp
+ * @param networkCapabilities The NetworkCapabilities available on network at
+ * reportTimestamp
+ * @param additionalInfo A PersistableBundle that may contain additional info about the
+ * report
+ */
+ public ConnectivityReport(
+ @NonNull Network network,
+ long reportTimestamp,
+ @NonNull LinkProperties linkProperties,
+ @NonNull NetworkCapabilities networkCapabilities,
+ @NonNull PersistableBundle additionalInfo) {
+ this.network = network;
+ this.reportTimestamp = reportTimestamp;
+ this.linkProperties = linkProperties;
+ this.networkCapabilities = networkCapabilities;
+ this.additionalInfo = additionalInfo;
+ }
+ }
+
+ /** Class that includes information for a suspected data stall on a specific Network */
+ public static class DataStallReport {
+ /** The Network for which this DataStallReport applied */
+ @NonNull public final Network network;
+
+ /**
+ * The timestamp for the report. The timestamp is taken from {@link
+ * System#currentTimeMillis}.
+ */
+ public final long reportTimestamp;
+
+ /** The detection method used to identify the suspected data stall */
+ @DetectionMethod public final int detectionMethod;
+
+ /** PersistableBundle that may contain additional information on the suspected data stall */
+ @NonNull public final PersistableBundle stallDetails;
+
+ /**
+ * Constructor for DataStallReport.
+ *
+ * <p>Apps should obtain instances through {@link
+ * ConnectivityDiagnosticsCallback#onDataStallSuspected} instead of instantiating their own
+ * instances (unless for testing purposes).
+ *
+ * @param network The Network for which this DataStallReport applies
+ * @param reportTimestamp The timestamp for the report
+ * @param detectionMethod The detection method used to identify this data stall
+ * @param stallDetails A PersistableBundle that may contain additional info about the report
+ */
+ public DataStallReport(
+ @NonNull Network network,
+ long reportTimestamp,
+ @DetectionMethod int detectionMethod,
+ @NonNull PersistableBundle stallDetails) {
+ this.network = network;
+ this.reportTimestamp = reportTimestamp;
+ this.detectionMethod = detectionMethod;
+ this.stallDetails = stallDetails;
+ }
+ }
+
+ /**
+ * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
+ * network connectivity events. Must be extended by applications wanting notifications.
+ */
+ public abstract static class ConnectivityDiagnosticsCallback {
+ /**
+ * Called when the platform completes a data connectivity check. This will also be invoked
+ * upon registration with the latest report.
+ *
+ * <p>The Network specified in the ConnectivityReport may not be active any more when this
+ * method is invoked.
+ *
+ * @param report The ConnectivityReport containing information about a connectivity check
+ */
+ public void onConnectivityReport(@NonNull ConnectivityReport report) {}
+
+ /**
+ * Called when the platform suspects a data stall on some Network.
+ *
+ * <p>The Network specified in the DataStallReport may not be active any more when this
+ * method is invoked.
+ *
+ * @param report The DataStallReport containing information about the suspected data stall
+ */
+ public void onDataStallSuspected(@NonNull DataStallReport report) {}
+
+ /**
+ * Called when any app reports connectivity to the System.
+ *
+ * @param network The Network for which connectivity has been reported
+ * @param hasConnectivity The connectivity reported to the System
+ */
+ public void onNetworkConnectivityReported(
+ @NonNull Network network, boolean hasConnectivity) {}
+ }
+
+ /**
+ * Registers a ConnectivityDiagnosticsCallback with the System.
+ *
+ * <p>Only apps that offer network connectivity to the user are allowed to register callbacks.
+ * This includes:
+ *
+ * <ul>
+ * <li>Carrier apps with active subscriptions
+ * <li>Active VPNs
+ * <li>WiFi Suggesters
+ * </ul>
+ *
+ * <p>Callbacks will be limited to receiving notifications for networks over which apps provide
+ * connectivity.
+ *
+ * <p>If a registering app loses its relevant permissions, any callbacks it registered will
+ * silently stop receiving callbacks.
+ *
+ * <p>Each register() call <b>MUST</b> use a unique ConnectivityDiagnosticsCallback instance. If
+ * a single instance is registered with multiple NetworkRequests, an IllegalArgumentException
+ * will be thrown.
+ *
+ * @param request The NetworkRequest that will be used to match with Networks for which
+ * callbacks will be fired
+ * @param e The Executor to be used for running the callback method invocations
+ * @param callback The ConnectivityDiagnosticsCallback that the caller wants registered with the
+ * System
+ * @throws IllegalArgumentException if the same callback instance is registered with multiple
+ * NetworkRequests
+ * @throws SecurityException if the caller does not have appropriate permissions to register a
+ * callback
+ */
+ public void registerConnectivityDiagnosticsCallback(
+ @NonNull NetworkRequest request,
+ @NonNull Executor e,
+ @NonNull ConnectivityDiagnosticsCallback callback) {
+ // TODO(b/143187964): implement ConnectivityDiagnostics functionality
+ throw new UnsupportedOperationException("registerCallback() not supported yet");
+ }
+
+ /**
+ * Unregisters a ConnectivityDiagnosticsCallback with the System.
+ *
+ * <p>If the given callback is not currently registered with the System, this operation will be
+ * a no-op.
+ *
+ * @param callback The ConnectivityDiagnosticsCallback to be unregistered from the System.
+ */
+ public void unregisterConnectivityDiagnosticsCallback(
+ @NonNull ConnectivityDiagnosticsCallback callback) {
+ // TODO(b/143187964): implement ConnectivityDiagnostics functionality
+ throw new UnsupportedOperationException("registerCallback() not supported yet");
+ }
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a6e070e..6806d78 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -27,8 +27,8 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.net.IpSecManager.UdpEncapsulationSocket;
@@ -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/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 97be51a..059cd94 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.shared.InetAddressUtils;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 7256502..fd015b4 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,7 +17,7 @@
package android.net;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
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 1ae44e1..37425ff 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java
index dddb64d..23d5ff7 100644
--- a/core/java/android/net/IpConfiguration.java
+++ b/core/java/android/net/IpConfiguration.java
@@ -20,8 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
-import android.net.StaticIpConfiguration;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 93dd2e4..bf8b38f 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -30,7 +30,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 8e18341..2792c56 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -63,6 +63,7 @@
private String mPrivateDnsServerName;
private String mDomains;
private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
+ private Inet4Address mDhcpServerAddress;
private ProxyInfo mHttpProxy;
private int mMtu;
// in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
@@ -74,6 +75,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<>();
@@ -194,6 +197,7 @@
addStackedLink(l);
}
setMtu(source.mMtu);
+ setDhcpServerAddress(source.getDhcpServerAddress());
mTcpBufferSizes = source.mTcpBufferSizes;
mNat64Prefix = source.mNat64Prefix;
mWakeOnLanSupported = source.mWakeOnLanSupported;
@@ -227,7 +231,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 +251,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 +346,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());
@@ -458,6 +462,24 @@
}
/**
+ * Set DHCP server address.
+ *
+ * @param serverAddress the server address to set.
+ */
+ public void setDhcpServerAddress(@Nullable Inet4Address serverAddress) {
+ mDhcpServerAddress = serverAddress;
+ }
+
+ /**
+ * Get DHCP server address
+ *
+ * @return The current DHCP server address.
+ */
+ public @Nullable Inet4Address getDhcpServerAddress() {
+ return mDhcpServerAddress;
+ }
+
+ /**
* Returns the private DNS server name that is in use. If not {@code null},
* private DNS is in strict mode. In this mode, applications should ensure
* that all DNS queries are encrypted and sent to this hostname and that
@@ -542,6 +564,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 +752,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()) {
@@ -848,6 +871,7 @@
mHttpProxy = null;
mStackedLinks.clear();
mMtu = 0;
+ mDhcpServerAddress = null;
mTcpBufferSizes = null;
mNat64Prefix = null;
mWakeOnLanSupported = false;
@@ -916,6 +940,11 @@
resultJoiner.add("WakeOnLanSupported: true");
}
+ if (mDhcpServerAddress != null) {
+ resultJoiner.add("ServerAddress:");
+ resultJoiner.add(mDhcpServerAddress.toString());
+ }
+
if (mTcpBufferSizes != null) {
resultJoiner.add("TcpBufferSizes:");
resultJoiner.add(mTcpBufferSizes);
@@ -1025,7 +1054,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 +1111,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 +1139,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) {
@@ -1270,6 +1299,17 @@
}
/**
+ * Compares this {@code LinkProperties} DHCP server address against the target
+ *
+ * @param target LinkProperties to compare.
+ * @return {@code true} if both are identical, {@code false} otherwise.
+ * @hide
+ */
+ public boolean isIdenticalDhcpServerAddress(@NonNull LinkProperties target) {
+ return Objects.equals(mDhcpServerAddress, target.mDhcpServerAddress);
+ }
+
+ /**
* Compares this {@code LinkProperties} interface addresses against the target
*
* @param target LinkProperties to compare.
@@ -1486,6 +1526,7 @@
*/
return isIdenticalInterfaceName(target)
&& isIdenticalAddresses(target)
+ && isIdenticalDhcpServerAddress(target)
&& isIdenticalDnses(target)
&& isIdenticalPrivateDns(target)
&& isIdenticalValidatedPrivateDnses(target)
@@ -1610,6 +1651,7 @@
+ mMtu * 51
+ ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
+ (mUsePrivateDns ? 57 : 0)
+ + ((null == mDhcpServerAddress) ? 0 : mDhcpServerAddress.hashCode())
+ mPcscfs.size() * 67
+ ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
+ Objects.hash(mNat64Prefix)
@@ -1626,21 +1668,13 @@
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);
+ writeAddress(dest, mDhcpServerAddress);
dest.writeInt(mMtu);
dest.writeString(mTcpBufferSizes);
dest.writeInt(mRoutes.size());
@@ -1662,6 +1696,38 @@
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, @Nullable InetAddress addr) {
+ byte[] addressBytes = (addr == null ? null : addr.getAddress());
+ dest.writeByteArray(addressBytes);
+ if (addr instanceof Inet6Address) {
+ final Inet6Address v6Addr = (Inet6Address) addr;
+ final boolean hasScopeId = v6Addr.getScopeId() != 0;
+ dest.writeBoolean(hasScopeId);
+ if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
+ }
+ }
+
+ @Nullable
+ private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
+ final byte[] addr = p.createByteArray();
+ if (addr == null) return null;
+
+ 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 +1747,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,10 +1761,14 @@
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());
+ try {
+ netProp.setDhcpServerAddress((Inet4Address) InetAddress
+ .getByAddress(in.createByteArray()));
+ } catch (UnknownHostException e) { }
netProp.setMtu(in.readInt());
netProp.setTcpBufferSizes(in.readString());
addressCount = in.readInt();
diff --git a/core/java/android/net/LinkQualityInfo.java b/core/java/android/net/LinkQualityInfo.java
index 2e6915f..aa56cff 100644
--- a/core/java/android/net/LinkQualityInfo.java
+++ b/core/java/android/net/LinkQualityInfo.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 6a2031b..5b38f78 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -16,7 +16,8 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index b066a15..e80e3a6 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Int32Ref;
import android.system.Os;
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 8729514..74c9aac 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import android.os.Parcelable;
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/MobileLinkQualityInfo.java b/core/java/android/net/MobileLinkQualityInfo.java
index a10a14d..a65de6b 100644
--- a/core/java/android/net/MobileLinkQualityInfo.java
+++ b/core/java/android/net/MobileLinkQualityInfo.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index f12ba13..8d1ab33 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.system.ErrnoException;
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index ff4bf2d..60bd573 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -17,7 +17,7 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 88877e2..a5e567d 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Build;
import android.os.Parcel;
@@ -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/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index 5b1d12c..42ab925 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 92f105f..d0c5363 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -17,7 +17,7 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 33baebb..4f05c9b 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 628dcd2..53854c2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,8 +19,8 @@
import static android.content.pm.PackageManager.GET_SIGNATURES;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java
index a46cdde..2e52d9c 100644
--- a/core/java/android/net/NetworkQuotaInfo.java
+++ b/core/java/android/net/NetworkQuotaInfo.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 471b23e..c7b3009 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
import android.net.NetworkCapabilities.Transport;
import android.os.Build;
@@ -247,9 +247,8 @@
* removing even the capabilities that are set by default when the object is constructed.
*
* @return The builder to facilitate chaining.
- * @hide
*/
- @UnsupportedAppUsage
+ @NonNull
public Builder clearCapabilities() {
mNetworkCapabilities.clearAll();
return this;
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 2bc3eb5..cf31d21 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -16,6 +16,9 @@
package android.net;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
/**
* Describes specific properties of a requested network for use in a {@link NetworkRequest}.
*
@@ -31,7 +34,8 @@
*
* @hide
*/
- public abstract boolean satisfiedBy(NetworkSpecifier other);
+ @SystemApi
+ public abstract boolean satisfiedBy(@Nullable NetworkSpecifier other);
/**
* Optional method which can be overridden by concrete implementations of NetworkSpecifier to
@@ -45,6 +49,7 @@
*
* @hide
*/
+ @SystemApi
public void assertValidFromUid(int requestorUid) {
// empty
}
@@ -68,6 +73,8 @@
*
* @hide
*/
+ @SystemApi
+ @Nullable
public NetworkSpecifier redact() {
// TODO (b/122160111): convert default to null once all platform NetworkSpecifiers
// implement this method.
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index 292cf50..e449615 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 6c7aa13..45bf4d2 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -19,7 +19,7 @@
import static android.os.Process.CLAT_UID;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index f61260e..7b799e2 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -30,7 +30,7 @@
import static com.android.internal.util.ArrayUtils.total;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.NetworkStatsHistoryBucketProto;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 87c7118..5e6c47a 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,7 +34,7 @@
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d0f54b4..08cc4e2 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -20,7 +20,7 @@
import static android.system.OsConstants.AF_INET6;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.shared.Inet4AddressUtils;
import android.os.Build;
import android.system.ErrnoException;
@@ -61,13 +61,6 @@
public static native void detachBPFFilter(FileDescriptor fd) throws SocketException;
/**
- * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
- * @param fd the socket's {@link FileDescriptor}.
- * @param ifIndex the interface index.
- */
- public native static void setupRaSocket(FileDescriptor fd, int ifIndex) throws SocketException;
-
- /**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
* {@link Network#getSocketFactory}) will be bound to this network. Note that if this
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index a1c7fce..767b693 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -8,4 +8,4 @@
reminv@google.com
satk@google.com
-per-file SSL*, Uri*, Url* = flooey@google.com, narayan@google.com, tobiast@google.com
+per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, tobiast@google.com
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 4600942..4ba7394 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -18,7 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 9d92db4..ffe9ae9 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 52d3fc4..ea6002c 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 39cb323..8b6ac42 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
diff --git a/core/java/android/net/SSLSessionCache.java b/core/java/android/net/SSLSessionCache.java
index 9667e82..944bc54 100644
--- a/core/java/android/net/SSLSessionCache.java
+++ b/core/java/android/net/SSLSessionCache.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index f9c2def..8c6faf6 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -16,7 +16,7 @@
package android.net;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemClock;
import android.util.Log;
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 990c114..f24a9bd 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.shared.InetAddressUtils;
import android.os.Parcel;
import android.os.Parcelable;
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 bf4884a..162d6e2 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -20,10 +20,10 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.DownloadManager;
import android.app.backup.BackupManager;
import android.app.usage.NetworkStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Build;
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index c3166e9..ddca4b4 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Environment;
import android.os.Parcel;
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index ed7cddc..4b804b0 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -23,11 +23,11 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/net/WebAddress.java b/core/java/android/net/WebAddress.java
index 994c794..aa3777d 100644
--- a/core/java/android/net/WebAddress.java
+++ b/core/java/android/net/WebAddress.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.util.Locale;
diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS
index 6b8c9ed..3092612 100644
--- a/core/java/android/net/http/OWNERS
+++ b/core/java/android/net/http/OWNERS
@@ -1,3 +1,4 @@
-flooey@google.com
narayan@google.com
tobiast@google.com
+include platform/libcore:/OWNERS
+include platform/external/conscrypt:/OWNERS
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 01dd08f..250cff2 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -17,7 +17,7 @@
package android.net.http;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Bundle;
import android.text.format.DateFormat;
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index b3f2fb7..d43c616 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -16,8 +16,9 @@
package android.net.http;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+
import java.security.cert.X509Certificate;
/**
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index 8243be9..f93907a 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index eac5579..b221cb9 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 5f9f507..8fc1ef8 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
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/Build.java b/core/java/android/os/Build.java
index 1eda4d9..46b497d 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");
@@ -160,7 +161,7 @@
try {
Application application = ActivityThread.currentApplication();
String callingPackage = application != null ? application.getPackageName() : null;
- return service.getSerialForPackage(callingPackage);
+ return service.getSerialForPackage(callingPackage, null);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
@@ -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/IDeviceIdentifiersPolicyService.aidl b/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
index 87d358f..d11aa0c 100644
--- a/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
+++ b/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
@@ -21,5 +21,5 @@
*/
interface IDeviceIdentifiersPolicyService {
String getSerial();
- String getSerialForPackage(in String callingPackage);
-}
\ No newline at end of file
+ String getSerialForPackage(in String callingPackage, String callingFeatureId);
+}
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/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 6f1bf71..29aaf53 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -16,17 +16,24 @@
package android.os;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArrayMap;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
/**
@@ -339,4 +346,44 @@
proto.end(token);
}
+
+ /**
+ * Writes the content of the {@link PersistableBundle} to a {@link OutputStream}.
+ *
+ * <p>The content can be read by a {@link #readFromStream}.
+ *
+ * @see #readFromStream
+ */
+ public void writeToStream(@NonNull OutputStream outputStream) throws IOException {
+ FastXmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(outputStream, UTF_8.name());
+ serializer.startTag(null, "bundle");
+ try {
+ saveToXml(serializer);
+ } catch (XmlPullParserException e) {
+ throw new IOException(e);
+ }
+ serializer.endTag(null, "bundle");
+ serializer.flush();
+ }
+
+ /**
+ * Reads a {@link PersistableBundle} from an {@link InputStream}.
+ *
+ * <p>The stream must be generated by {@link #writeToStream}.
+ *
+ * @see #writeToStream
+ */
+ @NonNull
+ public static PersistableBundle readFromStream(@NonNull InputStream inputStream)
+ throws IOException {
+ try {
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(inputStream, UTF_8.name());
+ parser.next();
+ return PersistableBundle.restoreFromXml(parser);
+ } catch (XmlPullParserException e) {
+ throw new IOException(e);
+ }
+ }
}
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/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/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index a9ddffe..16f7b39 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.IUpdateEngine;
@@ -140,8 +141,43 @@
* {@code SWITCH_SLOT_ON_REBOOT=0}. See {@link #applyPayload}.
*/
public static final int UPDATED_BUT_NOT_ACTIVE = 52;
+
+ /**
+ * Error code: there is not enough space on the device to apply the update. User should
+ * be prompted to free up space and re-try the update.
+ *
+ * <p>See {@link UpdateEngine#allocateSpace}.
+ */
+ public static final int NOT_ENOUGH_SPACE = 60;
+
+ /**
+ * Error code: the device is corrupted and no further updates may be applied.
+ *
+ * <p>See {@link UpdateEngine#cleanupAppliedPayload}.
+ */
+ public static final int DEVICE_CORRUPTED = 61;
}
+ /** @hide */
+ @IntDef(value = {
+ ErrorCodeConstants.SUCCESS,
+ ErrorCodeConstants.ERROR,
+ ErrorCodeConstants.FILESYSTEM_COPIER_ERROR,
+ ErrorCodeConstants.POST_INSTALL_RUNNER_ERROR,
+ ErrorCodeConstants.PAYLOAD_MISMATCHED_TYPE_ERROR,
+ ErrorCodeConstants.INSTALL_DEVICE_OPEN_ERROR,
+ ErrorCodeConstants.KERNEL_DEVICE_OPEN_ERROR,
+ ErrorCodeConstants.DOWNLOAD_TRANSFER_ERROR,
+ ErrorCodeConstants.PAYLOAD_HASH_MISMATCH_ERROR,
+ ErrorCodeConstants.PAYLOAD_SIZE_MISMATCH_ERROR,
+ ErrorCodeConstants.DOWNLOAD_PAYLOAD_VERIFICATION_ERROR,
+ ErrorCodeConstants.PAYLOAD_TIMESTAMP_ERROR,
+ ErrorCodeConstants.UPDATED_BUT_NOT_ACTIVE,
+ ErrorCodeConstants.NOT_ENOUGH_SPACE,
+ ErrorCodeConstants.DEVICE_CORRUPTED,
+ })
+ public @interface ErrorCode {}
+
/**
* Status codes for update engine. Values must agree with the ones in
* {@code system/update_engine/client_library/include/update_engine/update_status.h}.
@@ -419,4 +455,138 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Return value of {@link #allocateSpace.}
+ */
+ public static final class AllocateSpaceResult {
+ private @ErrorCode int mErrorCode = ErrorCodeConstants.SUCCESS;
+ private long mFreeSpaceRequired = 0;
+ private AllocateSpaceResult() {}
+ /**
+ * Error code.
+ *
+ * @return The following error codes:
+ * <ul>
+ * <li>{@link ErrorCodeConstants#SUCCESS} if space has been allocated
+ * successfully.</li>
+ * <li>{@link ErrorCodeConstants#NOT_ENOUGH_SPACE} if insufficient
+ * space.</li>
+ * <li>Other {@link ErrorCodeConstants} for other errors.</li>
+ * </ul>
+ */
+ @ErrorCode
+ public int errorCode() {
+ return mErrorCode;
+ }
+
+ /**
+ * Estimated total space that needs to be available on the userdata partition to apply the
+ * payload (in bytes).
+ *
+ * <p>
+ * Note that in practice, more space needs to be made available before applying the payload
+ * to keep the device working.
+ *
+ * @return The following values:
+ * <ul>
+ * <li>zero if {@link #errorCode} returns {@link ErrorCodeConstants#SUCCESS}</li>
+ * <li>non-zero if {@link #errorCode} returns {@link ErrorCodeConstants#NOT_ENOUGH_SPACE}.
+ * Value is the estimated total space required on userdata partition.</li>
+ * </ul>
+ * @throws IllegalStateException if {@link #errorCode} is not one of the above.
+ *
+ */
+ public long freeSpaceRequired() {
+ if (mErrorCode == ErrorCodeConstants.SUCCESS) {
+ return 0;
+ }
+ if (mErrorCode == ErrorCodeConstants.NOT_ENOUGH_SPACE) {
+ return mFreeSpaceRequired;
+ }
+ throw new IllegalStateException(String.format(
+ "freeSpaceRequired() is not available when error code is %d", mErrorCode));
+ }
+ }
+
+ /**
+ * Initialize partitions for a payload associated with the given payload
+ * metadata {@code payloadMetadataFilename} by preallocating required space.
+ *
+ * <p>This function should be called after payload has been verified after
+ * {@link #verifyPayloadMetadata}. This function does not verify whether
+ * the given payload is applicable or not.
+ *
+ * <p>Implementation of {@code allocateSpace} uses
+ * {@code headerKeyValuePairs} to determine whether space has been allocated
+ * for a different or same payload previously. If space has been allocated
+ * for a different payload before, space will be reallocated for the given
+ * payload. If space has been allocated for the same payload, no actions to
+ * storage devices are taken.
+ *
+ * <p>This function is synchronous and may take a non-trivial amount of
+ * time. Callers should call this function in a background thread.
+ *
+ * @param payloadMetadataFilename See {@link #verifyPayloadMetadata}.
+ * @param headerKeyValuePairs See {@link #applyPayload}.
+ * @return See {@link AllocateSpaceResult}.
+ */
+ @NonNull
+ public AllocateSpaceResult allocateSpace(
+ @NonNull String payloadMetadataFilename,
+ @NonNull String[] headerKeyValuePairs) {
+ AllocateSpaceResult result = new AllocateSpaceResult();
+ try {
+ result.mFreeSpaceRequired = mUpdateEngine.allocateSpaceForPayload(
+ payloadMetadataFilename,
+ headerKeyValuePairs);
+ result.mErrorCode = result.mFreeSpaceRequired == 0
+ ? ErrorCodeConstants.SUCCESS
+ : ErrorCodeConstants.NOT_ENOUGH_SPACE;
+ return result;
+ } catch (ServiceSpecificException e) {
+ result.mErrorCode = e.errorCode;
+ result.mFreeSpaceRequired = 0;
+ return result;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Cleanup files used by the previous update and free up space after the
+ * device has been booted successfully into the new build.
+ *
+ * <p>In particular, this function waits until delta files for snapshots for
+ * Virtual A/B update are merged to OS partitions, then delete these delta
+ * files.
+ *
+ * <p>This function is synchronous and may take a non-trivial amount of
+ * time. Callers should call this function in a background thread.
+ *
+ * <p>This function does not delete payload binaries downloaded for a
+ * non-streaming OTA update.
+ *
+ * @return One of the following:
+ * <ul>
+ * <li>{@link ErrorCodeConstants#SUCCESS} if execution is successful.</li>
+ * <li>{@link ErrorCodeConstants#ERROR} if a transient error has occurred.
+ * The device should be able to recover after a reboot. The function should
+ * be retried after the reboot.</li>
+ * <li>{@link ErrorCodeConstants#DEVICE_CORRUPTED} if a permanent error is
+ * encountered. Device is corrupted, and future updates must not be applied.
+ * The device cannot recover without flashing and factory resets.
+ * </ul>
+ *
+ * @throws ServiceSpecificException if other transient errors has occurred.
+ * A reboot may or may not help resolving the issue.
+ */
+ @ErrorCode
+ public int cleanupAppliedPayload() {
+ try {
+ return mUpdateEngine.cleanupSuccessfulUpdate();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/os/UpdateEngineCallback.java b/core/java/android/os/UpdateEngineCallback.java
index f07294e..7fe7024 100644
--- a/core/java/android/os/UpdateEngineCallback.java
+++ b/core/java/android/os/UpdateEngineCallback.java
@@ -44,5 +44,6 @@
* unsuccessfully. The value of {@code errorCode} will be one of the
* values from {@link UpdateEngine.ErrorCodeConstants}.
*/
- public abstract void onPayloadApplicationComplete(int errorCode);
+ public abstract void onPayloadApplicationComplete(
+ @UpdateEngine.ErrorCode int errorCode);
}
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.)
+ * > 0 if incompatible
+ * < 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/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index f1d90be..7285166 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -40,7 +40,7 @@
import android.net.Uri;
import android.os.RemoteException;
import android.text.format.DateUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -1680,7 +1680,7 @@
* <h3>Writing to Events</h3> There are further restrictions on all Updates
* and Inserts in the Events table:
* <ul>
- * <li>If allDay is set to 1 eventTimezone must be {@link Time#TIMEZONE_UTC}
+ * <li>If allDay is set to 1 eventTimezone must be "UTC"
* and the time must correspond to a midnight boundary.</li>
* <li>Exceptions are not allowed to recur. If rrule or rdate is not empty,
* original_id and original_sync_id must be empty.</li>
@@ -2609,9 +2609,7 @@
@UnsupportedAppUsage
public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
if (DEBUG) {
- Time time = new Time();
- time.set(alarmTime);
- String schedTime = time.format(" %a, %b %d, %Y %I:%M%P");
+ String schedTime = TimeMigrationUtils.formatMillisWithFixedFormat(alarmTime);
Log.d(TAG, "Schedule alarm at " + alarmTime + " " + schedTime);
}
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 7754666..13d167d 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1352,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;
}
@@ -3523,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.
@@ -3832,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>
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/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index edab97dd..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;
@@ -188,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;
/**
@@ -318,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;
/**
@@ -341,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;
/**
@@ -660,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
}
@@ -679,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
@@ -697,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
@@ -908,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
*/
@@ -1011,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) {
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index a7f45a0..8507e12 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -21,17 +21,15 @@
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;
@@ -120,7 +118,8 @@
};
mSubscriptionChangedListenerMap.put(listener, callback);
try {
- sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback);
+ sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+ null, callback);
} catch (RemoteException ex) {
// system server crash
}
@@ -179,7 +178,7 @@
mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
- callback);
+ null, callback);
} catch (RemoteException ex) {
// system server crash
}
@@ -363,27 +362,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
}
@@ -652,25 +642,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/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java
index 5a14092..f7fd89d 100644
--- a/core/java/android/text/format/TimeFormatter.java
+++ b/core/java/android/text/format/TimeFormatter.java
@@ -26,6 +26,9 @@
import libcore.util.ZoneInfo;
import java.nio.CharBuffer;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.Formatter;
import java.util.Locale;
import java.util.TimeZone;
@@ -86,6 +89,59 @@
}
/**
+ * The implementation of {@link TimeMigrationUtils#formatMillisWithFixedFormat(long)} for
+ * 2038-safe formatting with the pattern "%Y-%m-%d %H:%M:%S" and including the historic
+ * incorrect digit localization behavior.
+ */
+ String formatMillisWithFixedFormat(long timeMillis) {
+ // This method is deliberately not a general purpose replacement for
+ // format(String, ZoneInfo.WallTime, ZoneInfo): It hard-codes the pattern used; many of the
+ // pattern characters supported by Time.format() have unusual behavior which would make
+ // using java.time.format or similar packages difficult. It would be a lot of work to share
+ // behavior and many internal Android usecases can be covered by this common pattern
+ // behavior.
+
+ // No need to worry about overflow / underflow: long millis is representable by Instant and
+ // LocalDateTime with room to spare.
+ Instant instant = Instant.ofEpochMilli(timeMillis);
+
+ // Date/times are calculated in the current system default time zone.
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+
+ // You'd think it would be as simple as:
+ // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", locale);
+ // return formatter.format(localDateTime);
+ // but we retain Time's behavior around digits.
+
+ StringBuilder stringBuilder = new StringBuilder(19);
+
+ // This effectively uses the US locale because number localization is handled separately
+ // (see below).
+ stringBuilder.append(localDateTime.getYear());
+ stringBuilder.append('-');
+ append2DigitNumber(stringBuilder, localDateTime.getMonthValue());
+ stringBuilder.append('-');
+ append2DigitNumber(stringBuilder, localDateTime.getDayOfMonth());
+ stringBuilder.append(' ');
+ append2DigitNumber(stringBuilder, localDateTime.getHour());
+ stringBuilder.append(':');
+ append2DigitNumber(stringBuilder, localDateTime.getMinute());
+ stringBuilder.append(':');
+ append2DigitNumber(stringBuilder, localDateTime.getSecond());
+
+ String result = stringBuilder.toString();
+ return localizeDigits(result);
+ }
+
+ /** Zero-pads value as needed to achieve a 2-digit number. */
+ private static void append2DigitNumber(StringBuilder builder, int value) {
+ if (value < 10) {
+ builder.append('0');
+ }
+ builder.append(value);
+ }
+
+ /**
* Format the specified {@code wallTime} using {@code pattern}. The output is returned.
*/
public String format(String pattern, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) {
@@ -99,12 +155,9 @@
formatInternal(pattern, wallTime, zoneInfo);
String result = stringBuilder.toString();
- // This behavior is the source of a bug since some formats are defined as being
- // in ASCII and not localized.
- if (localeData.zeroDigit != '0') {
- result = localizeDigits(result);
- }
- return result;
+ // The localizeDigits() behavior is the source of a bug since some formats are defined
+ // as being in ASCII and not localized.
+ return localizeDigits(result);
} finally {
outputBuilder = null;
numberFormatter = null;
@@ -112,6 +165,10 @@
}
private String localizeDigits(String s) {
+ if (localeData.zeroDigit == '0') {
+ return s;
+ }
+
int length = s.length();
int offsetToLocalizedDigits = localeData.zeroDigit - '0';
StringBuilder result = new StringBuilder(length);
diff --git a/core/java/android/text/format/TimeMigrationUtils.java b/core/java/android/text/format/TimeMigrationUtils.java
new file mode 100644
index 0000000..17bac8d
--- /dev/null
+++ b/core/java/android/text/format/TimeMigrationUtils.java
@@ -0,0 +1,40 @@
+/*
+ * 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.text.format;
+
+/**
+ * Logic to ease migration away from {@link Time} in Android internal code. {@link Time} is
+ * afflicted by the Y2038 issue and deprecated. The methods here are intended to allow minimal
+ * changes to classes that use {@link Time} for common behavior.
+ *
+ * @hide
+ */
+public class TimeMigrationUtils {
+
+ private TimeMigrationUtils() {}
+
+ /**
+ * A Y2038-safe replacement for various users of the {@link Time#format(String)} with the
+ * pattern "%Y-%m-%d %H:%M:%S". Note, this method retains the unusual localization behavior
+ * originally implemented by Time, which can lead to non-latin numbers being produced if the
+ * default locale does not use latin numbers.
+ */
+ public static String formatMillisWithFixedFormat(long timeMillis) {
+ // Delegate to TimeFormatter so that the unusual localization / threading behavior can be
+ // reused.
+ return new TimeFormatter().formatMillisWithFixedFormat(timeMillis);
+ }
+}
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java
index c39a6c9..6ac7696 100644
--- a/core/java/android/util/CloseGuard.java
+++ b/core/java/android/util/CloseGuard.java
@@ -38,6 +38,11 @@
* 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 {
@@ -75,7 +80,9 @@
* public void cleanup() {
* guard.close();
* ...;
- * Reference.reachabilityFence(this);
+ * 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.
* }
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index da566c9..ea294f0 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -175,4 +175,21 @@
public long getCachedNtpTimeReference() {
return mCachedNtpElapsedRealtime;
}
+
+ /**
+ * Returns the combination of {@link #getCachedNtpTime()} and {@link
+ * #getCachedNtpTimeReference()} as a {@link TimestampedValue}. This method is useful when
+ * passing the time to another component that will adjust for elapsed time.
+ *
+ * @throws IllegalStateException if there is no cached value
+ */
+ public TimestampedValue<Long> getCachedNtpTimeSignal() {
+ if (!mHasCache) {
+ throw new IllegalStateException("Missing authoritative time source");
+ }
+ if (LOGD) Log.d(TAG, "getCachedNtpTimeSignal() cache hit");
+
+ return new TimestampedValue<>(mCachedNtpElapsedRealtime, mCachedNtpTime);
+ }
+
}
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/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 8a1fd62..c67fca5 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -870,6 +870,94 @@
return null;
}
+ private static class StreamingPictureCallbackHandler implements AutoCloseable,
+ HardwareRenderer.PictureCapturedCallback, Runnable {
+ private final HardwareRenderer mRenderer;
+ private final Callable<OutputStream> mCallback;
+ private final Executor mExecutor;
+ private final ReentrantLock mLock = new ReentrantLock(false);
+ private final ArrayDeque<byte[]> mQueue = new ArrayDeque<>(3);
+ private final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
+ private boolean mStopListening;
+ private Thread mRenderThread;
+
+ private StreamingPictureCallbackHandler(HardwareRenderer renderer,
+ Callable<OutputStream> callback, Executor executor) {
+ mRenderer = renderer;
+ mCallback = callback;
+ mExecutor = executor;
+ mRenderer.setPictureCaptureCallback(this);
+ }
+
+ @Override
+ public void close() {
+ mLock.lock();
+ mStopListening = true;
+ mLock.unlock();
+ mRenderer.setPictureCaptureCallback(null);
+ }
+
+ @Override
+ public void onPictureCaptured(Picture picture) {
+ mLock.lock();
+ if (mStopListening) {
+ mLock.unlock();
+ mRenderer.setPictureCaptureCallback(null);
+ return;
+ }
+ if (mRenderThread == null) {
+ mRenderThread = Thread.currentThread();
+ }
+ boolean needsInvoke = true;
+ if (mQueue.size() == 3) {
+ mQueue.removeLast();
+ needsInvoke = false;
+ }
+ picture.writeToStream(mByteStream);
+ mQueue.add(mByteStream.toByteArray());
+ mByteStream.reset();
+ mLock.unlock();
+
+ if (needsInvoke) {
+ mExecutor.execute(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ mLock.lock();
+ final byte[] picture = mQueue.poll();
+ final boolean isStopped = mStopListening;
+ mLock.unlock();
+ if (Thread.currentThread() == mRenderThread) {
+ close();
+ throw new IllegalStateException(
+ "ViewDebug#startRenderingCommandsCapture must be given an executor that "
+ + "invokes asynchronously");
+ }
+ if (isStopped) {
+ return;
+ }
+ OutputStream stream = null;
+ try {
+ stream = mCallback.call();
+ } catch (Exception ex) {
+ Log.w("ViewDebug", "Aborting rendering commands capture "
+ + "because callback threw exception", ex);
+ }
+ if (stream != null) {
+ try {
+ stream.write(picture);
+ } catch (IOException ex) {
+ Log.w("ViewDebug", "Aborting rendering commands capture "
+ + "due to IOException writing to output stream", ex);
+ }
+ } else {
+ close();
+ }
+ }
+ }
+
/**
* Begins capturing the entire rendering commands for the view tree referenced by the given
* view. The view passed may be any View in the tree as long as it is attached. That is,
@@ -915,18 +1003,7 @@
}
final HardwareRenderer renderer = attachInfo.mThreadedRenderer;
if (renderer != null) {
- return new PictureCallbackHandler(renderer, (picture -> {
- try {
- OutputStream stream = callback.call();
- if (stream != null) {
- picture.writeToStream(stream);
- return true;
- }
- } catch (Exception ex) {
- // fall through
- }
- return false;
- }), executor);
+ return new StreamingPictureCallbackHandler(renderer, callback, executor);
}
return null;
}
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/core/java/com/android/internal/compat/AndroidBuildClassifier.java
similarity index 63%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to core/java/com/android/internal/compat/AndroidBuildClassifier.java
index d502088..0b937fa 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/core/java/com/android/internal/compat/AndroidBuildClassifier.java
@@ -14,15 +14,21 @@
* limitations under the License.
*/
-package android.net;
+package com.android.internal.compat;
-import android.net.Network;
+import android.os.Build;
/**
- * Callback class for receiving tethering changed events
- * @hide
+ * Platform private class for determining the type of Android build installed.
+ *
*/
-oneway interface ITetheringEventCallback
-{
- void onUpstreamChanged(in Network network);
+public class AndroidBuildClassifier {
+
+ public boolean isDebuggableBuild() {
+ return Build.IS_DEBUGGABLE;
+ }
+
+ public boolean isFinalBuild() {
+ return "REL".equals(Build.VERSION.CODENAME);
+ }
}
diff --git a/core/java/com/android/internal/compat/IOverrideValidator.aidl b/core/java/com/android/internal/compat/IOverrideValidator.aidl
new file mode 100644
index 0000000..add4708
--- /dev/null
+++ b/core/java/com/android/internal/compat/IOverrideValidator.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.compat;
+
+import android.content.pm.ApplicationInfo;
+
+import com.android.internal.compat.OverrideAllowedState;
+
+/**
+ * Platform private API for determining whether a changeId can be overridden.
+ *
+ * {@hide}
+ */
+interface IOverrideValidator
+{
+ /**
+ * Validation function.
+ * @param changeId id of the change to be toggled on or off.
+ * @param packageName package of the app for which the change should be overridden.
+ * @return {@link OverrideAllowedState} specifying whether the change can be overridden for
+ * the given package or a reason why not.
+ */
+ OverrideAllowedState getOverrideAllowedState(long changeId, String packageName);
+}
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 7dcb12c..4c203d3 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -17,6 +17,7 @@
package com.android.internal.compat;
import android.content.pm.ApplicationInfo;
+import com.android.internal.compat.IOverrideValidator;
import java.util.Map;
parcelable CompatibilityChangeConfig;
@@ -195,4 +196,9 @@
* @return An array of {@link CompatChangeInfo} known to the service.
*/
CompatibilityChangeInfo[] listAllChanges();
+
+ /**
+ * Get an instance that can determine whether a changeid can be overridden for a package name.
+ */
+ IOverrideValidator getOverrideValidator();
}
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/core/java/com/android/internal/compat/OverrideAllowedState.aidl
similarity index 73%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to core/java/com/android/internal/compat/OverrideAllowedState.aidl
index d502088..10ceac7 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/core/java/com/android/internal/compat/OverrideAllowedState.aidl
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-package android.net;
+package com.android.internal.compat;
-import android.net.Network;
-
-/**
- * Callback class for receiving tethering changed events
- * @hide
- */
-oneway interface ITetheringEventCallback
-{
- void onUpstreamChanged(in Network network);
-}
+parcelable OverrideAllowedState;
\ No newline at end of file
diff --git a/core/java/com/android/internal/compat/OverrideAllowedState.java b/core/java/com/android/internal/compat/OverrideAllowedState.java
new file mode 100644
index 0000000..56216c2
--- /dev/null
+++ b/core/java/com/android/internal/compat/OverrideAllowedState.java
@@ -0,0 +1,153 @@
+/*
+ * 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.compat;
+
+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;
+
+/**
+ * This class contains all the possible override allowed states.
+ */
+public final class OverrideAllowedState implements Parcelable {
+ @IntDef({
+ ALLOWED,
+ DISABLED_NOT_DEBUGGABLE,
+ DISABLED_NON_TARGET_SDK,
+ DISABLED_TARGET_SDK_TOO_HIGH,
+ PACKAGE_DOES_NOT_EXIST
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {
+ }
+
+ /**
+ * Change can be overridden.
+ */
+ public static final int ALLOWED = 0;
+ /**
+ * Change cannot be overridden, due to the app not being debuggable.
+ */
+ public static final int DISABLED_NOT_DEBUGGABLE = 1;
+ /**
+ * Change cannot be overridden, due to the build being non-debuggable and the change being
+ * non-targetSdk.
+ */
+ public static final int DISABLED_NON_TARGET_SDK = 2;
+ /**
+ * Change cannot be overridden, due to the app's targetSdk being above the change's targetSdk.
+ */
+ public static final int DISABLED_TARGET_SDK_TOO_HIGH = 3;
+ /**
+ * Package does not exist.
+ */
+ public static final int PACKAGE_DOES_NOT_EXIST = 4;
+
+ @State
+ public final int state;
+ public final int appTargetSdk;
+ public final int changeIdTargetSdk;
+
+ private OverrideAllowedState(Parcel parcel) {
+ state = parcel.readInt();
+ appTargetSdk = parcel.readInt();
+ changeIdTargetSdk = parcel.readInt();
+ }
+
+ public OverrideAllowedState(@State int state, int appTargetSdk, int changeIdTargetSdk) {
+ this.state = state;
+ this.appTargetSdk = appTargetSdk;
+ this.changeIdTargetSdk = changeIdTargetSdk;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(state);
+ out.writeInt(appTargetSdk);
+ out.writeInt(changeIdTargetSdk);
+ }
+
+ /**
+ * Enforces the policy for overriding compat changes.
+ *
+ * @param changeId the change id that was attempted to be overridden.
+ * @param packageName the package for which the attempt was made.
+ * @throws SecurityException if the policy forbids this operation.
+ */
+ public void enforce(long changeId, String packageName)
+ throws SecurityException {
+ switch (state) {
+ case ALLOWED:
+ return;
+ case DISABLED_NOT_DEBUGGABLE:
+ throw new SecurityException(
+ "Cannot override a change on a non-debuggable app and user build.");
+ case DISABLED_NON_TARGET_SDK:
+ throw new SecurityException(
+ "Cannot override a default enabled/disabled change on a user build.");
+ case DISABLED_TARGET_SDK_TOO_HIGH:
+ throw new SecurityException(String.format(
+ "Cannot override %1$d for %2$s because the app's targetSdk (%3$d) is "
+ + "above the change's targetSdk threshold (%4$d)",
+ changeId, packageName, appTargetSdk, changeIdTargetSdk));
+ case PACKAGE_DOES_NOT_EXIST:
+ throw new SecurityException(String.format(
+ "Cannot override %1$d for %2$s because the package does not exist, and "
+ + "the change is targetSdk gated.",
+ changeId, packageName));
+ }
+ }
+
+ public static final @NonNull
+ Parcelable.Creator<OverrideAllowedState> CREATOR =
+ new Parcelable.Creator<OverrideAllowedState>() {
+ public OverrideAllowedState createFromParcel(Parcel parcel) {
+ OverrideAllowedState info = new OverrideAllowedState(parcel);
+ return info;
+ }
+
+ public OverrideAllowedState[] newArray(int size) {
+ return new OverrideAllowedState[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OverrideAllowedState)) {
+ return false;
+ }
+ OverrideAllowedState otherState = (OverrideAllowedState) obj;
+ return state == otherState.state
+ && appTargetSdk == otherState.appTargetSdk
+ && changeIdTargetSdk == otherState.changeIdTargetSdk;
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index c859f11..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;
@@ -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/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 4551d16..5228584 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -24,6 +24,8 @@
import android.telephony.CellInfo;
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;
@@ -31,16 +33,22 @@
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
interface ITelephonyRegistry {
- void addOnSubscriptionsChangedListener(String pkg,
+ void addOnSubscriptionsChangedListener(String pkg, String featureId,
IOnSubscriptionsChangedListener callback);
- void addOnOpportunisticSubscriptionsChangedListener(String pkg,
+ void addOnOpportunisticSubscriptionsChangedListener(String pkg, String featureId,
IOnSubscriptionsChangedListener callback);
void removeOnSubscriptionsChangedListener(String pkg,
IOnSubscriptionsChangedListener callback);
+ /**
+ * @deprecated Use {@link #listenWithFeature(String, String, IPhoneStateListener, int,
+ * boolean) instead
+ */
@UnsupportedAppUsage
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
- void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events,
+ void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events,
boolean notifyNow);
+ void listenForSubscriber(in int subId, String pkg, String featureId,
+ IPhoneStateListener callback, int events, boolean notifyNow);
@UnsupportedAppUsage
void notifyCallStateForAllSubs(int state, String incomingNumber);
void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber);
@@ -54,13 +62,8 @@
@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);
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/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/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_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 08aa1d9..ba7fe7f 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -24,9 +24,7 @@
#include <linux/tcp.h>
#include <net/if.h>
#include <netinet/ether.h>
-#include <netinet/icmp6.h>
#include <netinet/ip.h>
-#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <android_runtime/AndroidRuntime.h>
@@ -102,98 +100,6 @@
}
}
-static void android_net_utils_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd,
- jint ifIndex)
-{
- static const int kLinkLocalHopLimit = 255;
-
- int fd = jniGetFDFromFileDescriptor(env, javaFd);
-
- // Set an ICMPv6 filter that only passes Router Solicitations.
- struct icmp6_filter rs_only;
- ICMP6_FILTER_SETBLOCKALL(&rs_only);
- ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only);
- socklen_t len = sizeof(rs_only);
- if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(ICMP6_FILTER): %s", strerror(errno));
- return;
- }
-
- // Most/all of the rest of these options can be set via Java code, but
- // because we're here on account of setting an icmp6_filter go ahead
- // and do it all natively for now.
- //
- // TODO: Consider moving these out to Java.
-
- // Set the multicast hoplimit to 255 (link-local only).
- int hops = kLinkLocalHopLimit;
- len = sizeof(hops);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
- return;
- }
-
- // Set the unicast hoplimit to 255 (link-local only).
- hops = kLinkLocalHopLimit;
- len = sizeof(hops);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
- return;
- }
-
- // Explicitly disable multicast loopback.
- int off = 0;
- len = sizeof(off);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno));
- return;
- }
-
- // Specify the IPv6 interface to use for outbound multicast.
- len = sizeof(ifIndex);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno));
- return;
- }
-
- // Additional options to be considered:
- // - IPV6_TCLASS
- // - IPV6_RECVPKTINFO
- // - IPV6_RECVHOPLIMIT
-
- // Bind to [::].
- const struct sockaddr_in6 sin6 = {
- .sin6_family = AF_INET6,
- .sin6_port = 0,
- .sin6_flowinfo = 0,
- .sin6_addr = IN6ADDR_ANY_INIT,
- .sin6_scope_id = 0,
- };
- auto sa = reinterpret_cast<const struct sockaddr *>(&sin6);
- len = sizeof(sin6);
- if (bind(fd, sa, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "bind(IN6ADDR_ANY): %s", strerror(errno));
- return;
- }
-
- // Join the all-routers multicast group, ff02::2%index.
- struct ipv6_mreq all_rtrs = {
- .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}},
- .ipv6mr_interface = ifIndex,
- };
- len = sizeof(all_rtrs);
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) {
- jniThrowExceptionFmt(env, "java/net/SocketException",
- "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno));
- return;
- }
-}
static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
{
@@ -370,7 +276,6 @@
{ "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter },
{ "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter },
{ "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow },
- { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_setupRaSocket },
{ "resNetworkSend", "(I[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
{ "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
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_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/fd_utils.cpp b/core/jni/fd_utils.cpp
index 0c21076..ee74f6d 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -37,8 +37,7 @@
"/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 8dc84c8..a42ba17 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" />
@@ -450,7 +451,6 @@
<protected-broadcast android:name="android.intent.action.internal_sim_state_changed" />
<protected-broadcast android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<protected-broadcast android:name="android.intent.action.PRECISE_CALL_STATE" />
- <protected-broadcast android:name="android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.intent.action.SUBSCRIPTION_PHONE_STATE" />
<protected-broadcast android:name="android.intent.action.USER_INFO_CHANGED" />
<protected-broadcast android:name="android.intent.action.USER_UNLOCKED" />
@@ -635,7 +635,7 @@
<!-- NETWORK_SET_TIME moved from com.android.phone to system server. It should ultimately be
removed. -->
- <protected-broadcast android:name="android.intent.action.NETWORK_SET_TIME" />
+ <protected-broadcast android:name="android.telephony.action.NETWORK_SET_TIME" />
<!-- For tether entitlement recheck-->
<protected-broadcast
@@ -1767,6 +1767,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
@@ -1868,6 +1876,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
@@ -2508,17 +2523,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"
@@ -2526,6 +2541,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/config.xml b/core/res/res/values/config.xml
index 4b5840e..04d1eef 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2266,9 +2266,6 @@
<!-- Number of times to try again with the shorter interval, before backing
off until the normal polling interval. A value < 0 indicates infinite. -->
<integer name="config_ntpRetry">3</integer>
- <!-- If the time difference is greater than this threshold in milliseconds,
- then update the time. -->
- <integer name="config_ntpThreshold">5000</integer>
<!-- Timeout to wait for NTP server response in milliseconds. -->
<integer name="config_ntpTimeout">5000</integer>
@@ -3020,10 +3017,6 @@
<!-- 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" />
@@ -3542,6 +3535,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">
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 04b86a8..383fcd4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -295,7 +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="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" />
@@ -490,7 +489,6 @@
<java-symbol type="integer" name="config_ntpPollingInterval" />
<java-symbol type="integer" name="config_ntpPollingIntervalShorter" />
<java-symbol type="integer" name="config_ntpRetry" />
- <java-symbol type="integer" name="config_ntpThreshold" />
<java-symbol type="integer" name="config_ntpTimeout" />
<java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
<java-symbol type="integer" name="config_toastDefaultGravity" />
@@ -3154,6 +3152,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/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.java
new file mode 100644
index 0000000..9b3d0c9
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/NetworkTimeSuggestionTest.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 NetworkTimeSuggestionTest {
+
+ private static final TimestampedValue<Long> ARBITRARY_TIME =
+ new TimestampedValue<>(1111L, 2222L);
+
+ @Test
+ public void testEquals() {
+ NetworkTimeSuggestion one = new NetworkTimeSuggestion(ARBITRARY_TIME);
+ assertEquals(one, one);
+
+ NetworkTimeSuggestion two = new NetworkTimeSuggestion(ARBITRARY_TIME);
+ assertEquals(one, two);
+ assertEquals(two, one);
+
+ TimestampedValue<Long> differentTime = new TimestampedValue<>(
+ ARBITRARY_TIME.getReferenceTimeMillis() + 1,
+ ARBITRARY_TIME.getValue());
+ NetworkTimeSuggestion three = new NetworkTimeSuggestion(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() {
+ NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(ARBITRARY_TIME);
+ assertRoundTripParcelable(suggestion);
+
+ // DebugInfo should also be stored (but is not checked by equals()
+ suggestion.addDebugInfo("This is debug info");
+ NetworkTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
+ assertEquals(suggestion.getDebugInfo(), rtSuggestion.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/text/format/TimeMigrationUtilsTest.java b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
new file mode 100644
index 0000000..b605520
--- /dev/null
+++ b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.text.format;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TimeMigrationUtilsTest {
+
+ private static final int ONE_DAY_IN_SECONDS = 24 * 60 * 60;
+
+ private Locale mDefaultLocale;
+ private TimeZone mDefaultTimeZone;
+
+ @Before
+ public void setUp() {
+ mDefaultLocale = Locale.getDefault();
+ mDefaultTimeZone = TimeZone.getDefault();
+ }
+
+ @After
+ public void tearDown() {
+ Locale.setDefault(mDefaultLocale);
+ TimeZone.setDefault(mDefaultTimeZone);
+ }
+
+ @Test
+ public void formatMillisWithFixedFormat_fixes2038Issue() {
+ Locale.setDefault(Locale.UK);
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+ // The following cannot be represented properly using Time because they are outside of the
+ // supported range.
+ long y2038Issue1 = (((long) Integer.MIN_VALUE) - ONE_DAY_IN_SECONDS) * 1000L;
+ assertEquals(
+ "1901-12-12 20:45:52", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue1));
+ long y2038Issue2 = (((long) Integer.MAX_VALUE) + ONE_DAY_IN_SECONDS) * 1000L;
+ assertEquals(
+ "2038-01-20 03:14:07", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue2));
+ }
+
+ /**
+ * Compares TimeMigrationUtils.formatSimpleDateTime() with the code it is replacing.
+ */
+ @Test
+ public void formatMillisAsDateTime_matchesOldBehavior() {
+ // A selection of interesting locales.
+ Locale[] locales = new Locale[] {
+ Locale.US,
+ Locale.UK,
+ Locale.FRANCE,
+ Locale.JAPAN,
+ Locale.CHINA,
+ // Android supports RTL locales like arabic and arabic with latin numbers.
+ Locale.forLanguageTag("ar-AE"),
+ Locale.forLanguageTag("ar-AE-u-nu-latn"),
+ };
+ // A selection of interesting time zones.
+ String[] timeZoneIds = new String[] {
+ "UTC", "Europe/London", "America/New_York", "America/Los_Angeles", "Asia/Shanghai",
+ };
+ // Some arbitrary times when the two formatters should agree.
+ long[] timesMillis = new long[] {
+ System.currentTimeMillis(),
+ 0,
+ // The Time class only works in 32-bit range, the replacement works beyond that. To
+ // avoid messing around with offsets and complicating the test, below there are a
+ // day after / before the known limits.
+ (Integer.MIN_VALUE + ONE_DAY_IN_SECONDS) * 1000L,
+ (Integer.MAX_VALUE - ONE_DAY_IN_SECONDS) * 1000L,
+ };
+
+ for (Locale locale : locales) {
+ Locale.setDefault(locale);
+ for (String timeZoneId : timeZoneIds) {
+ TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
+ TimeZone.setDefault(timeZone);
+ for (long timeMillis : timesMillis) {
+ Time time = new Time();
+ time.set(timeMillis);
+ String oldResult = time.format("%Y-%m-%d %H:%M:%S");
+ String newResult = TimeMigrationUtils.formatMillisWithFixedFormat(timeMillis);
+ assertEquals(
+ "locale=" + locale + ", timeZoneId=" + timeZoneId
+ + ", timeMillis=" + timeMillis,
+ oldResult, newResult);
+ }
+ }
+ }
+ }
+}
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/core/xsd/permission.xsd b/core/xsd/permission.xsd
index 9520db7..cc01a31 100644
--- a/core/xsd/permission.xsd
+++ b/core/xsd/permission.xsd
@@ -126,12 +126,12 @@
</xs:complexType>
<xs:complexType name="privapp-permissions">
<xs:sequence>
- <xs:element name="permission" maxOccurs="unbounded">
+ <xs:element name="permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
- <xs:element name="deny-permission" maxOccurs="unbounded">
+ <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
@@ -141,12 +141,12 @@
</xs:complexType>
<xs:complexType name="oem-permissions">
<xs:sequence>
- <xs:element name="permission" maxOccurs="unbounded">
+ <xs:element name="permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
- <xs:element name="deny-permission" maxOccurs="unbounded">
+ <xs:element name="deny-permission" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
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 51fc1e1..0756647 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -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/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 c462eb7..e748bd8 100644
--- a/libs/androidfw/LocaleDataTables.cpp
+++ b/libs/androidfw/LocaleDataTables.cpp
@@ -118,6 +118,7 @@
{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
@@ -145,6 +146,7 @@
{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
@@ -165,6 +167,7 @@
{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
@@ -236,7 +239,6 @@
{0x84E10000u, 17u}, // bhb -> Deva
{0x98E10000u, 44u}, // bhg -> Latn
{0xA0E10000u, 17u}, // bhi -> Deva
- {0xA8E10000u, 44u}, // bhk -> Latn
{0xACE10000u, 44u}, // bhl -> Latn
{0xB8E10000u, 17u}, // bho -> Deva
{0xE0E10000u, 44u}, // bhy -> Latn
@@ -332,6 +334,7 @@
{0xB8E20000u, 44u}, // cho -> Latn
{0xBCE20000u, 44u}, // chp -> Latn
{0xC4E20000u, 13u}, // chr -> Cher
+ {0x89020000u, 44u}, // cic -> Latn
{0x81220000u, 1u}, // cja -> Arab
{0xB1220000u, 12u}, // cjm -> Cham
{0xD5220000u, 44u}, // cjv -> Latn
@@ -387,6 +390,7 @@
{0xA1C30000u, 1u}, // doi -> Arab
{0xBDC30000u, 44u}, // dop -> Latn
{0xD9C30000u, 44u}, // dow -> Latn
+ {0x9E230000u, 54u}, // drh -> Mong
{0xA2230000u, 44u}, // dri -> Latn
{0xCA230000u, 19u}, // drs -> Ethi
{0x86430000u, 44u}, // dsb -> Latn
@@ -737,6 +741,7 @@
{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
@@ -755,8 +760,10 @@
{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, 44u}, // kxw -> Latn
@@ -766,7 +773,9 @@
{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
@@ -899,6 +908,7 @@
{0x95AC0000u, 44u}, // mnf -> Latn
{0xA1AC0000u, 7u}, // mni -> Beng
{0xD9AC0000u, 56u}, // mnw -> Mymr
+ {0x6D6F0000u, 44u}, // mo -> Latn
{0x81CC0000u, 44u}, // moa -> Latn
{0x91CC0000u, 44u}, // moe -> Latn
{0x9DCC0000u, 44u}, // moh -> Latn
@@ -1069,6 +1079,7 @@
{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
@@ -1241,6 +1252,7 @@
{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
@@ -1326,6 +1338,7 @@
{0xC5B40000u, 7u}, // unr -> Beng
{0xC5B44E50u, 17u}, // unr-NP -> Deva
{0xDDB40000u, 7u}, // unx -> Beng
+ {0xA9D40000u, 44u}, // uok -> Latn
{0x75720000u, 1u}, // ur -> Arab
{0xA2340000u, 44u}, // uri -> Latn
{0xCE340000u, 44u}, // urt -> Latn
@@ -1479,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
@@ -1491,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
@@ -1500,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
@@ -1537,7 +1553,6 @@
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
@@ -1584,6 +1599,7 @@
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
@@ -1617,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
@@ -1809,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
@@ -1821,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
@@ -1893,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
@@ -1981,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
@@ -2094,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
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/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/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/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index ea00d6e..4318a0a 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -61,6 +61,9 @@
private final boolean mEncrypted;
private final int mAudioChannelCount;
private final int mAudioSampleRate;
+ private final boolean mAudioDescription;
+ private final boolean mHardOfHearing;
+ private final boolean mSpokenSubtitle;
private final int mVideoWidth;
private final int mVideoHeight;
private final float mVideoFrameRate;
@@ -70,9 +73,10 @@
private final Bundle mExtra;
private TvTrackInfo(int type, String id, String language, CharSequence description,
- boolean encrypted, int audioChannelCount, int audioSampleRate, int videoWidth,
- int videoHeight, float videoFrameRate, float videoPixelAspectRatio,
- byte videoActiveFormatDescription, Bundle extra) {
+ boolean encrypted, int audioChannelCount, int audioSampleRate, boolean audioDescription,
+ boolean hardOfHearing, boolean spokenSubtitle, int videoWidth, int videoHeight,
+ float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription,
+ Bundle extra) {
mType = type;
mId = id;
mLanguage = language;
@@ -80,6 +84,9 @@
mEncrypted = encrypted;
mAudioChannelCount = audioChannelCount;
mAudioSampleRate = audioSampleRate;
+ mAudioDescription = audioDescription;
+ mHardOfHearing = hardOfHearing;
+ mSpokenSubtitle = spokenSubtitle;
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
mVideoFrameRate = videoFrameRate;
@@ -96,6 +103,9 @@
mEncrypted = in.readInt() != 0;
mAudioChannelCount = in.readInt();
mAudioSampleRate = in.readInt();
+ mAudioDescription = in.readInt() != 0;
+ mHardOfHearing = in.readInt() != 0;
+ mSpokenSubtitle = in.readInt() != 0;
mVideoWidth = in.readInt();
mVideoHeight = in.readInt();
mVideoFrameRate = in.readFloat();
@@ -172,6 +182,56 @@
}
/**
+ * Returns {@code true} if the track is an audio description intended for people with visual
+ * impairment, {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks.
+ *
+ * <p>For example of broadcast, audio description information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language
+ * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track
+ */
+ public boolean isAudioDescription() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ return mAudioDescription;
+ }
+
+ /**
+ * Returns {@code true} if the track is intended for people with hearing impairment, {@code
+ * false} otherwise. Valid only for {@link #TYPE_AUDIO} and {@link #TYPE_SUBTITLE} tracks.
+ *
+ * <p>For example of broadcast, hard of hearing information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio Language
+ * Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track or a subtitle track
+ */
+ public boolean isHardOfHearing() {
+ if (mType != TYPE_AUDIO && mType != TYPE_SUBTITLE) {
+ throw new IllegalStateException("Not an audio or a subtitle track");
+ }
+ return mHardOfHearing;
+ }
+
+ /**
+ * Returns {@code true} if the track is a spoken subtitle for people with visual impairment,
+ * {@code false} otherwise. Valid only for {@link #TYPE_AUDIO} tracks.
+ *
+ * <p>For example of broadcast, spoken subtitle information may be referred to broadcast
+ * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468).
+ *
+ * @throws IllegalStateException if not called on an audio track
+ */
+ public boolean isSpokenSubtitle() {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ return mSpokenSubtitle;
+ }
+
+ /**
* Returns the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
* tracks.
*
@@ -266,6 +326,9 @@
dest.writeInt(mEncrypted ? 1 : 0);
dest.writeInt(mAudioChannelCount);
dest.writeInt(mAudioSampleRate);
+ dest.writeInt(mAudioDescription ? 1 : 0);
+ dest.writeInt(mHardOfHearing ? 1 : 0);
+ dest.writeInt(mSpokenSubtitle ? 1 : 0);
dest.writeInt(mVideoWidth);
dest.writeInt(mVideoHeight);
dest.writeFloat(mVideoFrameRate);
@@ -289,6 +352,7 @@
if (!TextUtils.equals(mId, obj.mId) || mType != obj.mType
|| !TextUtils.equals(mLanguage, obj.mLanguage)
|| !TextUtils.equals(mDescription, obj.mDescription)
+ || mEncrypted != obj.mEncrypted
|| !Objects.equals(mExtra, obj.mExtra)) {
return false;
}
@@ -296,7 +360,10 @@
switch (mType) {
case TYPE_AUDIO:
return mAudioChannelCount == obj.mAudioChannelCount
- && mAudioSampleRate == obj.mAudioSampleRate;
+ && mAudioSampleRate == obj.mAudioSampleRate
+ && mAudioDescription == obj.mAudioDescription
+ && mHardOfHearing == obj.mHardOfHearing
+ && mSpokenSubtitle == obj.mSpokenSubtitle;
case TYPE_VIDEO:
return mVideoWidth == obj.mVideoWidth
@@ -304,6 +371,9 @@
&& mVideoFrameRate == obj.mVideoFrameRate
&& mVideoPixelAspectRatio == obj.mVideoPixelAspectRatio
&& mVideoActiveFormatDescription == obj.mVideoActiveFormatDescription;
+
+ case TYPE_SUBTITLE:
+ return mHardOfHearing == obj.mHardOfHearing;
}
return true;
@@ -338,6 +408,9 @@
private boolean mEncrypted;
private int mAudioChannelCount;
private int mAudioSampleRate;
+ private boolean mAudioDescription;
+ private boolean mHardOfHearing;
+ private boolean mSpokenSubtitle;
private int mVideoWidth;
private int mVideoHeight;
private float mVideoFrameRate;
@@ -430,6 +503,67 @@
}
/**
+ * Sets the audio description attribute of the audio. Valid only for {@link #TYPE_AUDIO}
+ * tracks.
+ *
+ * <p>For example of broadcast, audio description information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio
+ * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN
+ * 300 468).
+ *
+ * @param audioDescription The audio description attribute of the audio.
+ * @throws IllegalStateException if not called on an audio track
+ */
+ @NonNull
+ public Builder setAudioDescription(boolean audioDescription) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mAudioDescription = audioDescription;
+ return this;
+ }
+
+ /**
+ * Sets the hard of hearing attribute of the track. Valid only for {@link #TYPE_AUDIO} and
+ * {@link #TYPE_SUBTITLE} tracks.
+ *
+ * <p>For example of broadcast, hard of hearing information may be referred to broadcast
+ * standard (e.g. ISO 639 Language Descriptor of ISO/IEC 13818-1, Supplementary Audio
+ * Language Descriptor, AC-3 Descriptor, Enhanced AC-3 Descriptor, AAC Descriptor of ETSI EN
+ * 300 468).
+ *
+ * @param hardOfHearing The hard of hearing attribute of the track.
+ * @throws IllegalStateException if not called on an audio track or a subtitle track
+ */
+ @NonNull
+ public Builder setHardOfHearing(boolean hardOfHearing) {
+ if (mType != TYPE_AUDIO && mType != TYPE_SUBTITLE) {
+ throw new IllegalStateException("Not an audio track or a subtitle track");
+ }
+ mHardOfHearing = hardOfHearing;
+ return this;
+ }
+
+ /**
+ * Sets the spoken subtitle attribute of the audio. Valid only for {@link #TYPE_AUDIO}
+ * tracks.
+ *
+ * <p>For example of broadcast, spoken subtitle information may be referred to broadcast
+ * standard (e.g. Supplementary Audio Language Descriptor of ETSI EN 300 468).
+ *
+ * @param spokenSubtitle The spoken subtitle attribute of the audio.
+ * @throws IllegalStateException if not called on an audio track
+ */
+ @NonNull
+ public Builder setSpokenSubtitle(boolean spokenSubtitle) {
+ if (mType != TYPE_AUDIO) {
+ throw new IllegalStateException("Not an audio track");
+ }
+ mSpokenSubtitle = spokenSubtitle;
+ return this;
+ }
+
+ /**
* Sets the width of the video, in the unit of pixels. Valid only for {@link #TYPE_VIDEO}
* tracks.
*
@@ -531,8 +665,9 @@
*/
public TvTrackInfo build() {
return new TvTrackInfo(mType, mId, mLanguage, mDescription, mEncrypted,
- mAudioChannelCount, mAudioSampleRate, mVideoWidth, mVideoHeight,
- mVideoFrameRate, mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
+ mAudioChannelCount, mAudioSampleRate, mAudioDescription, mHardOfHearing,
+ mSpokenSubtitle, mVideoWidth, mVideoHeight, mVideoFrameRate,
+ mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
}
}
}
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/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 9e49826..c2ce840 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -262,10 +262,11 @@
return;
}
+ stopForeground(true);
mJustCancelledByUser = true;
if (mInstallTask.cancel(false)) {
- // Will cleanup and post status in onResult()
+ // Will stopSelf() in onResult()
Log.d(TAG, "Cancel request filed successfully");
} else {
Log.e(TAG, "Trying to cancel installation while it's already completed.");
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/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 39c55fd..413211d 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -132,6 +132,20 @@
<item>avrcp16</item>
</string-array>
+ <!-- Titles for Bluetooth MAP Versions -->
+ <string-array name="bluetooth_map_versions">
+ <item>MAP 1.2 (Default)</item>
+ <item>MAP 1.3</item>
+ <item>MAP 1.4</item>
+ </string-array>
+
+ <!-- Values for Bluetooth MAP Versions -->
+ <string-array name="bluetooth_map_version_values">
+ <item>map12</item>
+ <item>map13</item>
+ <item>map14</item>
+ </string-array>
+
<!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50] -->
<string-array name="bluetooth_a2dp_codec_titles">
<item>Use System Selection (Default)</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index bdfa217..8c2ff2c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -597,6 +597,11 @@
<!-- UI debug setting: Select Bluetooth AVRCP Version -->
<string name="bluetooth_select_avrcp_version_dialog_title">Select Bluetooth AVRCP Version</string>
+ <!-- UI debug setting: Select Bluetooth MAP Version [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_select_map_version_string">Bluetooth MAP Version</string>
+ <!-- UI debug setting: Select Bluetooth MAP Version [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_select_map_version_dialog_title">Select Bluetooth MAP Version</string>
+
<!-- UI debug setting: Trigger Bluetooth Audio Codec Selection -->
<string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
<!-- UI debug setting: Trigger Bluetooth Audio Codec Selection -->
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/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 58655a2..b4b55f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -203,13 +203,6 @@
}
}
- public int getVolume() {
- if (mService == null) {
- return 0;
- }
- return mService.getVolume();
- }
-
public void setVolume(int volume) {
if (mService == null) {
return;
@@ -224,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/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/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/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 4700baa..18d436f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -421,7 +421,7 @@
}
/** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
- private static class AnimateCloseListener extends AnimatorListenerAdapter {
+ private class AnimateCloseListener extends AnimatorListenerAdapter {
final View mView;
private final GutsContent mGutsContent;
@@ -433,8 +433,10 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- mView.setVisibility(View.GONE);
- mGutsContent.onFinishedClosing();
+ if (!isExposed()) {
+ mView.setVisibility(View.GONE);
+ mGutsContent.onFinishedClosing();
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 8f7671a..719ec32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -100,6 +100,7 @@
protected String mKeyToRemoveOnGutsClosed;
private StatusBar mStatusBar;
+ private Runnable mOpenRunnable;
@Inject
public NotificationGutsManager(
@@ -343,6 +344,7 @@
public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
int x, int y, boolean resetMenu) {
if (mNotificationGutsExposed != null) {
+ mNotificationGutsExposed.removeCallbacks(mOpenRunnable);
mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
}
if (resetMenu) {
@@ -445,7 +447,7 @@
// ensure that it's laid but not visible until actually laid out
guts.setVisibility(View.INVISIBLE);
// Post to ensure the the guts are properly laid out.
- guts.post(new Runnable() {
+ mOpenRunnable = new Runnable() {
@Override
public void run() {
if (row.getWindowToken() == null) {
@@ -470,7 +472,8 @@
mListContainer.onHeightChanged(row, true /* needsAnimation */);
mGutsMenuItem = menuItem;
}
- });
+ };
+ guts.post(mOpenRunnable);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index f4635d1..f7b8a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -67,6 +67,9 @@
}
private fun updateListeningState() {
+ if (pickupSensor == null) {
+ return
+ }
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0c47d14..68ee8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -62,6 +62,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import androidx.annotation.VisibleForTesting;
+
/**
* Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
* via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -161,6 +163,7 @@
private boolean mLastLockVisible;
private OnDismissAction mAfterKeyguardGoneAction;
+ private Runnable mKeyguardGoneCancelAction;
private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
@@ -328,10 +331,20 @@
return false;
}
- private void hideBouncer(boolean destroyView) {
+ @VisibleForTesting
+ void hideBouncer(boolean destroyView) {
if (mBouncer == null) {
return;
}
+ if (mShowing) {
+ // If we were showing the bouncer and then aborting, we need to also clear out any
+ // potential actions unless we actually unlocked.
+ mAfterKeyguardGoneAction = null;
+ if (mKeyguardGoneCancelAction != null) {
+ mKeyguardGoneCancelAction.run();
+ mKeyguardGoneCancelAction = null;
+ }
+ }
mBouncer.hide(destroyView);
cancelPendingWakeupAction();
}
@@ -364,6 +377,7 @@
mBouncer.showWithDismissAction(r, cancelAction);
} else {
mAfterKeyguardGoneAction = r;
+ mKeyguardGoneCancelAction = cancelAction;
mBouncer.show(false /* resetSecuritySelection */);
}
}
@@ -671,6 +685,7 @@
mAfterKeyguardGoneAction.onDismiss();
mAfterKeyguardGoneAction = null;
}
+ mKeyguardGoneCancelAction = null;
for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
mAfterKeyguardGoneRunnables.get(i).run();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 63f653b..0da0e76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -221,6 +221,31 @@
verify(mStatusBar, never()).animateKeyguardUnoccluding();
}
+ @Test
+ public void testHiding_cancelsGoneRunnable() {
+ OnDismissAction action = mock(OnDismissAction.class);
+ Runnable cancelAction = mock(Runnable.class);
+ mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+ true /* afterKeyguardGone */);
+
+ mStatusBarKeyguardViewManager.hideBouncer(true);
+ mStatusBarKeyguardViewManager.hide(0, 30);
+ verify(action, never()).onDismiss();
+ verify(cancelAction).run();
+ }
+
+ @Test
+ public void testHiding_doesntCancelWhenShowing() {
+ OnDismissAction action = mock(OnDismissAction.class);
+ Runnable cancelAction = mock(Runnable.class);
+ mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+ true /* afterKeyguardGone */);
+
+ mStatusBarKeyguardViewManager.hide(0, 30);
+ verify(action).onDismiss();
+ verify(cancelAction, never()).run();
+ }
+
private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 3c953b3..596f62f 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -29,9 +29,11 @@
"netlink-client",
"networkstack-aidl-interfaces-unstable-java",
"android.hardware.tetheroffload.control-V1.0-java",
- "tethering-client",
],
- libs: ["unsupportedappusage"],
+ libs: [
+ "framework-tethering",
+ ],
+
manifest: "AndroidManifestBase.xml",
}
@@ -43,9 +45,9 @@
// Due to b/143733063, APK can't access a jni lib that is in APEX (but not in the APK).
cc_library {
- name: "libtetheroffloadjni",
+ name: "libtetherutilsjni",
srcs: [
- "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ "jni/android_net_util_TetheringUtils.cpp",
],
shared_libs: [
"libcgrouprc",
@@ -85,11 +87,15 @@
"libcgrouprc",
"libnativehelper_compat_libc++",
"libvndksupport",
- "libtetheroffloadjni",
+ "libtetherutilsjni",
],
resource_dirs: [
"res",
],
+ libs: [
+ "framework-tethering",
+ ],
+ jarjar_rules: "jarjar-rules.txt",
optimize: {
proguard_flags_files: ["proguard.flags"],
},
@@ -104,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 7fb286b..a49ab85 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,95 +15,142 @@
*/
package android.net;
-import static android.Manifest.permission.NETWORK_STACK;
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
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;
}
@@ -113,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");
}
/**
@@ -165,108 +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) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- 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) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- 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) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return TETHER_ERROR_SERVICE_UNAVAIL;
- }
- 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) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return;
- }
+ 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) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return;
- }
- 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);
+ }
+ });
}
/**
@@ -277,47 +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) {
- if (mConnector == null) {
- Slog.wtf(TAG, "Tethering not ready yet");
- return;
- }
+ 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;
@@ -334,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;
}
@@ -348,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;
}
@@ -362,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;
}
@@ -375,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;
}
@@ -416,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..d93531b
--- /dev/null
+++ b/packages/Tethering/jarjar-rules.txt
@@ -0,0 +1,17 @@
+# 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
+
+rule android.net.shared.Inet4AddressUtils* com.android.networkstack.tethering.shared.Inet4AddressUtils@1
diff --git a/packages/Tethering/jni/android_net_util_TetheringUtils.cpp b/packages/Tethering/jni/android_net_util_TetheringUtils.cpp
new file mode 100644
index 0000000..1cf8f98
--- /dev/null
+++ b/packages/Tethering/jni/android_net_util_TetheringUtils.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <error.h>
+#include <hidl/HidlSupport.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netlink.h>
+#include <net/if.h>
+#include <netinet/icmp6.h>
+#include <sys/socket.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+
+#define LOG_TAG "TetheringUtils"
+#include <utils/Log.h>
+
+namespace android {
+
+using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::tetheroffload::config::V1_0::IOffloadConfig;
+
+namespace {
+
+inline const sockaddr * asSockaddr(const sockaddr_nl *nladdr) {
+ return reinterpret_cast<const sockaddr *>(nladdr);
+}
+
+int conntrackSocket(unsigned groups) {
+ base::unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
+ if (s.get() < 0) return -errno;
+
+ const struct sockaddr_nl bind_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl kernel_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
+ return -errno;
+ }
+
+ return s.release();
+}
+
+// Return a hidl_handle that owns the file descriptor owned by fd, and will
+// auto-close it (otherwise there would be double-close problems).
+//
+// Rely upon the compiler to eliminate the constexprs used for clarity.
+hidl_handle handleFromFileDescriptor(base::unique_fd fd) {
+ hidl_handle h;
+
+ static constexpr int kNumFds = 1;
+ static constexpr int kNumInts = 0;
+ native_handle_t *nh = native_handle_create(kNumFds, kNumInts);
+ nh->data[0] = fd.release();
+
+ static constexpr bool kTakeOwnership = true;
+ h.setTo(nh, kTakeOwnership);
+
+ return h;
+}
+
+} // namespace
+
+static jboolean android_net_util_configOffload(
+ JNIEnv* /* env */) {
+ sp<IOffloadConfig> configInterface = IOffloadConfig::getService();
+ if (configInterface.get() == nullptr) {
+ ALOGD("Could not find IOffloadConfig service.");
+ return false;
+ }
+
+ // Per the IConfigOffload definition:
+ //
+ // fd1 A file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
+ //
+ // fd2 A file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
+ base::unique_fd
+ fd1(conntrackSocket(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)),
+ fd2(conntrackSocket(NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY));
+ if (fd1.get() < 0 || fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ return false;
+ }
+
+ hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
+ h2(handleFromFileDescriptor(std::move(fd2)));
+
+ bool rval(false);
+ hidl_string msg;
+ const auto status = configInterface->setHandles(h1, h2,
+ [&rval, &msg](bool success, const hidl_string& errMsg) {
+ rval = success;
+ msg = errMsg;
+ });
+ if (!status.isOk() || !rval) {
+ ALOGE("IOffloadConfig::setHandles() error: '%s' / '%s'",
+ status.description().c_str(), msg.c_str());
+ // If status is somehow not ok, make sure rval captures this too.
+ rval = false;
+ }
+
+ return rval;
+}
+
+static void android_net_util_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd,
+ jint ifIndex)
+{
+ static const int kLinkLocalHopLimit = 255;
+
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+
+ // Set an ICMPv6 filter that only passes Router Solicitations.
+ struct icmp6_filter rs_only;
+ ICMP6_FILTER_SETBLOCKALL(&rs_only);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only);
+ socklen_t len = sizeof(rs_only);
+ if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(ICMP6_FILTER): %s", strerror(errno));
+ return;
+ }
+
+ // Most/all of the rest of these options can be set via Java code, but
+ // because we're here on account of setting an icmp6_filter go ahead
+ // and do it all natively for now.
+
+ // Set the multicast hoplimit to 255 (link-local only).
+ int hops = kLinkLocalHopLimit;
+ len = sizeof(hops);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
+ return;
+ }
+
+ // Set the unicast hoplimit to 255 (link-local only).
+ hops = kLinkLocalHopLimit;
+ len = sizeof(hops);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
+ return;
+ }
+
+ // Explicitly disable multicast loopback.
+ int off = 0;
+ len = sizeof(off);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno));
+ return;
+ }
+
+ // Specify the IPv6 interface to use for outbound multicast.
+ len = sizeof(ifIndex);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno));
+ return;
+ }
+
+ // Additional options to be considered:
+ // - IPV6_TCLASS
+ // - IPV6_RECVPKTINFO
+ // - IPV6_RECVHOPLIMIT
+
+ // Bind to [::].
+ const struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ .sin6_port = 0,
+ .sin6_flowinfo = 0,
+ .sin6_addr = IN6ADDR_ANY_INIT,
+ .sin6_scope_id = 0,
+ };
+ auto sa = reinterpret_cast<const struct sockaddr *>(&sin6);
+ len = sizeof(sin6);
+ if (bind(fd, sa, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "bind(IN6ADDR_ANY): %s", strerror(errno));
+ return;
+ }
+
+ // Join the all-routers multicast group, ff02::2%index.
+ struct ipv6_mreq all_rtrs = {
+ .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}},
+ .ipv6mr_interface = ifIndex,
+ };
+ len = sizeof(all_rtrs);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno));
+ return;
+ }
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "configOffload", "()Z", (void*) android_net_util_configOffload },
+ { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_util_setupRaSocket },
+};
+
+int register_android_net_util_TetheringUtils(JNIEnv* env) {
+ return jniRegisterNativeMethods(env,
+ "android/net/util/TetheringUtils",
+ gMethods, NELEM(gMethods));
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("ERROR: GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_android_net_util_TetheringUtils(env) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
+
+}; // namespace android
diff --git a/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
deleted file mode 100644
index 663154a..0000000
--- a/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <error.h>
-#include <hidl/HidlSupport.h>
-#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netlink.h>
-#include <sys/socket.h>
-#include <android-base/unique_fd.h>
-#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
-
-#define LOG_TAG "OffloadHardwareInterface"
-#include <utils/Log.h>
-
-namespace android {
-
-using hardware::hidl_handle;
-using hardware::hidl_string;
-using hardware::tetheroffload::config::V1_0::IOffloadConfig;
-
-namespace {
-
-inline const sockaddr * asSockaddr(const sockaddr_nl *nladdr) {
- return reinterpret_cast<const sockaddr *>(nladdr);
-}
-
-int conntrackSocket(unsigned groups) {
- base::unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
- if (s.get() < 0) return -errno;
-
- const struct sockaddr_nl bind_addr = {
- .nl_family = AF_NETLINK,
- .nl_pad = 0,
- .nl_pid = 0,
- .nl_groups = groups,
- };
- if (bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
- return -errno;
- }
-
- const struct sockaddr_nl kernel_addr = {
- .nl_family = AF_NETLINK,
- .nl_pad = 0,
- .nl_pid = 0,
- .nl_groups = groups,
- };
- if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
- return -errno;
- }
-
- return s.release();
-}
-
-// Return a hidl_handle that owns the file descriptor owned by fd, and will
-// auto-close it (otherwise there would be double-close problems).
-//
-// Rely upon the compiler to eliminate the constexprs used for clarity.
-hidl_handle handleFromFileDescriptor(base::unique_fd fd) {
- hidl_handle h;
-
- static constexpr int kNumFds = 1;
- static constexpr int kNumInts = 0;
- native_handle_t *nh = native_handle_create(kNumFds, kNumInts);
- nh->data[0] = fd.release();
-
- static constexpr bool kTakeOwnership = true;
- h.setTo(nh, kTakeOwnership);
-
- return h;
-}
-
-} // namespace
-
-static jboolean android_server_connectivity_tethering_OffloadHardwareInterface_configOffload(
- JNIEnv* /* env */) {
- sp<IOffloadConfig> configInterface = IOffloadConfig::getService();
- if (configInterface.get() == nullptr) {
- ALOGD("Could not find IOffloadConfig service.");
- return false;
- }
-
- // Per the IConfigOffload definition:
- //
- // fd1 A file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
- //
- // fd2 A file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
- base::unique_fd
- fd1(conntrackSocket(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)),
- fd2(conntrackSocket(NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY));
- if (fd1.get() < 0 || fd2.get() < 0) {
- ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
- return false;
- }
-
- hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
- h2(handleFromFileDescriptor(std::move(fd2)));
-
- bool rval(false);
- hidl_string msg;
- const auto status = configInterface->setHandles(h1, h2,
- [&rval, &msg](bool success, const hidl_string& errMsg) {
- rval = success;
- msg = errMsg;
- });
- if (!status.isOk() || !rval) {
- ALOGE("IOffloadConfig::setHandles() error: '%s' / '%s'",
- status.description().c_str(), msg.c_str());
- // If status is somehow not ok, make sure rval captures this too.
- rval = false;
- }
-
- return rval;
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "configOffload", "()Z",
- (void*) android_server_connectivity_tethering_OffloadHardwareInterface_configOffload },
-};
-
-int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv* env) {
- return jniRegisterNativeMethods(env,
- "com/android/server/connectivity/tethering/OffloadHardwareInterface",
- gMethods, NELEM(gMethods));
-}
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- ALOGE("ERROR: GetEnv failed");
- return JNI_ERR;
- }
-
- if (register_android_server_connectivity_tethering_OffloadHardwareInterface(env) < 0) {
- return JNI_ERR;
- }
-
- return JNI_VERSION_1_6;
-}
-
-}; // namespace android
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/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
index 1fe2328..d6bc063 100644
--- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
+++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
@@ -20,11 +20,11 @@
import android.annotation.NonNull;
import android.net.LinkAddress;
-
-import com.google.android.collect.Sets;
+import android.util.ArraySet;
import java.net.Inet4Address;
import java.util.Collection;
+import java.util.Collections;
import java.util.Set;
/**
@@ -68,7 +68,7 @@
* but it must always be set explicitly.
*/
public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
- return setDefaultRouters(Sets.newArraySet(defaultRouters));
+ return setDefaultRouters(newArraySet(defaultRouters));
}
/**
@@ -96,7 +96,7 @@
* <p>This may be an empty list of servers, but it must always be set explicitly.
*/
public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) {
- return setDnsServers(Sets.newArraySet(dnsServers));
+ return setDnsServers(newArraySet(dnsServers));
}
/**
@@ -126,7 +126,7 @@
* and do not need to be set here.
*/
public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
- return setExcludedAddrs(Sets.newArraySet(excludedAddrs));
+ return setExcludedAddrs(newArraySet(excludedAddrs));
}
/**
@@ -169,4 +169,10 @@
}
return res;
}
+
+ private static ArraySet<Inet4Address> newArraySet(Inet4Address... addrs) {
+ ArraySet<Inet4Address> addrSet = new ArraySet<>(addrs.length);
+ Collections.addAll(addrSet, addrs);
+ return addrSet;
+ }
}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index ff3d7bc..abfb33c 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -17,10 +17,12 @@
package android.net.ip;
import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.util.NetworkConstants.FF;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.net.util.NetworkConstants.asByte;
+import static android.net.util.TetheringMessageBase.BASE_IPSERVER;
import android.net.ConnectivityManager;
import android.net.INetd;
@@ -30,7 +32,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;
@@ -47,11 +48,9 @@
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Log;
-import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.util.MessageUtils;
-import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -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,36 +148,31 @@
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;
// request from the user that it wants to tether
- public static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2;
+ public static final int CMD_TETHER_REQUESTED = BASE_IPSERVER + 1;
// request from the user that it wants to untether
- public static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3;
+ public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2;
// notification that this interface is down
- public static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4;
+ public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3;
// notification from the master SM that it had trouble enabling IP Forwarding
- public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7;
+ public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4;
// notification from the master SM that it had trouble disabling IP Forwarding
- public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8;
+ public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5;
// notification from the master SM that it had trouble starting tethering
- public static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9;
+ public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6;
// notification from the master SM that it had trouble stopping tethering
- public static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10;
+ public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7;
// notification from the master SM that it had trouble setting the DNS forwarders
- public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11;
+ public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8;
// the upstream connection has changed
- public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12;
+ public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9;
// new IPv6 tethering parameters need to be processed
- public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13;
+ public static final int CMD_IPV6_TETHER_UPDATE = BASE_IPSERVER + 10;
private final State mInitialState;
private final State mLocalHotspotState;
@@ -491,7 +485,9 @@
}
// Directly-connected route.
- final RouteInfo route = new RouteInfo(linkAddr);
+ final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(),
+ linkAddr.getPrefixLength());
+ final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST);
if (enabled) {
mLinkProperties.addLinkAddress(linkAddr);
mLinkProperties.addRoute(route);
@@ -1012,7 +1008,7 @@
String ifname, HashSet<IpPrefix> prefixes) {
final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
for (IpPrefix ipp : prefixes) {
- localRoutes.add(new RouteInfo(ipp, null, ifname));
+ localRoutes.add(new RouteInfo(ipp, null, ifname, RTN_UNICAST));
}
return localRoutes;
}
@@ -1024,7 +1020,7 @@
try {
return Inet6Address.getByAddress(null, dnsBytes, 0);
} catch (UnknownHostException e) {
- Slog.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix);
+ Log.wtf(TAG, "Failed to construct Inet6Address from: " + localPrefix);
return null;
}
}
diff --git a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index 4147413..bba61d7 100644
--- a/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -22,14 +22,14 @@
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.SOCK_RAW;
import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_BINDTODEVICE;
import static android.system.OsConstants.SO_SNDTIMEO;
import android.net.IpPrefix;
import android.net.LinkAddress;
-import android.net.NetworkUtils;
import android.net.TrafficStats;
import android.net.util.InterfaceParams;
+import android.net.util.SocketUtils;
+import android.net.util.TetheringUtils;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
@@ -38,8 +38,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.TrafficStatsConstants;
-import libcore.io.IoBridge;
-
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.Inet6Address;
@@ -611,9 +609,8 @@
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms));
- Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
- NetworkUtils.protectFromVpn(mSocket);
- NetworkUtils.setupRaSocket(mSocket, mInterface.index);
+ SocketUtils.bindSocketToInterface(mSocket, mInterface.name);
+ TetheringUtils.setupRaSocket(mSocket, mInterface.index);
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
@@ -627,7 +624,7 @@
private void closeSocket() {
if (mSocket != null) {
try {
- IoBridge.closeAndSignalBlockedThreads(mSocket);
+ SocketUtils.closeSocket(mSocket);
} catch (IOException ignored) { }
}
mSocket = null;
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
similarity index 65%
copy from core/java/android/net/ITetheringEventCallback.aidl
copy to packages/Tethering/src/android/net/util/TetheringMessageBase.java
index d502088..1b763ce 100644
--- a/core/java/android/net/ITetheringEventCallback.aidl
+++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,16 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package android.net;
-
-import android.net.Network;
+package android.net.util;
/**
- * Callback class for receiving tethering changed events
- * @hide
+ * This class defines Message.what base addresses for various state machine.
*/
-oneway interface ITetheringEventCallback
-{
- void onUpstreamChanged(in Network network);
+public class TetheringMessageBase {
+ public static final int BASE_MASTER = 0;
+ public static final int BASE_IPSERVER = 100;
+
}
diff --git a/packages/Tethering/src/android/net/util/TetheringUtils.java b/packages/Tethering/src/android/net/util/TetheringUtils.java
new file mode 100644
index 0000000..fa543bd
--- /dev/null
+++ b/packages/Tethering/src/android/net/util/TetheringUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.util;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+
+/**
+ * Native methods for tethering utilization.
+ *
+ * {@hide}
+ */
+public class TetheringUtils {
+
+ /**
+ * Offload management process need to know conntrack rules to support NAT, but it may not have
+ * permission to create netlink netfilter sockets. Create two netlink netfilter sockets and
+ * share them with offload management process.
+ */
+ public static native boolean configOffload();
+
+ /**
+ * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param ifIndex the interface index.
+ */
+ public static native void setupRaSocket(FileDescriptor fd, int ifIndex)
+ throws SocketException;
+
+ /**
+ * Read s as an unsigned 16-bit integer.
+ */
+ public static int uint16(short s) {
+ return s & 0xffff;
+ }
+}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index ba5d08d..7e685fb 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -38,7 +38,6 @@
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.util.SharedLog;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -48,7 +47,6 @@
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.util.ArraySet;
@@ -196,9 +194,9 @@
// till upstream change to cellular.
if (mUsingCellularAsUpstream) {
if (showProvisioningUi) {
- runUiTetherProvisioning(type, config.subId);
+ runUiTetherProvisioning(type, config.activeDataSubId);
} else {
- runSilentTetherProvisioning(type, config.subId);
+ runSilentTetherProvisioning(type, config.activeDataSubId);
}
mNeedReRunProvisioningUi = false;
} else {
@@ -270,9 +268,9 @@
if (mCellularPermitted.indexOfKey(downstream) < 0) {
if (mNeedReRunProvisioningUi) {
mNeedReRunProvisioningUi = false;
- runUiTetherProvisioning(downstream, config.subId);
+ runUiTetherProvisioning(downstream, config.activeDataSubId);
} else {
- runSilentTetherProvisioning(downstream, config.subId);
+ runSilentTetherProvisioning(downstream, config.activeDataSubId);
}
}
}
@@ -336,7 +334,8 @@
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager == null) return null;
- final PersistableBundle carrierConfig = configManager.getConfigForSubId(config.subId);
+ final PersistableBundle carrierConfig = configManager.getConfigForSubId(
+ config.activeDataSubId);
if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return carrierConfig;
@@ -379,12 +378,9 @@
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
intent.setComponent(TETHER_SERVICE);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.startServiceAsUser(intent, UserHandle.CURRENT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ // Only admin user can change tethering and SilentTetherProvisioning don't need to
+ // show UI, it is fine to always start setting's background service as system user.
+ mContext.startService(intent);
}
private void runUiTetherProvisioning(int type, int subId) {
@@ -407,12 +403,9 @@
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final long ident = Binder.clearCallingIdentity();
- try {
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ // Only launch entitlement UI for system user. Entitlement UI should not appear for other
+ // user because only admin user is allowed to change tethering.
+ mContext.startActivity(intent);
}
// Not needed to check if this don't run on the handler thread because it's private.
@@ -671,7 +664,7 @@
receiver.send(cacheValue, null);
} else {
ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
- runUiTetherProvisioning(downstream, config.subId, proxy);
+ runUiTetherProvisioning(downstream, config.activeDataSubId, proxy);
}
}
}
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..66b9ade 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;
@@ -30,6 +29,7 @@
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -72,7 +72,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 +115,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 +144,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));
@@ -261,7 +258,7 @@
final LinkProperties lp = new LinkProperties();
final IpPrefix local48 = makeUniqueLocalPrefix(ulp, (short) 0, 48);
- lp.addRoute(new RouteInfo(local48, null, null));
+ lp.addRoute(new RouteInfo(local48, null, null, RouteInfo.RTN_UNICAST));
final IpPrefix local64 = makeUniqueLocalPrefix(ulp, subnetId, 64);
// Because this is a locally-generated ULA, we don't have an upstream
@@ -277,7 +274,13 @@
final byte[] bytes = Arrays.copyOf(in6addr, in6addr.length);
bytes[7] = (byte) (subnetId >> 8);
bytes[8] = (byte) subnetId;
- return new IpPrefix(bytes, prefixlen);
+ final InetAddress addr;
+ try {
+ addr = InetAddress.getByAddress(bytes);
+ } catch (UnknownHostException e) {
+ throw new IllegalStateException("Invalid address length: " + bytes.length, e);
+ }
+ return new IpPrefix(addr, prefixlen);
}
// Generates a Unique Locally-assigned Prefix:
@@ -295,14 +298,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/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index 16734d8..38fa91e 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -25,6 +25,7 @@
import android.content.ContentResolver;
import android.net.ITetheringStatsProvider;
+import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -33,7 +34,6 @@
import android.net.netlink.ConntrackMessage;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkSocket;
-import android.net.util.IpUtils;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.INetworkManagementService;
@@ -477,9 +477,10 @@
if (!ri.hasGateway()) continue;
final String gateway = ri.getGateway().getHostAddress();
- if (ri.isIPv4Default()) {
+ final InetAddress address = ri.getDestination().getAddress();
+ if (ri.isDefaultRoute() && address instanceof Inet4Address) {
v4gateway = gateway;
- } else if (ri.isIPv6Default()) {
+ } else if (ri.isDefaultRoute() && address instanceof Inet6Address) {
v6gateways.add(gateway);
}
}
@@ -547,7 +548,10 @@
private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) {
// Ignore any link-local routes.
- if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true;
+ final IpPrefix destination = route.getDestination();
+ final LinkAddress linkAddr = new LinkAddress(destination.getAddress(),
+ destination.getPrefixLength());
+ if (!linkAddr.isGlobalPreferred()) return true;
return false;
}
@@ -588,7 +592,7 @@
return;
}
- if (!IpUtils.isValidUdpOrTcpPort(srcPort)) {
+ if (!isValidUdpOrTcpPort(srcPort)) {
mLog.e("Invalid src port: " + srcPort);
return;
}
@@ -599,7 +603,7 @@
return;
}
- if (!IpUtils.isValidUdpOrTcpPort(dstPort)) {
+ if (!isValidUdpOrTcpPort(dstPort)) {
mLog.e("Invalid dst port: " + dstPort);
return;
}
@@ -628,7 +632,7 @@
private static Inet4Address parseIPv4Address(String addrString) {
try {
- final InetAddress ip = InetAddress.parseNumericAddress(addrString);
+ final InetAddress ip = InetAddresses.parseNumericAddress(addrString);
// TODO: Consider other sanitization steps here, including perhaps:
// not eql to 0.0.0.0
// not within 169.254.0.0/16
@@ -668,4 +672,8 @@
return 180;
}
}
+
+ private static boolean isValidUdpOrTcpPort(int port) {
+ return port > 0 && port < 65536;
+ }
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 00a6773..4a8ef1f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -16,7 +16,7 @@
package com.android.server.connectivity.tethering;
-import static com.android.internal.util.BitUtils.uint16;
+import static android.net.util.TetheringUtils.uint16;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
@@ -24,6 +24,7 @@
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.net.util.SharedLog;
+import android.net.util.TetheringUtils;
import android.os.Handler;
import android.os.RemoteException;
import android.system.OsConstants;
@@ -47,8 +48,6 @@
private static final String NO_IPV4_ADDRESS = "";
private static final String NO_IPV4_GATEWAY = "";
- private static native boolean configOffload();
-
private final Handler mHandler;
private final SharedLog mLog;
private IOffloadControl mOffloadControl;
@@ -107,8 +106,6 @@
public OffloadHardwareInterface(Handler h, SharedLog log) {
mHandler = h;
mLog = log.forSubComponent(TAG);
-
- System.loadLibrary("tetheroffloadjni");
}
/** Get default value indicating whether offload is supported. */
@@ -118,7 +115,7 @@
/** Configure offload management process. */
public boolean initOffloadConfig() {
- return configOffload();
+ return TetheringUtils.configOffload();
}
/** Initialize the tethering offload HAL. */
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..2c8858e 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;
@@ -36,6 +37,7 @@
import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
import static android.net.ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.util.TetheringMessageBase.BASE_MASTER;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -63,13 +65,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 +90,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 +105,11 @@
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;
@@ -120,6 +120,8 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
/**
*
@@ -162,6 +164,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;
@@ -183,13 +187,13 @@
private final TetheringDependencies mDeps;
private final EntitlementManager mEntitlementMgr;
private final Handler mHandler;
- private final PhoneStateListener mPhoneStateListener;
private final INetd mNetd;
private final NetdCallback mNetdCallback;
private final UserRestrictionActionListener mTetheringRestriction;
+ private final ActiveDataSubIdListener mActiveDataSubIdListener;
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;
@@ -250,26 +254,6 @@
mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
});
- mPhoneStateListener = new PhoneStateListener(mLooper) {
- @Override
- public void onActiveDataSubscriptionIdChanged(int subId) {
- mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
- + " to " + subId);
- if (subId == mActiveDataSubId) return;
-
- mActiveDataSubId = subId;
- updateConfiguration();
- // To avoid launching unexpected provisioning checks, ignore re-provisioning when
- // no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be
- // triggered again when CarrierConfig is loaded.
- if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
- mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
- } else {
- mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded");
- }
- }
- };
-
mStateReceiver = new StateReceiver();
mNetdCallback = new NetdCallback();
@@ -282,6 +266,8 @@
final UserManager userManager = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
mTetheringRestriction = new UserRestrictionActionListener(userManager, this);
+ final TetheringThreadExecutor executor = new TetheringThreadExecutor(mHandler);
+ mActiveDataSubIdListener = new ActiveDataSubIdListener(executor);
// Load tethering configuration.
updateConfiguration();
@@ -292,8 +278,8 @@
private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening();
- mContext.getSystemService(TelephonyManager.class).listen(
- mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+ mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener,
+ PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_STATE);
@@ -312,6 +298,43 @@
}
+ private class TetheringThreadExecutor implements Executor {
+ private final Handler mTetherHandler;
+ TetheringThreadExecutor(Handler handler) {
+ mTetherHandler = handler;
+ }
+ @Override
+ public void execute(Runnable command) {
+ if (!mTetherHandler.post(command)) {
+ throw new RejectedExecutionException(mTetherHandler + " is shutting down");
+ }
+ }
+ }
+
+ private class ActiveDataSubIdListener extends PhoneStateListener {
+ ActiveDataSubIdListener(Executor executor) {
+ super(executor);
+ }
+
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
+ + " to " + subId);
+ if (subId == mActiveDataSubId) return;
+
+ mActiveDataSubId = subId;
+ updateConfiguration();
+ // To avoid launching unexpected provisioning checks, ignore re-provisioning
+ // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning()
+ // ill be triggered again when CarrierConfig is loaded.
+ if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
+ mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
+ } else {
+ mLog.log("IGNORED reevaluate provisioning, no carrier config loaded");
+ }
+ }
+ }
+
private WifiManager getWifiManager() {
return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
}
@@ -324,8 +347,7 @@
}
private void maybeDunSettingChanged() {
- final boolean isDunRequired = TetheringConfiguration.checkDunRequired(
- mContext, mActiveDataSubId);
+ final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
if (isDunRequired == mConfig.isDunRequired) return;
updateConfiguration();
}
@@ -573,6 +595,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 +615,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++) {
@@ -626,8 +653,7 @@
reportTetherStateChanged(mTetherStatesParcel);
final Intent bcast = new Intent(ACTION_TETHER_STATE_CHANGED);
- bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList);
bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList);
@@ -1144,7 +1170,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)) {
@@ -1156,7 +1182,6 @@
}
class TetherMasterSM extends StateMachine {
- private static final int BASE_MASTER = Protocol.BASE_TETHERING;
// an interface SM has requested Tethering/Local Hotspot
static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1;
// an interface SM has unrequested Tethering/Local Hotspot
@@ -1173,7 +1198,6 @@
static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7;
// Events from EntitlementManager to choose upstream again.
static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MASTER + 8;
-
private final State mInitialState;
private final State mTetherModeAliveState;
@@ -1312,7 +1336,7 @@
maybeDunSettingChanged();
final TetheringConfiguration config = mConfig;
- final NetworkState ns = (config.chooseUpstreamAutomatically)
+ final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically)
? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
: mUpstreamNetworkMonitor.selectPreferredUpstreamType(
config.preferredUpstreamIfaceTypes);
@@ -1333,7 +1357,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 +1373,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 +1410,7 @@
}
}
- protected void handleNewUpstreamNetworkState(NetworkState ns) {
+ protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
mOffload.updateUpstreamNetworkState(ns);
}
@@ -1450,7 +1474,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 +1744,7 @@
mOffloadController.stop();
}
- public void updateUpstreamNetworkState(NetworkState ns) {
+ public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
mOffloadController.setUpstreamLinkProperties(
(ns != null) ? ns.linkProperties : null);
}
@@ -1796,47 +1820,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 +1888,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/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 0ab4d63..490614b 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -100,13 +100,13 @@
public final String provisioningAppNoUi;
public final int provisioningCheckPeriod;
- public final int subId;
+ public final int activeDataSubId;
public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
- subId = id;
- Resources res = getResources(ctx, subId);
+ activeDataSubId = id;
+ Resources res = getResources(ctx, activeDataSubId);
tetherableUsbRegexs = getResourceStringArray(res, config_tether_usb_regexs);
// TODO: Evaluate deleting this altogether now that Wi-Fi always passes
@@ -116,7 +116,7 @@
tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs);
tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
- isDunRequired = checkDunRequired(ctx, subId);
+ isDunRequired = checkDunRequired(ctx);
chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
@@ -166,8 +166,8 @@
/** Does the dumping.*/
public void dump(PrintWriter pw) {
- pw.print("subId: ");
- pw.println(subId);
+ pw.print("activeDataSubId: ");
+ pw.println(activeDataSubId);
dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
@@ -196,7 +196,7 @@
/** Returns the string representation of this object.*/
public String toString() {
final StringJoiner sj = new StringJoiner(" ");
- sj.add(String.format("subId:%d", subId));
+ sj.add(String.format("activeDataSubId:%d", activeDataSubId));
sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
@@ -250,9 +250,11 @@
}
/** Check whether dun is required. */
- public static boolean checkDunRequired(Context ctx, int id) {
+ public static boolean checkDunRequired(Context ctx) {
final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
- return (tm != null) ? tm.isTetheringApnRequired(id) : false;
+ // TelephonyManager would uses the active data subscription, which should be the one used
+ // by tethering.
+ return (tm != null) ? tm.isTetheringApnRequired() : false;
}
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
@@ -391,7 +393,7 @@
*/
public TetheringConfigurationParcel toStableParcelable() {
final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel();
- parcel.subId = subId;
+ parcel.subId = activeDataSubId;
parcel.tetherableUsbRegexs = tetherableUsbRegexs;
parcel.tetherableWifiRegexs = tetherableWifiRegexs;
parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs;
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..775484e 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,37 @@
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 static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
+
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 +69,7 @@
private Context mContext;
private TetheringDependencies mDeps;
private Tethering mTethering;
+ private UserManager mUserManager;
@Override
public void onCreate() {
@@ -59,6 +77,7 @@
mDeps = getTetheringDependencies();
mContext = mDeps.getContext();
mTethering = makeTethering(mDeps);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
/**
@@ -66,6 +85,7 @@
*/
@VisibleForTesting
public Tethering makeTethering(TetheringDependencies deps) {
+ System.loadLibrary("tetherutilsjni");
return new Tethering(deps);
}
@@ -74,7 +94,7 @@
*/
private synchronized IBinder makeConnector() {
if (mConnector == null) {
- mConnector = new TetheringConnector(mTethering);
+ mConnector = new TetheringConnector(mTethering, TetheringService.this);
}
return mConnector;
}
@@ -87,55 +107,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 +321,58 @@
@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) {
+ Log.e(TAG, "Fail to make dhcp server");
+ try {
+ cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null);
+ } catch (RemoteException re) { }
+ }
+ }
+ };
+ }
+
+ // 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..22150f6 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
@@ -329,22 +328,15 @@
network, newNc));
}
- // Log changes in upstream network signal strength, if available.
- if (network.equals(mTetheringUpstreamNetwork) && newNc.hasSignalStrength()) {
- final int newSignal = newNc.getSignalStrength();
- final String prevSignal = getSignalStrength(prev.networkCapabilities);
- 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 +349,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 +501,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 +524,7 @@
nc.setSingleUid(Process.myUid());
- for (NetworkState value : netStates) {
+ for (UpstreamNetworkState value : netStates) {
if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) {
continue;
}
@@ -546,10 +538,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));
@@ -558,12 +550,7 @@
return prefixSet;
}
- private static String getSignalStrength(NetworkCapabilities nc) {
- if (nc == null || !nc.hasSignalStrength()) return "unknown";
- 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 +559,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..53782fed 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -20,7 +20,11 @@
srcs: [
"src/**/*.java",
],
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "mts",
+ ],
+ compile_multilib: "both",
static_libs: [
"androidx.test.rules",
"frameworks-base-testutils",
@@ -33,10 +37,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/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
index e01ac7f..e8add98 100644
--- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
@@ -18,8 +18,6 @@
import static android.net.InetAddresses.parseNumericAddress;
-import static com.google.android.collect.Sets.newHashSet;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -34,6 +32,8 @@
import org.junit.runner.RunWith;
import java.net.Inet4Address;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -47,9 +47,10 @@
private static final int TEST_LEASE_TIME_SECS = 120;
private static final int TEST_MTU = 1000;
private static final Set<Inet4Address> TEST_ADDRESS_SET =
- newHashSet(inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124"));
+ new HashSet<Inet4Address>(Arrays.asList(
+ new Inet4Address[] {inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124")}));
private static final Set<Integer> TEST_ADDRESS_SET_PARCELED =
- newHashSet(0xc0a8017b, 0xc0a8017c);
+ new HashSet<Integer>(Arrays.asList(new Integer[] {0xc0a8017b, 0xc0a8017c}));
private DhcpServingParamsParcelExt mParcel;
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 4358cd6..fd2f708 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -510,8 +510,10 @@
}
assertNotNull("missing IPv4 address", addr4);
+ final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength());
// Assert the presence of the associated directly connected route.
- final RouteInfo directlyConnected = new RouteInfo(addr4, null, lp.getInterfaceName());
+ final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(),
+ RouteInfo.RTN_UNICAST);
assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
lp.getRoutes().contains(directlyConnected));
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 8574f54..7886ca6 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -21,6 +21,7 @@
import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.TrafficStats.UID_TETHERING;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
@@ -269,7 +270,7 @@
final String ipv4Addr = "192.0.2.5";
final String linkAddr = ipv4Addr + "/24";
lp.addLinkAddress(new LinkAddress(linkAddr));
- lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24")));
+ lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// IPv4 prefixes and addresses on the upstream are simply left as whole
// prefixes (already passed in from UpstreamNetworkMonitor code). If a
@@ -285,7 +286,7 @@
inOrder.verifyNoMoreInteractions();
final String ipv4Gateway = "192.0.2.1";
- lp.addRoute(new RouteInfo(InetAddress.getByName(ipv4Gateway)));
+ lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv4Gateway), null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
@@ -296,7 +297,7 @@
inOrder.verifyNoMoreInteractions();
final String ipv6Gw1 = "fe80::cafe";
- lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw1)));
+ lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw1), null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
@@ -310,7 +311,7 @@
inOrder.verifyNoMoreInteractions();
final String ipv6Gw2 = "fe80::d00d";
- lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw2)));
+ lp.addRoute(new RouteInfo(null, InetAddress.getByName(ipv6Gw2), null, RTN_UNICAST));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture());
@@ -327,8 +328,10 @@
final LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName("stacked");
stacked.addLinkAddress(new LinkAddress("192.0.2.129/25"));
- stacked.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
- stacked.addRoute(new RouteInfo(InetAddress.getByName("fe80::bad:f00")));
+ stacked.addRoute(new RouteInfo(null, InetAddress.getByName("192.0.2.254"), null,
+ RTN_UNICAST));
+ stacked.addRoute(new RouteInfo(null, InetAddress.getByName("fe80::bad:f00"), null,
+ RTN_UNICAST));
assertTrue(lp.addStackedLink(stacked));
offload.setUpstreamLinkProperties(lp);
// No change in local addresses means no call to setLocalPrefixes().
@@ -348,7 +351,7 @@
// removed from "local prefixes" and /128s added for the upstream IPv6
// addresses. This is not yet implemented, and for now we simply
// expect to see these /128s.
- lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64")));
+ lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"), null, null, RTN_UNICAST));
// "2001:db8::/64" plus "assigned" ASCII in hex
lp.addLinkAddress(new LinkAddress("2001:db8::6173:7369:676e:6564/64"));
// "2001:db8::/64" plus "random" ASCII in hex
@@ -574,13 +577,15 @@
final LinkProperties usbLinkProperties = new LinkProperties();
usbLinkProperties.setInterfaceName(RNDIS0);
usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX);
inOrder.verifyNoMoreInteractions();
// [2] Routes for IPv6 link-local prefixes should never be added.
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString());
inOrder.verifyNoMoreInteractions();
@@ -588,7 +593,8 @@
// [3] Add an IPv6 prefix for good measure. Only new offload-able
// prefixes should be passed to the HAL.
usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64"));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
inOrder.verifyNoMoreInteractions();
@@ -601,8 +607,10 @@
// [5] Differences in local routes are converted into addDownstream()
// and removeDownstream() invocations accordingly.
- usbLinkProperties.removeRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX)));
+ usbLinkProperties.removeRoute(
+ new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0, RTN_UNICAST));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX);
@@ -680,19 +688,23 @@
final LinkProperties usbLinkProperties = new LinkProperties();
usbLinkProperties.setInterfaceName(RNDIS0);
usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
- usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX)));
+ usbLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
final LinkProperties wifiLinkProperties = new LinkProperties();
wifiLinkProperties.setInterfaceName(WLAN0);
wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24"));
- wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX)));
- wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL)));
+ wifiLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(WIFI_PREFIX), null, null, RTN_UNICAST));
+ wifiLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
// Use a benchmark prefix (RFC 5180 + erratum), since the documentation
// prefix is included in the excluded prefix list.
wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64"));
wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64"));
- wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64")));
+ wifiLinkProperties.addRoute(
+ new RouteInfo(new IpPrefix("2001:2::/64"), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(wifiLinkProperties);
offload.removeDownstreamInterface(RNDIS0);
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index 30bff35..7799da4 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -34,7 +34,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
@@ -145,7 +144,7 @@
@Test
public void testDunFromTelephonyManagerMeansDun() {
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(true);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true);
final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -169,7 +168,7 @@
@Test
public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -212,7 +211,7 @@
@Test
public void testNoDefinedUpstreamTypesAddsEthernet() {
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{});
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -235,7 +234,7 @@
public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -253,7 +252,7 @@
public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
when(mResources.getIntArray(config_tether_upstream_types))
.thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
- when(mTelephonyManager.isTetheringApnRequired(anyInt())).thenReturn(false);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
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..809f0e9 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,8 +27,8 @@
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.RouteInfo.RTN_UNICAST;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
@@ -72,7 +72,8 @@
import android.net.INetd;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
-import android.net.ITetherInternalCallback;
+import android.net.ITetheringEventCallback;
+import android.net.InetAddresses;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -81,8 +82,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkState;
-import android.net.NetworkUtils;
+import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.net.TetherStatesParcel;
import android.net.TetheringConfigurationParcel;
@@ -167,6 +167,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 +312,11 @@
}
@Override
+ public NetworkRequest getDefaultNetworkRequest() {
+ return mNetworkRequest;
+ }
+
+ @Override
public boolean isTetheringSupported() {
mIsTetheringSupportedCalls++;
return true;
@@ -353,32 +359,33 @@
}
}
- 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);
if (withIPv4) {
prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
+ InetAddresses.parseNumericAddress("10.0.0.1"),
+ TEST_MOBILE_IFNAME, RTN_UNICAST));
}
if (withIPv6) {
- prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
+ prop.addDnsServer(InetAddresses.parseNumericAddress("2001:db8::2"));
prop.addLinkAddress(
- new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
+ new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
NetworkConstants.RFC7421_PREFIX_LENGTH));
prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
- NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
+ InetAddresses.parseNumericAddress("2001:db8::1"),
+ TEST_MOBILE_IFNAME, RTN_UNICAST));
}
if (with464xlat) {
final LinkProperties stackedLink = new LinkProperties();
stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
- NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
+ InetAddresses.parseNumericAddress("192.0.0.1"),
+ TEST_XLAT_MOBILE_IFNAME, RTN_UNICAST));
prop.addStackedLink(stackedLink);
}
@@ -386,22 +393,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 +562,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 +577,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 +657,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 +673,7 @@
mLooper.dispatchAll();
}
- private void runUsbTethering(NetworkState upstreamState) {
+ private void runUsbTethering(UpstreamNetworkState upstreamState) {
prepareUsbTethering(upstreamState);
sendUsbBroadcast(true, true, true);
mLooper.dispatchAll();
@@ -674,7 +681,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 +696,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 +705,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 +718,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 +733,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 +751,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 +789,7 @@
sendConfigurationChanged();
// Setup IPv6
- final NetworkState upstreamState = buildMobileIPv6UpstreamState();
+ final UpstreamNetworkState upstreamState = buildMobileIPv6UpstreamState();
runUsbTethering(upstreamState);
// UpstreamNetworkMonitor should choose upstream automatically
@@ -1039,7 +1046,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 +1107,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 +1125,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 +1159,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,25 +1189,37 @@
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
public void testMultiSimAware() throws Exception {
final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration();
- assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.subId);
+ assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.activeDataSubId);
final int fakeSubId = 1234;
mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration();
- assertEquals(fakeSubId, newConfig.subId);
+ assertEquals(fakeSubId, newConfig.activeDataSubId);
}
private void workingWifiP2pGroupOwner(
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 3b56607..943e491 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -72,6 +72,7 @@
libs: [
"android.hidl.manager-V1.0-java",
+ "framework-tethering"
],
plugins: [
@@ -101,3 +102,35 @@
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-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"],
+ check_api: {
+ current: {
+ api_file: "api/current.txt",
+ removed_api_file: "api/removed.txt",
+ },
+ },
+}
+
+java_library {
+ name: "services-stubs",
+ srcs: [":services-stubs.sources"],
+ installable: false,
+}
diff --git a/services/api/current.txt b/services/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/api/removed.txt b/services/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 725303d..4c569ef 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -27,8 +27,9 @@
"android.hardware.light-V2.0-java",
"android.hardware.power-V1.0-java",
"android.hardware.tv.cec-V1.0-java",
+ "android.hardware.vibrator-java",
"app-compat-annotations",
- "vintf-vibrator-java",
+ "framework-tethering",
],
required: [
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b719435..49cfa7b 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();
@@ -3054,25 +3022,9 @@
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
// Finish setting up the full connection
- mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
- AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- // A network factory has connected. Send it all current NetworkRequests.
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.request.isListen()) continue;
- ensureRunningOnConnectivityServiceThread();
- NetworkAgentInfo nai = nri.mSatisfier;
- final int score;
- final int serial;
- if (nai != null) {
- score = nai.getCurrentScore();
- serial = nai.factorySerialNumber;
- } else {
- score = 0;
- serial = NetworkFactory.SerialNumber.NONE;
- }
- ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, serial,
- nri.request);
- }
+ NetworkFactoryInfo nfi = mNetworkFactoryInfos.get(msg.replyTo);
+ nfi.completeConnection();
+ sendAllRequestsToFactory(nfi);
} else {
loge("Error connecting NetworkFactory");
mNetworkFactoryInfos.remove(msg.obj);
@@ -3455,8 +3407,7 @@
}
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
- nri.request);
+ nfi.cancelRequest(nri.request);
}
} else {
// listens don't have a singular affectedNetwork. Check all networks to see
@@ -3993,183 +3944,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.
@@ -5080,16 +4903,33 @@
private static class NetworkFactoryInfo {
public final String name;
public final Messenger messenger;
- public final AsyncChannel asyncChannel;
+ private final AsyncChannel mAsyncChannel;
public final int factorySerialNumber;
NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
int factorySerialNumber) {
this.name = name;
this.messenger = messenger;
- this.asyncChannel = asyncChannel;
+ this.mAsyncChannel = asyncChannel;
this.factorySerialNumber = factorySerialNumber;
}
+
+ void requestNetwork(NetworkRequest request, int score, int servingSerialNumber) {
+ mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
+ servingSerialNumber, request);
+ }
+
+ void cancelRequest(NetworkRequest request) {
+ mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request);
+ }
+
+ void connect(Context context, Handler handler) {
+ mAsyncChannel.connect(context, handler, messenger);
+ }
+
+ void completeConnection() {
+ mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ }
}
private void ensureNetworkRequestHasType(NetworkRequest request) {
@@ -5478,7 +5318,7 @@
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
mNetworkFactoryInfos.put(nfi.messenger, nfi);
- nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
+ nfi.connect(mContext, mTrackerHandler);
}
@Override
@@ -6114,8 +5954,26 @@
log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
}
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
- serial, networkRequest);
+ nfi.requestNetwork(networkRequest, score, serial);
+ }
+ }
+
+ /** Sends all current NetworkRequests to the specified factory. */
+ private void sendAllRequestsToFactory(NetworkFactoryInfo nfi) {
+ ensureRunningOnConnectivityServiceThread();
+ for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ if (nri.request.isListen()) continue;
+ NetworkAgentInfo nai = nri.mSatisfier;
+ final int score;
+ final int serial;
+ if (nai != null) {
+ score = nai.getCurrentScore();
+ serial = nai.factorySerialNumber;
+ } else {
+ score = 0;
+ serial = NetworkFactory.SerialNumber.NONE;
+ }
+ nfi.requestNetwork(nri.request, score, serial);
}
}
@@ -7050,14 +6908,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/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 9dead16..aeb3e7f 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -41,7 +41,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -582,11 +582,9 @@
}
int numFound = 0, numArgs = searchArgs.size();
- Time time = new Time();
out.append("\n");
for (EntryFile entry : mAllFiles.contents) {
- time.set(entry.timestampMillis);
- String date = time.format("%Y-%m-%d %H:%M:%S");
+ String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis);
boolean match = true;
for (int i = 0; i < numArgs && match; i++) {
String arg = searchArgs.get(i);
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..9b1326b 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+
import android.Manifest;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -37,6 +39,7 @@
import android.os.UserHandle;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -137,11 +140,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 +368,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(),
@@ -523,11 +515,11 @@
// Grant permission for the carrier app.
Intent intent = new Intent(action);
- TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- List<String> carrierPackages =
- telephonyManager.getCarrierPackageNamesForIntentAndPhone(
- intent, SubscriptionManager.getPhoneId(subId));
+ TelephonyManager telephonyManager = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ List<String> carrierPackages = telephonyManager
+ .getCarrierPackageNamesForIntentAndPhone(
+ intent, getPhoneIdFromSubId(subId));
if (carrierPackages != null && carrierPackages.size() == 1) {
LocalServices.getService(UriGrantsManagerInternal.class)
.grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
@@ -539,4 +531,13 @@
return contentUri;
}
}
+
+ private int getPhoneIdFromSubId(int subId) {
+ SubscriptionManager subManager = (SubscriptionManager)
+ mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+ SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+ if (info == null) return INVALID_SIM_SLOT_INDEX;
+ return info.getSimSlotIndex();
+ }
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
index b0b45f4..cfe56052 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceImpl.java
@@ -18,6 +18,8 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
+import android.app.timedetector.NetworkTimeSuggestion;
+import android.app.timedetector.TimeDetector;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,29 +40,27 @@
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.TimeUtils;
+import android.util.TimestampedValue;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
- * Monitors the network time and updates the system time if it is out of sync
- * and there hasn't been any NITZ update from the carrier recently.
- * If looking up the network time fails for some reason, it tries a few times with a short
- * interval and then resets to checking on longer intervals.
- * <p>
- * If the user enables AUTO_TIME, it will check immediately for the network time, if NITZ wasn't
- * available.
- * </p>
+ * Monitors the network time. If looking up the network time fails for some reason, it tries a few
+ * times with a short interval and then resets to checking on longer intervals.
+ *
+ * <p>When available, the time is always suggested to the {@link
+ * com.android.server.timedetector.TimeDetectorService} where it may be used to set the device
+ * system clock, depending on user settings and what other signals are available.
*/
public class NetworkTimeUpdateServiceImpl extends Binder implements NetworkTimeUpdateService {
private static final String TAG = "NetworkTimeUpdateService";
private static final boolean DBG = false;
- private static final int EVENT_AUTO_TIME_CHANGED = 1;
+ private static final int EVENT_AUTO_TIME_ENABLED = 1;
private static final int EVENT_POLL_NETWORK_TIME = 2;
private static final int EVENT_NETWORK_CHANGED = 3;
@@ -69,20 +69,19 @@
private static final int POLL_REQUEST = 0;
- private static final long NOT_SET = -1;
- private long mNitzTimeSetTime = NOT_SET;
private Network mDefaultNetwork = null;
private final Context mContext;
private final NtpTrustedTime mTime;
private final AlarmManager mAlarmManager;
+ private final TimeDetector mTimeDetector;
private final ConnectivityManager mCM;
private final PendingIntent mPendingPollIntent;
private final PowerManager.WakeLock mWakeLock;
// NTP lookup is done on this thread and handler
private Handler mHandler;
- private SettingsObserver mSettingsObserver;
+ private AutoTimeSettingObserver mAutoTimeSettingObserver;
private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
// Normal polling frequency
@@ -91,8 +90,6 @@
private final long mPollingIntervalShorterMs;
// Number of times to try again
private final int mTryAgainTimesMax;
- // If the time difference is greater than this threshold, then update the time.
- private final int mTimeErrorThresholdMs;
// Keeps track of how many quick attempts were made to fetch NTP time.
// During bootup, the network may not have been up yet, or it's taking time for the
// connection to happen.
@@ -102,6 +99,7 @@
mContext = context;
mTime = NtpTrustedTime.getInstance(context);
mAlarmManager = mContext.getSystemService(AlarmManager.class);
+ mTimeDetector = mContext.getSystemService(TimeDetector.class);
mCM = mContext.getSystemService(ConnectivityManager.class);
Intent pollIntent = new Intent(ACTION_POLL, null);
@@ -113,8 +111,6 @@
com.android.internal.R.integer.config_ntpPollingIntervalShorter);
mTryAgainTimesMax = mContext.getResources().getInteger(
com.android.internal.R.integer.config_ntpRetry);
- mTimeErrorThresholdMs = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_ntpThreshold);
mWakeLock = context.getSystemService(PowerManager.class).newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG);
@@ -122,7 +118,6 @@
@Override
public void systemRunning() {
- registerForTelephonyIntents();
registerForAlarms();
HandlerThread thread = new HandlerThread(TAG);
@@ -131,14 +126,9 @@
mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);
- mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
- mSettingsObserver.observe(mContext);
- }
-
- private void registerForTelephonyIntents() {
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
- mContext.registerReceiver(mNitzReceiver, intentFilter);
+ mAutoTimeSettingObserver = new AutoTimeSettingObserver(mContext, mHandler,
+ EVENT_AUTO_TIME_ENABLED);
+ mAutoTimeSettingObserver.observe();
}
private void registerForAlarms() {
@@ -152,8 +142,7 @@
}
private void onPollNetworkTime(int event) {
- // If Automatic time is not set, don't bother. Similarly, if we don't
- // have any default network, don't bother.
+ // If we don't have any default network, don't bother.
if (mDefaultNetwork == null) return;
mWakeLock.acquire();
try {
@@ -173,10 +162,12 @@
if (mTime.getCacheAge() < mPollingIntervalMs) {
// Obtained fresh fix; schedule next normal update
resetAlarm(mPollingIntervalMs);
- if (isAutomaticTimeRequested()) {
- updateSystemClock(event);
- }
+ // Suggest the time to the time detector. It may choose use it to set the system clock.
+ TimestampedValue<Long> timeSignal = mTime.getCachedNtpTimeSignal();
+ NetworkTimeSuggestion timeSuggestion = new NetworkTimeSuggestion(timeSignal);
+ timeSuggestion.addDebugInfo("Origin: NetworkTimeUpdateServiceImpl. event=" + event);
+ mTimeDetector.suggestNetworkTime(timeSuggestion);
} else {
// No fresh fix; schedule retry
mTryAgainCounter++;
@@ -190,36 +181,6 @@
}
}
- private long getNitzAge() {
- if (mNitzTimeSetTime == NOT_SET) {
- return Long.MAX_VALUE;
- } else {
- return SystemClock.elapsedRealtime() - mNitzTimeSetTime;
- }
- }
-
- /**
- * Consider updating system clock based on current NTP fix, if requested by
- * user, significant enough delta, and we don't have a recent NITZ.
- */
- private void updateSystemClock(int event) {
- final boolean forceUpdate = (event == EVENT_AUTO_TIME_CHANGED);
- if (!forceUpdate) {
- if (getNitzAge() < mPollingIntervalMs) {
- if (DBG) Log.d(TAG, "Ignoring NTP update due to recent NITZ");
- return;
- }
-
- final long skew = Math.abs(mTime.currentTimeMillis() - System.currentTimeMillis());
- if (skew < mTimeErrorThresholdMs) {
- if (DBG) Log.d(TAG, "Ignoring NTP update due to low skew");
- return;
- }
- }
-
- SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis());
- }
-
/**
* Cancel old alarm and starts a new one for the specified interval.
*
@@ -232,27 +193,6 @@
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
}
- /**
- * Checks if the user prefers to automatically set the time.
- */
- private boolean isAutomaticTimeRequested() {
- return Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.AUTO_TIME, 0) != 0;
- }
-
- /** Receiver for Nitz time events */
- private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() {
-
- @Override
- 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)) {
- mNitzTimeSetTime = SystemClock.elapsedRealtime();
- }
- }
- };
-
/** Handler to do the network accesses on */
private class MyHandler extends Handler {
@@ -263,7 +203,7 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case EVENT_AUTO_TIME_CHANGED:
+ case EVENT_AUTO_TIME_ENABLED:
case EVENT_POLL_NETWORK_TIME:
case EVENT_NETWORK_CHANGED:
onPollNetworkTime(msg.what);
@@ -287,27 +227,42 @@
}
}
- /** Observer to watch for changes to the AUTO_TIME setting */
- private static class SettingsObserver extends ContentObserver {
+ /**
+ * Observer to watch for changes to the AUTO_TIME setting. It only triggers when the setting
+ * is enabled.
+ */
+ private static class AutoTimeSettingObserver extends ContentObserver {
- private int mMsg;
- private Handler mHandler;
+ private final Context mContext;
+ private final int mMsg;
+ private final Handler mHandler;
- SettingsObserver(Handler handler, int msg) {
+ AutoTimeSettingObserver(Context context, Handler handler, int msg) {
super(handler);
+ mContext = context;
mHandler = handler;
mMsg = msg;
}
- void observe(Context context) {
- ContentResolver resolver = context.getContentResolver();
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
false, this);
}
@Override
public void onChange(boolean selfChange) {
- mHandler.obtainMessage(mMsg).sendToTarget();
+ if (isAutomaticTimeEnabled()) {
+ mHandler.obtainMessage(mMsg).sendToTarget();
+ }
+ }
+
+ /**
+ * Checks if the user prefers to automatically set the time.
+ */
+ private boolean isAutomaticTimeEnabled() {
+ ContentResolver resolver = mContext.getContentResolver();
+ return Settings.Global.getInt(resolver, Settings.Global.AUTO_TIME, 0) != 0;
}
}
@@ -319,8 +274,6 @@
pw.print("\nPollingIntervalShorterMs: ");
TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
- pw.print("TimeErrorThresholdMs: ");
- TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
pw.println("\nTryAgainCounter: " + mTryAgainCounter);
pw.println("NTP cache age: " + mTime.getCacheAge());
pw.println("NTP cache certainty: " + mTime.getCacheCertainty());
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 08cec2e..a788fc8 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -16,12 +16,14 @@
package com.android.server;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_DATA;
import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_VOICE;
import static java.util.Arrays.copyOf;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
@@ -30,7 +32,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;
@@ -58,6 +59,7 @@
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -96,7 +98,7 @@
* and 15973975 by saving the phoneId of the registrant and then using the
* phoneId when deciding to to make a callback. This is necessary because
* a subId changes from to a dummy value when a SIM is removed and thus won't
- * compare properly. Because SubscriptionManager.getPhoneId(int subId) handles
+ * compare properly. Because getPhoneIdFromSubId(int subId) handles
* the dummy value conversion we properly do the callbacks.
*
* Eventually we may want to remove the notion of dummy value but for now this
@@ -113,6 +115,7 @@
Context context;
String callingPackage;
+ String callingFeatureId;
IBinder binder;
@@ -129,7 +132,7 @@
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0);
@@ -146,7 +149,7 @@
boolean canReadCallLog() {
try {
return TelephonyPermissions.checkReadCallLog(
- context, subId, callerPid, callerUid, callingPackage);
+ context, subId, callerPid, callerUid, callingPackage, callingFeatureId);
} catch (SecurityException e) {
return false;
}
@@ -227,7 +230,7 @@
private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+ private int mDefaultPhoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private int[] mRingingCallState;
@@ -256,7 +259,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;
@@ -354,7 +359,7 @@
SubscriptionManager.getDefaultSubscriptionId());
int newDefaultPhoneId = intent.getIntExtra(
SubscriptionManager.EXTRA_SLOT_INDEX,
- SubscriptionManager.getPhoneId(newDefaultSubId));
+ getPhoneIdFromSubId(newDefaultSubId));
if (DBG) {
log("onReceive:current mDefaultSubId=" + mDefaultSubId
+ " current mDefaultPhoneId=" + mDefaultPhoneId
@@ -410,7 +415,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);
@@ -418,6 +422,7 @@
if (mNumPhones < oldNumPhones) {
cutListToSize(mCellInfo, mNumPhones);
cutListToSize(mImsReasonInfo, mNumPhones);
+ cutListToSize(mPreciseDataConnectionStates, mNumPhones);
return;
}
@@ -441,14 +446,14 @@
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ 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
@@ -509,7 +514,7 @@
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<>();
mEmergencyNumberList = new HashMap<>();
@@ -534,14 +539,14 @@
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ 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
@@ -567,7 +572,7 @@
}
@Override
- public void addOnSubscriptionsChangedListener(String callingPackage,
+ public void addOnSubscriptionsChangedListener(String callingPackage, String callingFeatureId,
IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
@@ -589,6 +594,7 @@
r.context = mContext;
r.onSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
@@ -621,7 +627,7 @@
@Override
public void addOnOpportunisticSubscriptionsChangedListener(String callingPackage,
- IOnSubscriptionsChangedListener callback) {
+ String callingFeatureId, IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (VDBG) {
@@ -642,6 +648,7 @@
r.context = mContext;
r.onOpportunisticSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
@@ -717,21 +724,28 @@
}
}
+ @Deprecated
@Override
- public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
+ public void listen(String callingPackage, IPhoneStateListener callback, int events,
boolean notifyNow) {
- listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
- events, notifyNow);
+ listenWithFeature(callingPackage, null, callback, events, notifyNow);
}
@Override
- public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback,
- int events, boolean notifyNow) {
- listen(pkgForDebug, callback, events, notifyNow, subId);
+ public void listenWithFeature(String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow) {
+ listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage,
+ callingFeatureId, callback, events, notifyNow);
}
- private void listen(String callingPackage, IPhoneStateListener callback, int events,
- boolean notifyNow, int subId) {
+ @Override
+ public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow) {
+ listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId);
+ }
+
+ private void listen(String callingPackage, @Nullable String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
String str = "listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
@@ -746,11 +760,12 @@
// Checks permission and throws SecurityException for disallowed operations. For pre-M
// apps whose runtime permission has been revoked, we return immediately to skip sending
// events to the app without crashing it.
- if (!checkListenerPermission(events, subId, callingPackage, "listen")) {
+ if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
+ "listen")) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
@@ -763,6 +778,7 @@
r.context = mContext;
r.callback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
@@ -785,9 +801,11 @@
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onServiceStateChanged(rawSs);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(false));
} else {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(true));
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -896,8 +914,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);
}
@@ -911,7 +931,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);
}
@@ -1073,7 +1094,7 @@
// Called only by Telecomm to communicate call state across different phone accounts. So
// there is no need to add a valid subId or slotId.
broadcastCallStateChanged(state, phoneNumber,
- SubscriptionManager.INVALID_PHONE_INDEX,
+ SubscriptionManager.INVALID_SIM_SLOT_INDEX,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
@@ -1140,9 +1161,9 @@
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
stateToSend = new ServiceState(state);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = state.sanitizeLocationInfo(false);
+ stateToSend = state.createLocationInfoSanitizedCopy(false);
} else {
- stateToSend = state.sanitizeLocationInfo(true);
+ stateToSend = state.createLocationInfoSanitizedCopy(true);
}
if (DBG) {
log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -1297,7 +1318,7 @@
synchronized (mRecords) {
mCarrierNetworkChangeState = active;
for (int subId : subIds) {
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
if (VDBG) {
log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId);
@@ -1330,7 +1351,7 @@
log("notifyCellInfoForSubscriber: subId=" + subId
+ " cellInfo=" + cellInfo);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCellInfo.set(phoneId, cellInfo);
@@ -1421,7 +1442,7 @@
log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCallForwarding[phoneId] = cfi;
@@ -1449,7 +1470,7 @@
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mDataActivity[phoneId] = state;
@@ -1469,30 +1490,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.
@@ -1524,33 +1553,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);
+
+ 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) {
@@ -1563,17 +1604,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);
}
@@ -1583,7 +1627,6 @@
handleRemoveListLocked();
}
- broadcastDataConnectionFailed(apnType, subId);
}
public void notifyCellLocation(Bundle cellLocation) {
@@ -1600,7 +1643,7 @@
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mCellLocation[phoneId] = cellLocation;
@@ -1709,7 +1752,7 @@
if (!checkNotifyPermission("notifyImsCallDisconnectCause()")) {
return;
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mImsReasonInfo.set(phoneId, imsReasonInfo);
@@ -1738,25 +1781,32 @@
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();
}
}
@@ -1769,7 +1819,7 @@
if (VDBG) {
log("notifySrvccStateChanged: subId=" + subId + " srvccState=" + state);
}
- int phoneId = SubscriptionManager.getPhoneId(subId);
+ int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mSrvccState[phoneId] = state;
@@ -2014,7 +2064,6 @@
}
}
-
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2052,7 +2101,7 @@
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();
@@ -2176,7 +2225,7 @@
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) {
+ if (phoneId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
}
@@ -2212,29 +2261,13 @@
}
}
- private void broadcastDataConnectionStateChanged(int state, boolean isDataAllowed, String apn,
- String apnType, LinkProperties linkProperties,
- NetworkCapabilities networkCapabilities,
- boolean roaming, int subId) {
+ 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(TelephonyManager.EXTRA_STATE, dataStateToString(state));
- 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(PhoneConstants.DATA_APN_KEY, apn);
intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
@@ -2242,13 +2275,6 @@
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(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
private void enforceNotifyPermissionOrCarrierPrivilege(String method) {
if (checkNotifyPermission()) {
return;
@@ -2273,8 +2299,8 @@
== PackageManager.PERMISSION_GRANTED;
}
- private boolean checkListenerPermission(
- int events, int subId, String callingPackage, String message) {
+ private boolean checkListenerPermission(int events, int subId, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
.setCallingPackage(callingPackage)
@@ -2309,7 +2335,7 @@
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, subId, callingPackage, message)) {
+ mContext, subId, callingPackage, callingFeatureId, message)) {
return false;
}
}
@@ -2636,8 +2662,14 @@
return "TD_SCDMA";
case TelephonyManager.NETWORK_TYPE_IWLAN:
return "IWLAN";
- case TelephonyManager.NETWORK_TYPE_LTE_CA:
- return "LTE_CA";
+
+ //TODO: 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. Since this method is only used for logging, in the event that this
+ // network type is selected, the log will read as "Unknown."
+ //case TelephonyManager.NETWORK_TYPE_LTE_CA:
+ // return "LTE_CA";
+
case TelephonyManager.NETWORK_TYPE_NR:
return "NR";
default:
@@ -2645,8 +2677,31 @@
}
}
+ /** 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);
}
+
+ private int getPhoneIdFromSubId(int subId) {
+ SubscriptionManager subManager = (SubscriptionManager)
+ mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+
+ if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ subId = SubscriptionManager.getDefaultSubscriptionId();
+ }
+
+ SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+ if (info == null) return INVALID_SIM_SLOT_INDEX;
+ return info.getSimSlotIndex();
+ }
}
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/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 35774ed..2af04ae 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5280,7 +5280,7 @@
storageManager.commitChanges();
} catch (Exception e) {
PowerManager pm = (PowerManager)
- mInjector.getContext().getSystemService(Context.POWER_SERVICE);
+ mContext.getSystemService(Context.POWER_SERVICE);
pm.reboot("Checkpoint commit failed");
}
@@ -12799,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);
@@ -13525,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 b406ce6..972b106 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2899,33 +2899,37 @@
}
ArraySet<Long> enabled = new ArraySet<>();
ArraySet<Long> disabled = new ArraySet<>();
- switch (toggleValue) {
- case "enable":
- enabled.add(changeId);
- pw.println("Enabled change " + changeId + " for " + packageName + ".");
- CompatibilityChangeConfig overrides =
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
- return 0;
- case "disable":
- disabled.add(changeId);
- pw.println("Disabled change " + changeId + " for " + packageName + ".");
- overrides =
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
- return 0;
- case "reset":
- if (platformCompat.clearOverride(changeId, packageName)) {
- pw.println("Reset change " + changeId + " for " + packageName
- + " to default value.");
- } else {
- pw.println("No override exists for changeId " + changeId + ".");
- }
- return 0;
- default:
- pw.println("Invalid toggle value: '" + toggleValue + "'.");
+ try {
+ switch (toggleValue) {
+ case "enable":
+ enabled.add(changeId);
+ CompatibilityChangeConfig overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
+ pw.println("Enabled change " + changeId + " for " + packageName + ".");
+ return 0;
+ case "disable":
+ disabled.add(changeId);
+ overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
+ pw.println("Disabled change " + changeId + " for " + packageName + ".");
+ return 0;
+ case "reset":
+ if (platformCompat.clearOverride(changeId, packageName)) {
+ pw.println("Reset change " + changeId + " for " + packageName
+ + " to default value.");
+ } else {
+ pw.println("No override exists for changeId " + changeId + ".");
+ }
+ return 0;
+ default:
+ pw.println("Invalid toggle value: '" + toggleValue + "'.");
+ }
+ } catch (SecurityException e) {
+ pw.println(e.getMessage());
}
return -1;
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3b8d39b..766fa3b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -246,20 +246,27 @@
"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_PROCKILL = 5; // Note: this is an unsolicated command
+ 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;
@@ -1308,6 +1315,11 @@
}
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) {
return false;
}
@@ -1351,7 +1363,7 @@
final int procCount = procs.size();
for (int i = 0; i < procCount; i++) {
final int procUid = procs.keyAt(i);
- if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
+ if (!UserHandle.isCore(procUid) || !UserHandle.isSameUser(procUid, uid)) {
// Don't use an app process or different user process for system component.
continue;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 135f199d..4a5a212 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -195,15 +195,17 @@
} else {
makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
}
+ } 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
+ a2dpVolume * 10,
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
+ }
+ makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
+ "onSetA2dpSinkConnectionState", a2dpCodec);
}
- if (a2dpVolume != -1) {
- mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
- // convert index to internal representation in VolumeStreamState
- a2dpVolume * 10,
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
- }
- makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
- "onSetA2dpSinkConnectionState", a2dpCodec);
}
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index cf83dd6..f15d999 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -17,8 +17,10 @@
package com.android.server.compat;
import android.compat.Compatibility.ChangeConfig;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Environment;
+import android.os.RemoteException;
import android.text.TextUtils;
import android.util.LongArray;
import android.util.LongSparseArray;
@@ -26,8 +28,11 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.AndroidBuildClassifier;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
import com.android.server.compat.config.Change;
import com.android.server.compat.config.XmlParser;
@@ -54,22 +59,14 @@
private static final String TAG = "CompatConfig";
- private static final CompatConfig sInstance = new CompatConfig().initConfigFromLib(
- Environment.buildPath(
- Environment.getRootDirectory(), "etc", "compatconfig"));
-
@GuardedBy("mChanges")
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
- @VisibleForTesting
- CompatConfig() {
- }
+ private IOverrideValidator mOverrideValidator;
- /**
- * @return The static instance of this class to be used within the system server.
- */
- static CompatConfig get() {
- return sInstance;
+ @VisibleForTesting
+ CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
+ mOverrideValidator = new OverrideValidatorImpl(androidBuildClassifier, context, this);
}
/**
@@ -159,8 +156,12 @@
* @param enabled If the change should be enabled or disabled.
* @return {@code true} if the change existed before adding the override.
*/
- boolean addOverride(long changeId, String packageName, boolean enabled) {
+ boolean addOverride(long changeId, String packageName, boolean enabled)
+ throws RemoteException, SecurityException {
boolean alreadyKnown = true;
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(changeId, packageName);
+ allowedState.enforce(changeId, packageName);
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c == null) {
@@ -186,6 +187,20 @@
}
/**
+ * Returns the minimum sdk version for which this change should be enabled (or 0 if it is not
+ * target sdk gated).
+ */
+ int minTargetSdkForChangeId(long changeId) {
+ synchronized (mChanges) {
+ CompatChange c = mChanges.get(changeId);
+ if (c == null) {
+ return 0;
+ }
+ return c.getEnableAfterTargetSdk();
+ }
+ }
+
+ /**
* Removes an override previously added via {@link #addOverride(long, String, boolean)}. This
* restores the default behaviour for the given change and app, once any app processes have been
* restarted.
@@ -194,34 +209,44 @@
* @param packageName The app package name that was overridden.
* @return {@code true} if an override existed;
*/
- boolean removeOverride(long changeId, String packageName) {
+ boolean removeOverride(long changeId, String packageName)
+ throws RemoteException, SecurityException {
boolean overrideExists = false;
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
- if (c != null) {
- overrideExists = true;
- c.removePackageOverride(packageName);
+ try {
+ if (c != null) {
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(changeId, packageName);
+ allowedState.enforce(changeId, packageName);
+ overrideExists = true;
+ c.removePackageOverride(packageName);
+ }
+ } catch (RemoteException e) {
+ // Should never occur, since validator is in the same process.
+ throw new RuntimeException("Unable to call override validator!", e);
}
}
return overrideExists;
}
/**
- * Overrides the enabled state for a given change and app. This method is intended to be used
- * *only* for debugging purposes.
+ * Overrides the enabled state for a given change and app.
*
* <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
*
* @param overrides list of overrides to default changes config.
* @param packageName app for which the overrides will be applied.
*/
- void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
+ void addOverrides(CompatibilityChangeConfig overrides, String packageName)
+ throws RemoteException, SecurityException {
synchronized (mChanges) {
for (Long changeId : overrides.enabledChanges()) {
addOverride(changeId, packageName, true);
}
for (Long changeId : overrides.disabledChanges()) {
addOverride(changeId, packageName, false);
+
}
}
}
@@ -235,10 +260,22 @@
*
* @param packageName The package for which the overrides should be purged.
*/
- void removePackageOverrides(String packageName) {
+ void removePackageOverrides(String packageName) throws RemoteException, SecurityException {
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
- mChanges.valueAt(i).removePackageOverride(packageName);
+ try {
+ CompatChange change = mChanges.valueAt(i);
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(change.getId(),
+ packageName);
+ allowedState.enforce(change.getId(), packageName);
+ if (change != null) {
+ mChanges.valueAt(i).removePackageOverride(packageName);
+ }
+ } catch (RemoteException e) {
+ // Should never occur, since validator is in the same process.
+ throw new RuntimeException("Unable to call override validator!", e);
+ }
}
}
}
@@ -326,17 +363,23 @@
}
}
- CompatConfig initConfigFromLib(File libraryDir) {
+ static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) {
+ CompatConfig config = new CompatConfig(androidBuildClassifier, context);
+ config.initConfigFromLib(Environment.buildPath(
+ Environment.getRootDirectory(), "etc", "compatconfig"));
+ return config;
+ }
+
+ void initConfigFromLib(File libraryDir) {
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Slog.e(TAG, "No directory " + libraryDir + ", skipping");
- return this;
+ return;
}
for (File f : libraryDir.listFiles()) {
Slog.d(TAG, "Found a config file: " + f.getPath());
//TODO(b/138222363): Handle duplicate ids across config files.
readConfig(f);
}
- return this;
}
private void readConfig(File configFile) {
@@ -350,4 +393,7 @@
}
}
+ IOverrideValidator getOverrideValidator() {
+ return mOverrideValidator;
+ }
}
diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
new file mode 100644
index 0000000..dfc0080
--- /dev/null
+++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
@@ -0,0 +1,94 @@
+/*
+ * 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.compat;
+
+import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH;
+import static com.android.internal.compat.OverrideAllowedState.PACKAGE_DOES_NOT_EXIST;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.AndroidBuildClassifier;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
+
+/**
+ * Implementation of the policy for allowing compat change overrides.
+ */
+public class OverrideValidatorImpl extends IOverrideValidator.Stub {
+
+ private AndroidBuildClassifier mAndroidBuildClassifier;
+ private Context mContext;
+ private CompatConfig mCompatConfig;
+
+ @VisibleForTesting
+ OverrideValidatorImpl(AndroidBuildClassifier androidBuildClassifier,
+ Context context, CompatConfig config) {
+ mAndroidBuildClassifier = androidBuildClassifier;
+ mContext = context;
+ mCompatConfig = config;
+ }
+
+ @Override
+ public OverrideAllowedState getOverrideAllowedState(long changeId, String packageName) {
+ boolean debuggableBuild = false;
+ boolean finalBuild = false;
+
+ debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild();
+ finalBuild = mAndroidBuildClassifier.isFinalBuild();
+
+ // Allow any override for userdebug or eng builds.
+ if (debuggableBuild) {
+ return new OverrideAllowedState(ALLOWED, -1, -1);
+ }
+ PackageManager packageManager = mContext.getPackageManager();
+ if (packageManager == null) {
+ throw new IllegalStateException("No PackageManager!");
+ }
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = packageManager.getApplicationInfo(packageName, 0);
+ } catch (NameNotFoundException e) {
+ return new OverrideAllowedState(PACKAGE_DOES_NOT_EXIST, -1, -1);
+ }
+ int appTargetSdk = applicationInfo.targetSdkVersion;
+ // Only allow overriding debuggable apps.
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+ return new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1);
+ }
+ int minTargetSdk = mCompatConfig.minTargetSdkForChangeId(changeId);
+ // Do not allow overriding non-target sdk gated changes on user builds
+ if (minTargetSdk == -1) {
+ return new OverrideAllowedState(DISABLED_NON_TARGET_SDK, appTargetSdk, minTargetSdk);
+ }
+ // Allow overriding any change for debuggable apps on non-final builds.
+ if (!finalBuild) {
+ return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+ }
+ // Only allow to opt-in for a targetSdk gated change.
+ if (applicationInfo.targetSdkVersion < minTargetSdk) {
+ return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+ }
+ return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, minTargetSdk);
+ }
+}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 4a3d7d6..029b7bc 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -27,9 +27,12 @@
import android.util.Slog;
import android.util.StatsLog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.AndroidBuildClassifier;
import com.android.internal.compat.ChangeReporter;
import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.compat.CompatibilityChangeInfo;
+import com.android.internal.compat.IOverrideValidator;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.util.DumpUtils;
@@ -45,11 +48,21 @@
private final Context mContext;
private final ChangeReporter mChangeReporter;
+ private final CompatConfig mCompatConfig;
public PlatformCompat(Context context) {
mContext = context;
mChangeReporter = new ChangeReporter(
StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER);
+ mCompatConfig = CompatConfig.create(new AndroidBuildClassifier(), mContext);
+ }
+
+ @VisibleForTesting
+ PlatformCompat(Context context, CompatConfig compatConfig) {
+ mContext = context;
+ mChangeReporter = new ChangeReporter(
+ StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER);
+ mCompatConfig = compatConfig;
}
@Override
@@ -74,7 +87,7 @@
@Override
public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
- if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) {
+ if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
reportChange(changeId, appInfo.uid,
StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
return true;
@@ -121,57 +134,59 @@
* otherwise.
*/
public boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
- return CompatConfig.get().registerListener(changeId, listener);
+ return mCompatConfig.registerListener(changeId, listener);
}
@Override
- public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
- CompatConfig.get().addOverrides(overrides, packageName);
+ public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
+ throws RemoteException, SecurityException {
+ mCompatConfig.addOverrides(overrides, packageName);
killPackage(packageName);
}
@Override
- public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
- CompatConfig.get().addOverrides(overrides, packageName);
+ public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
+ throws RemoteException, SecurityException {
+ mCompatConfig.addOverrides(overrides, packageName);
}
@Override
- public void clearOverrides(String packageName) {
- CompatConfig config = CompatConfig.get();
- config.removePackageOverrides(packageName);
+ public void clearOverrides(String packageName) throws RemoteException, SecurityException {
+ mCompatConfig.removePackageOverrides(packageName);
killPackage(packageName);
}
@Override
- public void clearOverridesForTest(String packageName) {
- CompatConfig config = CompatConfig.get();
- config.removePackageOverrides(packageName);
+ public void clearOverridesForTest(String packageName)
+ throws RemoteException, SecurityException {
+ mCompatConfig.removePackageOverrides(packageName);
}
@Override
- public boolean clearOverride(long changeId, String packageName) {
- boolean existed = CompatConfig.get().removeOverride(changeId, packageName);
+ public boolean clearOverride(long changeId, String packageName)
+ throws RemoteException, SecurityException {
+ boolean existed = mCompatConfig.removeOverride(changeId, packageName);
killPackage(packageName);
return existed;
}
@Override
public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
- return CompatConfig.get().getAppConfig(appInfo);
+ return mCompatConfig.getAppConfig(appInfo);
}
@Override
public CompatibilityChangeInfo[] listAllChanges() {
- return CompatConfig.get().dumpChanges();
+ return mCompatConfig.dumpChanges();
}
/**
* Check whether the change is known to the compat config.
- * @param changeId
+ *
* @return {@code true} if the change is known.
*/
public boolean isKnownChangeId(long changeId) {
- return CompatConfig.get().isKnownChangeId(changeId);
+ return mCompatConfig.isKnownChangeId(changeId);
}
@@ -181,11 +196,11 @@
*
* @param appInfo The app in question
* @return A sorted long array of change IDs. We use a primitive array to minimize memory
- * footprint: Every app process will store this array statically so we aim to reduce
- * overhead as much as possible.
+ * footprint: Every app process will store this array statically so we aim to reduce
+ * overhead as much as possible.
*/
public long[] getDisabledChanges(ApplicationInfo appInfo) {
- return CompatConfig.get().getDisabledChanges(appInfo);
+ return mCompatConfig.getDisabledChanges(appInfo);
}
/**
@@ -195,18 +210,24 @@
* @return The change ID, or {@code -1} if no change with that name exists.
*/
public long lookupChangeId(String name) {
- return CompatConfig.get().lookupChangeId(name);
+ return mCompatConfig.lookupChangeId(name);
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
- CompatConfig.get().dumpConfig(pw);
+ mCompatConfig.dumpConfig(pw);
+ }
+
+ @Override
+ public IOverrideValidator getOverrideValidator() {
+ return mCompatConfig.getOverrideValidator();
}
/**
* Clears information stored about events reported on behalf of an app.
* To be called once upon app start or end. A second call would be a no-op.
+ *
* @param appInfo the app to reset
*/
public void resetReporting(ApplicationInfo appInfo) {
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/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index fa8c48b..a89daff 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -86,7 +86,7 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
@@ -1987,9 +1987,7 @@
if (time == 0) {
return "N/A";
}
- Time tobj = new Time();
- tobj.set(time);
- return tobj.format("%Y-%m-%d %H:%M:%S");
+ return TimeMigrationUtils.formatMillisWithFixedFormat(time);
}
private final static Comparator<SyncOperation> sOpDumpComparator = (op1, op2) -> {
@@ -2555,9 +2553,7 @@
accountKey = "Unknown";
}
final long elapsedTime = item.elapsedTime;
- final Time time = new Time();
final long eventTime = item.eventTime;
- time.set(eventTime);
final String key = authorityName + "/" + accountKey;
final Long lastEventTime = lastTimeMap.get(key);
@@ -2622,9 +2618,7 @@
authorityName = "Unknown";
accountKey = "Unknown";
}
- final Time time = new Time();
final long eventTime = item.eventTime;
- time.set(eventTime);
pw.printf(" #%-3d: %s %8s ",
i + 1,
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/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index eb5d472..e655b35 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -29,7 +29,7 @@
import android.net.Uri;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
@@ -1643,17 +1643,13 @@
if (numFailures != 0) {
pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
}
- final Time t = new Time();
- final String format = "%Y-%m-%d %H:%M:%S";
if (mLastSuccessfulRunTime != 0) {
pw.print(prefix); pw.print("Last successful run: ");
- t.set(mLastSuccessfulRunTime);
- pw.println(t.format(format));
+ pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastSuccessfulRunTime));
}
if (mLastFailedRunTime != 0) {
pw.print(prefix); pw.print("Last failed run: ");
- t.set(mLastFailedRunTime);
- pw.println(t.format(format));
+ pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastFailedRunTime));
}
}
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/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 583d9f7..877c40f 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;
@@ -609,12 +608,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 +640,7 @@
}
public void bindConnectivityManager(IConnectivityManager connManager) {
- mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
+ mConnManager = Objects.requireNonNull(connManager, "missing IConnectivityManager");
}
@GuardedBy("mUidRulesFirstLock")
@@ -1027,6 +1026,7 @@
// READ_NETWORK_USAGE_HISTORY permission above.
synchronized (mNetworkPoliciesSecondLock) {
+ updateNetworkRulesNL();
updateNetworkEnabledNL();
updateNotificationsNL();
}
@@ -3258,7 +3258,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/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
index 9c1ac34..947405e 100644
--- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
+++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@@ -56,16 +56,17 @@
// for any device / profile owner checks. The majority of requests for the serial number
// should use the getSerialForPackage method with the calling package specified.
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
- /* callingPackage */ null, "getSerial")) {
+ /* callingPackage */ null, null, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
@Override
- public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
+ public @Nullable String getSerialForPackage(String callingPackage,
+ String callingFeatureId) throws RemoteException {
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
- callingPackage, "getSerial")) {
+ callingPackage, callingFeatureId, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
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/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 2d8a2ac..ebba128 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -79,7 +79,7 @@
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.KeyValueListParser;
@@ -3981,9 +3981,7 @@
}
static String formatTime(long time) {
- Time tobj = new Time();
- tobj.set(time);
- return tobj.format("%Y-%m-%d %H:%M:%S");
+ return TimeMigrationUtils.formatMillisWithFixedFormat(time);
}
private void dumpCurrentTime(PrintWriter pw) {
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/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/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 172367a..b7d6360 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.app.timedetector.ITimeDetectorService;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.ContentResolver;
import android.content.Context;
@@ -105,6 +106,14 @@
mHandler.post(() -> mTimeDetectorStrategy.suggestManualTime(timeSignal));
}
+ @Override
+ public void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal) {
+ enforceSuggestNetworkTimePermission();
+ Objects.requireNonNull(timeSignal);
+
+ mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
+ }
+
@VisibleForTesting
public void handleAutoTimeDetectionToggle() {
mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged);
@@ -119,10 +128,20 @@
}
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");
+ }
+
+ private void enforceSuggestNetworkTimePermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SET_TIME,
+ "set time");
}
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index 0a6c2e7..b4f4eca 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.Intent;
import android.util.TimestampedValue;
@@ -86,6 +87,9 @@
/** Process the suggested manually entered time. */
void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);
+ /** Process the suggested time from network sources. */
+ void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
+
/** Handle the auto-time setting being toggled on or off. */
void handleAutoTimeDetectionChanged();
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 1b1ac6d..02656ea 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -21,23 +21,23 @@
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.Intent;
-import android.util.ArrayMap;
+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.telephony.TelephonyIntents;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.timezonedetector.ArrayMapWithHistory;
+import com.android.server.timezonedetector.ReferenceWithHistory;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.LinkedList;
-import java.util.Map;
/**
* An implementation of TimeDetectorStrategy that passes phone and manual suggestions to
@@ -58,11 +58,11 @@
/** 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. */
+ /** Phone and network suggestions older than this value are considered too old to be used. */
@VisibleForTesting
- static final long PHONE_MAX_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
+ static final long MAX_UTC_TIME_AGE_MILLIS = PHONE_BUCKET_COUNT * PHONE_BUCKET_SIZE_MILLIS;
- @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL })
+ @IntDef({ ORIGIN_PHONE, ORIGIN_MANUAL, ORIGIN_NETWORK })
@Retention(RetentionPolicy.SOURCE)
public @interface Origin {}
@@ -74,6 +74,10 @@
@Origin
private static final int ORIGIN_MANUAL = 2;
+ /** Used when a time value originated from a network signal. */
+ @Origin
+ private static final int ORIGIN_NETWORK = 3;
+
/**
* 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
@@ -99,14 +103,16 @@
private TimestampedValue<Long> mLastAutoSystemClockTimeSet;
/**
- * A mapping from phoneId to a linked list of time suggestions (the "first" 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_SUGGESTION_HISTORY_SIZE} in size.
+ * 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 ArrayMap<Integer, LinkedList<PhoneTimeSuggestion>> mSuggestionByPhoneId =
- new ArrayMap<>();
+ private final ArrayMapWithHistory<Integer, PhoneTimeSuggestion> mSuggestionByPhoneId =
+ new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+
+ @GuardedBy("this")
+ private final ReferenceWithHistory<NetworkTimeSuggestion> mLastNetworkSuggestion =
+ new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@Override
public void initialize(@NonNull Callback callback) {
@@ -126,6 +132,19 @@
}
@Override
+ public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion) {
+ if (!validateSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
+ return;
+ }
+ mLastNetworkSuggestion.set(timeSuggestion);
+
+ // Now perform auto time detection. The new suggestion may be used to modify the system
+ // clock.
+ String reason = "New network time suggested. timeSuggestion=" + timeSuggestion;
+ doAutoTimeDetection(reason);
+ }
+
+ @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,
@@ -171,6 +190,12 @@
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
@@ -179,16 +204,12 @@
ipw.println("Phone suggestion history:");
ipw.increaseIndent(); // level 2
- for (Map.Entry<Integer, LinkedList<PhoneTimeSuggestion>> entry
- : mSuggestionByPhoneId.entrySet()) {
- ipw.println("Phone " + entry.getKey());
+ mSuggestionByPhoneId.dump(ipw);
+ ipw.decreaseIndent(); // level 2
- ipw.increaseIndent(); // level 3
- for (PhoneTimeSuggestion suggestion : entry.getValue()) {
- ipw.println(suggestion);
- }
- ipw.decreaseIndent(); // level 3
- }
+ ipw.println("Network suggestion history:");
+ ipw.increaseIndent(); // level 2
+ mLastNetworkSuggestion.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.decreaseIndent(); // level 1
@@ -205,20 +226,10 @@
}
int phoneId = suggestion.getPhoneId();
- LinkedList<PhoneTimeSuggestion> phoneSuggestions = mSuggestionByPhoneId.get(phoneId);
- if (phoneSuggestions == null) {
- // The first time we've seen this phoneId.
- phoneSuggestions = new LinkedList<>();
- mSuggestionByPhoneId.put(phoneId, phoneSuggestions);
- } else if (phoneSuggestions.isEmpty()) {
- Slog.w(LOG_TAG, "Suggestions unexpectedly empty when adding suggestion=" + suggestion);
- }
-
- if (!phoneSuggestions.isEmpty()) {
+ PhoneTimeSuggestion previousSuggestion = mSuggestionByPhoneId.get(phoneId);
+ if (previousSuggestion != null) {
// We can log / discard suggestions with obvious issues with the reference time clock.
- PhoneTimeSuggestion previousSuggestion = phoneSuggestions.getFirst();
- if (previousSuggestion == null
- || previousSuggestion.getUtcTime() == null
+ 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."
@@ -240,10 +251,7 @@
}
// Store the latest suggestion.
- phoneSuggestions.addFirst(suggestion);
- if (phoneSuggestions.size() > KEEP_SUGGESTION_HISTORY_SIZE) {
- phoneSuggestions.removeLast();
- }
+ mSuggestionByPhoneId.put(phoneId, suggestion);
return true;
}
@@ -273,23 +281,34 @@
return;
}
+ // Android devices currently prioritize any telephony over network signals. There are
+ // carrier compliance tests that would need to be changed before we could ignore NITZ or
+ // prefer NTP generally. This check is cheap on devices without phone hardware.
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);
- }
+ if (bestPhoneSuggestion != null) {
+ final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
+ String cause = "Found good phone suggestion."
+ + ", bestPhoneSuggestion=" + bestPhoneSuggestion
+ + ", detectionReason=" + detectionReason;
+ setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
return;
}
- final TimestampedValue<Long> newUtcTime = bestPhoneSuggestion.getUtcTime();
- String cause = "Found good suggestion."
- + ", bestPhoneSuggestion=" + bestPhoneSuggestion
- + ", detectionReason=" + detectionReason;
- setSystemClockIfRequired(ORIGIN_PHONE, newUtcTime, cause);
+ // There is no good phone suggestion, try network.
+ NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
+ if (networkSuggestion != null) {
+ final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime();
+ String cause = "Found good network suggestion."
+ + ", networkSuggestion=" + networkSuggestion
+ + ", detectionReason=" + detectionReason;
+ setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause);
+ return;
+ }
+
+ if (DBG) {
+ Slog.d(LOG_TAG, "Could not determine time: No best phone or network suggestion."
+ + " detectionReason=" + detectionReason);
+ }
}
@GuardedBy("this")
@@ -331,15 +350,7 @@
int bestScore = PHONE_INVALID_SCORE;
for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
Integer phoneId = mSuggestionByPhoneId.keyAt(i);
- LinkedList<PhoneTimeSuggestion> phoneSuggestions = mSuggestionByPhoneId.valueAt(i);
- if (phoneSuggestions == null) {
- // Unexpected - map is missing a value.
- Slog.w(LOG_TAG, "Suggestions unexpectedly missing for phoneId."
- + " phoneId=" + phoneId);
- continue;
- }
-
- PhoneTimeSuggestion candidateSuggestion = phoneSuggestions.getFirst();
+ 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."
@@ -376,37 +387,50 @@
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.
+
+ // Validate first.
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. "
+ if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) {
+ Slog.w(LOG_TAG, "Existing suggestion found to be invalid "
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ ", timeSuggestion=" + timeSuggestion);
return PHONE_INVALID_SCORE;
}
- long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
+ // 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.
+ long ageMillis = elapsedRealtimeMillis - utcTime.getReferenceTimeMillis();
- // 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) {
+ // Turn the age into a discrete value: 0 <= bucketIndex < PHONE_BUCKET_COUNT.
+ int bucketIndex = (int) (ageMillis / PHONE_BUCKET_SIZE_MILLIS);
+ if (bucketIndex >= PHONE_BUCKET_COUNT) {
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;
}
+ /** Returns the latest, valid, network suggestion. Returns {@code null} if there isn't one. */
+ @GuardedBy("this")
+ @Nullable
+ private NetworkTimeSuggestion findLatestValidNetworkSuggestion() {
+ NetworkTimeSuggestion networkSuggestion = mLastNetworkSuggestion.get();
+ if (networkSuggestion == null) {
+ // No network suggestions received. This is normal if there's no connectivity.
+ return null;
+ }
+
+ TimestampedValue<Long> utcTime = networkSuggestion.getUtcTime();
+ long elapsedRealTimeMillis = mCallback.elapsedRealtimeMillis();
+ if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+ // The latest suggestion is not valid, usually due to its age.
+ return null;
+ }
+
+ return networkSuggestion;
+ }
+
@GuardedBy("this")
private void setSystemClockIfRequired(
@Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
@@ -443,7 +467,7 @@
}
private static boolean isOriginAutomatic(@Origin int origin) {
- return origin == ORIGIN_PHONE;
+ return origin != ORIGIN_MANUAL;
}
@GuardedBy("this")
@@ -512,12 +536,12 @@
mLastAutoSystemClockTimeSet = null;
}
- // Historically, Android has sent a TelephonyIntents.ACTION_NETWORK_SET_TIME broadcast only
+ // 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(TelephonyIntents.ACTION_NETWORK_SET_TIME);
+ Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_SET_TIME);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra("time", newSystemClockMillis);
mCallback.sendStickyBroadcast(intent);
@@ -535,15 +559,49 @@
}
/**
+ * Returns the latest valid network suggestion. Not intended for general use: it is used during
+ * tests to check strategy behavior.
+ */
+ @VisibleForTesting
+ @Nullable
+ public NetworkTimeSuggestion findLatestValidNetworkSuggestionForTests() {
+ return findLatestValidNetworkSuggestion();
+ }
+
+ /**
* A method used to inspect state during tests. Not intended for general use.
*/
@VisibleForTesting
@Nullable
public synchronized PhoneTimeSuggestion getLatestPhoneSuggestion(int phoneId) {
- LinkedList<PhoneTimeSuggestion> suggestions = mSuggestionByPhoneId.get(phoneId);
- if (suggestions == null) {
- return null;
+ return mSuggestionByPhoneId.get(phoneId);
+ }
+
+ /**
+ * A method used to inspect state during tests. Not intended for general use.
+ */
+ @VisibleForTesting
+ @Nullable
+ public NetworkTimeSuggestion getLatestNetworkSuggestion() {
+ return mLastNetworkSuggestion.get();
+ }
+
+ private static boolean validateSuggestionUtcTime(
+ long elapsedRealtimeMillis, TimestampedValue<Long> utcTime) {
+ long referenceTimeMillis = utcTime.getReferenceTimeMillis();
+ if (referenceTimeMillis > elapsedRealtimeMillis) {
+ // Future reference times are ignored. They imply the reference time was wrong, or the
+ // elapsed realtime clock used to derive it has gone backwards, neither of which are
+ // supportable situations.
+ return false;
}
- return suggestions.getFirst();
+
+ // 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.
+ long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
+ return ageMillis <= MAX_UTC_TIME_AGE_MILLIS;
}
}
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/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index b4d8053..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;
/**
@@ -175,14 +172,13 @@
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.
@@ -385,7 +372,7 @@
}
private static boolean isOriginAutomatic(@Origin int origin) {
- return origin == ORIGIN_PHONE;
+ return origin != ORIGIN_MANUAL;
}
@GuardedBy("this")
@@ -398,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;
@@ -456,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);
@@ -472,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();
}
/**
@@ -494,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
index 18ed51a..5b58199 100755
--- 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) {
diff --git a/services/core/java/com/android/server/wallpaper/GLHelper.java b/services/core/java/com/android/server/wallpaper/GLHelper.java
new file mode 100644
index 0000000..1d733f5
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/GLHelper.java
@@ -0,0 +1,148 @@
+/*
+ * 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.wallpaper;
+
+import static android.opengl.EGL14.EGL_ALPHA_SIZE;
+import static android.opengl.EGL14.EGL_BLUE_SIZE;
+import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
+import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
+import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
+import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_GREEN_SIZE;
+import static android.opengl.EGL14.EGL_HEIGHT;
+import static android.opengl.EGL14.EGL_NONE;
+import static android.opengl.EGL14.EGL_NO_CONTEXT;
+import static android.opengl.EGL14.EGL_NO_DISPLAY;
+import static android.opengl.EGL14.EGL_NO_SURFACE;
+import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
+import static android.opengl.EGL14.EGL_RED_SIZE;
+import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
+import static android.opengl.EGL14.EGL_STENCIL_SIZE;
+import static android.opengl.EGL14.EGL_WIDTH;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreatePbufferSurface;
+import static android.opengl.EGL14.eglDestroyContext;
+import static android.opengl.EGL14.eglDestroySurface;
+import static android.opengl.EGL14.eglGetDisplay;
+import static android.opengl.EGL14.eglGetError;
+import static android.opengl.EGL14.eglInitialize;
+import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.EGL14.eglTerminate;
+import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE;
+import static android.opengl.GLES20.glGetIntegerv;
+
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLUtils;
+import android.os.SystemProperties;
+import android.util.Log;
+
+class GLHelper {
+ private static final String TAG = GLHelper.class.getSimpleName();
+ private static final int sMaxTextureSize;
+
+ static {
+ int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0);
+ sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL();
+ }
+
+ private static int retrieveTextureSizeFromGL() {
+ try {
+ String err;
+
+ // Before we can retrieve info from GL,
+ // we have to create EGLContext, EGLConfig and EGLDisplay first.
+ // We will fail at querying info from GL once one of above failed.
+ // When this happens, we will use defValue instead.
+ EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) {
+ err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) {
+ err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ EGLConfig eglConfig = null;
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = new int[] {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+
+ if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */,
+ configs, 0 /* configOffset */, 1 /* config_size */,
+ configsCount, 0 /* num_configOffset */)) {
+ err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ } else if (configsCount[0] > 0) {
+ eglConfig = configs[0];
+ }
+
+ if (eglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized!");
+ }
+
+ int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext eglContext = eglCreateContext(
+ eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */);
+
+ if (eglContext == null || eglContext == EGL_NO_CONTEXT) {
+ err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ // We create a push buffer temporarily for querying info from GL.
+ int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+ EGLSurface eglSurface =
+ eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */);
+ eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+ // Now, we are ready to query the info from GL.
+ int[] maxSize = new int[1];
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */);
+
+ // We have got the info we want, release all egl resources.
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+ eglTerminate(eglDisplay);
+ return maxSize[0];
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Retrieve from GL failed", e);
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ static int getMaxTextureSize() {
+ return sMaxTextureSize;
+ }
+}
+
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b0f1e5d..991c09a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -134,6 +134,9 @@
private static final boolean DEBUG = false;
private static final boolean DEBUG_LIVE = true;
+ // This 100MB limitation is defined in RecordingCanvas.
+ private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024;
+
public static class Lifecycle extends SystemService {
private IWallpaperManagerService mService;
@@ -572,7 +575,9 @@
// Only generate crop for default display.
final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
- Rect cropHint = new Rect(wallpaper.cropHint);
+ final Rect cropHint = new Rect(wallpaper.cropHint);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
if (DEBUG) {
Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
@@ -618,12 +623,12 @@
}
// scale if the crop height winds up not matching the recommended metrics
- needScale = (wpData.mHeight != cropHint.height());
+ needScale = wpData.mHeight != cropHint.height()
+ || cropHint.height() > GLHelper.getMaxTextureSize()
+ || cropHint.width() > GLHelper.getMaxTextureSize();
//make sure screen aspect ratio is preserved if width is scaled under screen size
if (needScale) {
- final DisplayInfo displayInfo = new DisplayInfo();
- mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
final int newWidth = (int) (cropHint.width() * scaleByHeight);
if (newWidth < displayInfo.logicalWidth) {
@@ -644,14 +649,29 @@
if (!needCrop && !needScale) {
// Simple case: the nominal crop fits what we want, so we take
// the whole thing and just copy the image file directly.
- if (DEBUG) {
- Slog.v(TAG, "Null crop of new wallpaper; copying");
+
+ // TODO: It is not accurate to estimate bitmap size without decoding it,
+ // may be we can try to remove this optimized way in the future,
+ // that means, we will always go into the 'else' block.
+
+ // This is just a quick estimation, may be smaller than it is.
+ long estimateSize = options.outWidth * options.outHeight * 4;
+
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (estimateSize < MAX_BITMAP_SIZE) {
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
}
- success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+
if (!success) {
wallpaper.cropFile.delete();
// TODO: fall back to default wallpaper in this case
}
+
+ if (DEBUG) {
+ Slog.v(TAG, "Null crop of new wallpaper, estimate size="
+ + estimateSize + ", success=" + success);
+ }
} else {
// Fancy case: crop and scale. First, we decode and scale down if appropriate.
FileOutputStream f = null;
@@ -665,49 +685,78 @@
// We calculate the largest power-of-two under the actual ratio rather than
// just let the decode take care of it because we also want to remap where the
// cropHint rectangle lies in the decoded [super]rect.
- final BitmapFactory.Options scaler;
final int actualScale = cropHint.height() / wpData.mHeight;
int scale = 1;
- while (2*scale < actualScale) {
+ while (2 * scale <= actualScale) {
scale *= 2;
}
- if (scale > 1) {
- scaler = new BitmapFactory.Options();
- scaler.inSampleSize = scale;
+ options.inSampleSize = scale;
+ options.inJustDecodeBounds = false;
+
+ final Rect estimateCrop = new Rect(cropHint);
+ estimateCrop.scale(1f / options.inSampleSize);
+ final float hRatio = (float) wpData.mHeight / estimateCrop.height();
+ final int destHeight = (int) (estimateCrop.height() * hRatio);
+ final int destWidth = (int) (estimateCrop.width() * hRatio);
+
+ // We estimated an invalid crop, try to adjust the cropHint to get a valid one.
+ if (destWidth > GLHelper.getMaxTextureSize()) {
+ int newHeight = (int) (wpData.mHeight / hRatio);
+ int newWidth = (int) (wpData.mWidth / hRatio);
+
if (DEBUG) {
- Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
+ Slog.v(TAG, "Invalid crop dimensions, trying to adjust.");
}
- } else {
- scaler = null;
+
+ estimateCrop.set(cropHint);
+ estimateCrop.left += (cropHint.width() - newWidth) / 2;
+ estimateCrop.top += (cropHint.height() - newHeight) / 2;
+ estimateCrop.right = estimateCrop.left + newWidth;
+ estimateCrop.bottom = estimateCrop.top + newHeight;
+ cropHint.set(estimateCrop);
+ estimateCrop.scale(1f / options.inSampleSize);
}
- Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
+
+ // We've got the safe cropHint; now we want to scale it properly to
+ // the desired rectangle.
+ // That's a height-biased operation: make it fit the hinted height.
+ final int safeHeight = (int) (estimateCrop.height() * hRatio);
+ final int safeWidth = (int) (estimateCrop.width() * hRatio);
+
+ if (DEBUG) {
+ Slog.v(TAG, "Decode parameters:");
+ Slog.v(TAG, " cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
+ Slog.v(TAG, " down sampling=" + options.inSampleSize
+ + ", hRatio=" + hRatio);
+ Slog.v(TAG, " dest=" + destWidth + "x" + destHeight);
+ Slog.v(TAG, " safe=" + safeWidth + "x" + safeHeight);
+ Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize());
+ }
+
+ Bitmap cropped = decoder.decodeRegion(cropHint, options);
decoder.recycle();
if (cropped == null) {
Slog.e(TAG, "Could not decode new wallpaper");
} else {
- // We've got the extracted crop; now we want to scale it properly to
- // the desired rectangle. That's a height-biased operation: make it
- // fit the hinted height, and accept whatever width we end up with.
- cropHint.offsetTo(0, 0);
- cropHint.right /= scale; // adjust by downsampling factor
- cropHint.bottom /= scale;
- final float heightR =
- ((float) wpData.mHeight) / ((float) cropHint.height());
- if (DEBUG) {
- Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
- }
- final int destWidth = (int)(cropHint.width() * heightR);
+ // We are safe to create final crop with safe dimensions now.
final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
- destWidth, wpData.mHeight, true);
+ safeWidth, safeHeight, true);
if (DEBUG) {
Slog.v(TAG, "Final extract:");
Slog.v(TAG, " dims: w=" + wpData.mWidth
+ " h=" + wpData.mHeight);
- Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ " h=" + finalCrop.getHeight());
}
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (finalCrop.getByteCount() > MAX_BITMAP_SIZE) {
+ throw new RuntimeException(
+ "Too large bitmap, limit=" + MAX_BITMAP_SIZE);
+ }
+
f = new FileOutputStream(wallpaper.cropFile);
bos = new BufferedOutputStream(f, 32*1024);
finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
@@ -1981,6 +2030,11 @@
if (!isWallpaperSupported(callingPackage)) {
return;
}
+
+ // Make sure both width and height are not larger than max texture size.
+ width = Math.min(width, GLHelper.getMaxTextureSize());
+ height = Math.min(height, GLHelper.getMaxTextureSize());
+
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
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/Android.bp b/services/core/jni/Android.bp
index 2b1c07b..3b66c72 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -124,6 +124,7 @@
"android.hardware.thermal@1.0",
"android.hardware.tv.cec@1.0",
"android.hardware.tv.input@1.0",
+ "android.hardware.vibrator-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
@@ -133,7 +134,6 @@
"android.frameworks.sensorservice@1.0",
"android.system.suspend@1.0",
"suspend_control_aidl_interface-cpp",
- "vintf-vibrator-cpp",
],
static_libs: [
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/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 2528063..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,8 +41,8 @@
import android.database.sqlite.SQLiteGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.net.ConnectivityModuleConnector;
+import android.net.ITetheringConnector;
import android.net.NetworkStackClient;
-import android.net.TetheringManager;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -2212,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/net/Android.bp b/services/net/Android.bp
index 3babb0b..9c7cfc1 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -10,14 +10,12 @@
srcs: [
":net-module-utils-srcs",
":services.net-sources",
- ":tethering-manager",
],
static_libs: [
"dnsresolver_aidl_interface-V2-java",
"netd_aidl_interface-unstable-java",
"netlink-client",
"networkstack-client",
- "tethering-client",
],
}
@@ -25,8 +23,6 @@
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",
],
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/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/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f3c76b6..8871348 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -28,6 +28,7 @@
import android.app.admin.DevicePolicyManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.appwidget.PendingHostUpdate;
import android.content.BroadcastReceiver;
@@ -80,6 +81,7 @@
super.setUp();
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+ LocalServices.removeServiceForTest(AppWidgetManagerInternal.class);
mTestContext = new TestContext();
mPkgName = mTestContext.getOpPackageName();
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/compat/ApplicationInfoBuilder.java b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
new file mode 100644
index 0000000..d0767cc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/ApplicationInfoBuilder.java
@@ -0,0 +1,58 @@
+/*
+ * 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.compat;
+
+import android.content.pm.ApplicationInfo;
+
+class ApplicationInfoBuilder {
+ private boolean mIsDebuggable;
+ private int mTargetSdk;
+ private String mPackageName;
+
+ private ApplicationInfoBuilder() {
+ mTargetSdk = -1;
+ }
+
+ static ApplicationInfoBuilder create() {
+ return new ApplicationInfoBuilder();
+ }
+
+ ApplicationInfoBuilder withTargetSdk(int targetSdk) {
+ mTargetSdk = targetSdk;
+ return this;
+ }
+
+ ApplicationInfoBuilder debuggable() {
+ mIsDebuggable = true;
+ return this;
+ }
+
+ ApplicationInfoBuilder withPackageName(String packageName) {
+ mPackageName = packageName;
+ return this;
+ }
+
+ ApplicationInfo build() {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ if (mIsDebuggable) {
+ applicationInfo.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
+ }
+ applicationInfo.packageName = mPackageName;
+ applicationInfo.targetSdkVersion = mTargetSdk;
+ return applicationInfo;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
new file mode 100644
index 0000000..328c71d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
@@ -0,0 +1,99 @@
+/*
+ * 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.compat;
+
+import android.content.Context;
+
+import com.android.internal.compat.AndroidBuildClassifier;
+
+import java.util.ArrayList;
+
+/**
+ * Helper class for creating a CompatConfig.
+ */
+class CompatConfigBuilder {
+ private ArrayList<CompatChange> mChanges;
+ private AndroidBuildClassifier mBuildClassifier;
+ private Context mContext;
+
+ private CompatConfigBuilder(AndroidBuildClassifier buildClassifier, Context context) {
+ mChanges = new ArrayList<>();
+ mBuildClassifier = buildClassifier;
+ mContext = context;
+ }
+
+ static CompatConfigBuilder create(AndroidBuildClassifier buildClassifier, Context context) {
+ return new CompatConfigBuilder(buildClassifier, context);
+ }
+
+ CompatConfigBuilder addTargetSdkChangeWithId(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", sdk, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addTargetSdkDisabledChangeWithId(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", sdk, true, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addTargetSdkChangeWithIdAndName(int sdk, long id, String name) {
+ mChanges.add(new CompatChange(id, name, sdk, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addTargetSdkChangeWithIdAndDescription(int sdk, long id,
+ String description) {
+ mChanges.add(new CompatChange(id, "", sdk, false, description));
+ return this;
+ }
+
+ CompatConfigBuilder addEnabledChangeWithId(long id) {
+ mChanges.add(new CompatChange(id, "", -1, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addEnabledChangeWithIdAndName(long id, String name) {
+ mChanges.add(new CompatChange(id, name, -1, false, ""));
+ return this;
+ }
+ CompatConfigBuilder addEnabledChangeWithIdAndDescription(long id, String description) {
+ mChanges.add(new CompatChange(id, "", -1, false, description));
+ return this;
+ }
+
+ CompatConfigBuilder addDisabledChangeWithId(long id) {
+ mChanges.add(new CompatChange(id, "", -1, true, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addDisabledChangeWithIdAndName(long id, String name) {
+ mChanges.add(new CompatChange(id, name, -1, true, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addDisabledChangeWithIdAndDescription(long id, String description) {
+ mChanges.add(new CompatChange(id, "", -1, true, description));
+ return this;
+ }
+
+ CompatConfig build() {
+ CompatConfig config = new CompatConfig(mBuildClassifier, mContext);
+ for (CompatChange change : mChanges) {
+ config.addChange(change);
+ }
+ return config;
+ }
+}
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..407f67e 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -18,30 +18,41 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import androidx.test.runner.AndroidJUnit4;
-import com.android.compat.annotation.Change;
-import com.android.compat.annotation.XmlWriter;
+import com.android.internal.compat.AndroidBuildClassifier;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.UUID;
@RunWith(AndroidJUnit4.class)
public class CompatConfigTest {
- private ApplicationInfo makeAppInfo(String pName, int targetSdkVersion) {
- ApplicationInfo ai = new ApplicationInfo();
- ai.packageName = pName;
- ai.targetSdkVersion = targetSdkVersion;
- return ai;
- }
+ @Mock
+ private Context mContext;
+ @Mock
+ PackageManager mPackageManager;
+ @Mock
+ private AndroidBuildClassifier mBuildClassifier;
private File createTempDir() {
String base = System.getProperty("java.io.tmpdir");
@@ -50,167 +61,260 @@
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();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ // Assume userdebug/eng non-final build
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(false);
}
@Test
- public void testUnknownChangeEnabled() {
- CompatConfig pc = new CompatConfig();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isTrue();
+ public void testUnknownChangeEnabled() throws Exception {
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create().build()))
+ .isTrue();
}
@Test
- public void testDisabledChangeDisabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true, ""));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
+ public void testDisabledChangeDisabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create().build()))
+ .isFalse();
}
@Test
- public void testTargetSdkChangeDisabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, false, null));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isFalse();
+ public void testTargetSdkChangeDisabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addTargetSdkChangeWithId(2, 1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(2).build()))
+ .isFalse();
}
@Test
- public void testTargetSdkChangeEnabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, false, ""));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
+ public void testTargetSdkChangeEnabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addTargetSdkChangeWithId(2, 1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue();
}
@Test
- public void testDisabledOverrideTargetSdkChange() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, true, null));
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isFalse();
+ public void testDisabledOverrideTargetSdkChange() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addTargetSdkDisabledChangeWithId(2, 1234L)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isFalse();
}
@Test
- public void testGetDisabledChanges() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true, null));
- pc.addChange(new CompatChange(2345L, "OTHER_CHANGE", -1, false, null));
- assertThat(pc.getDisabledChanges(
- makeAppInfo("com.some.package", 2))).asList().containsExactly(1234L);
+ public void testGetDisabledChanges() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .addEnabledChangeWithId(2345L)
+ .build();
+
+ assertThat(compatConfig.getDisabledChanges(
+ ApplicationInfoBuilder.create().build())).asList().containsExactly(1234L);
}
@Test
- public void testGetDisabledChangesSorted() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, true, null));
- pc.addChange(new CompatChange(123L, "OTHER_CHANGE", 2, true, null));
- pc.addChange(new CompatChange(12L, "THIRD_CHANGE", 2, true, null));
- assertThat(pc.getDisabledChanges(
- makeAppInfo("com.some.package", 2))).asList().containsExactly(12L, 123L, 1234L);
+ public void testGetDisabledChangesSorted() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .addDisabledChangeWithId(123L)
+ .addDisabledChangeWithId(12L)
+ .build();
+
+ assertThat(compatConfig.getDisabledChanges(ApplicationInfoBuilder.create().build()))
+ .asList().containsExactly(12L, 123L, 1234L);
}
@Test
- public void testPackageOverrideEnabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true, null)); // disabled
- pc.addOverride(1234L, "com.some.package", true);
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isTrue();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.other.package", 2))).isFalse();
+ public void testPackageOverrideEnabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+
+ compatConfig.addOverride(1234L, "com.some.package", true);
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package").build())).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.other.package").build())).isFalse();
}
@Test
- public void testPackageOverrideDisabled() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false, null));
- pc.addOverride(1234L, "com.some.package", false);
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.other.package", 2))).isTrue();
+ public void testPackageOverrideDisabled() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1234L)
+ .build();
+
+ compatConfig.addOverride(1234L, "com.some.package", false);
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package").build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.other.package").build())).isTrue();
}
@Test
- public void testPackageOverrideUnknownPackage() {
- CompatConfig pc = new CompatConfig();
- pc.addOverride(1234L, "com.some.package", false);
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.other.package", 2))).isTrue();
+ public void testPackageOverrideUnknownPackage() throws Exception {
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+
+ compatConfig.addOverride(1234L, "com.some.package", false);
+
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package").build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create()
+ .withPackageName("com.other.package").build())).isTrue();
}
@Test
- public void testPackageOverrideUnknownChange() {
- CompatConfig pc = new CompatConfig();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isTrue();
+ public void testPreventAddOverride() throws Exception {
+ final long changeId = 1234L;
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+ PackageManager packageManager = mock(PackageManager.class);
+ when(mContext.getPackageManager()).thenReturn(packageManager);
+ when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
+ .thenReturn(applicationInfo);
+
+ // Force the validator to prevent overriding the change by using a user build.
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(true);
+
+ assertThrows(SecurityException.class,
+ () -> compatConfig.addOverride(1234L, "com.some.package", true)
+ );
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
}
@Test
- public void testRemovePackageOverride() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false, null));
- pc.addOverride(1234L, "com.some.package", false);
- pc.removeOverride(1234L, "com.some.package");
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 2))).isTrue();
+ public void testPreventRemoveOverride() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(1234L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+ when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
+ .thenReturn(applicationInfo);
+ // Assume the override was allowed to be added.
+ compatConfig.addOverride(1234L, "com.some.package", true);
+
+ // Validator allows turning on the change.
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
+
+ // Reject all override attempts.
+ // Force the validator to prevent overriding the change by using a user build.
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(true);
+ // Try to turn off change, but validator prevents it.
+ assertThrows(SecurityException.class,
+ () -> compatConfig.removeOverride(1234L, "com.some.package"));
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
}
@Test
- public void testLookupChangeId() {
- CompatConfig pc = new CompatConfig();
- pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false, null));
- pc.addChange(new CompatChange(2345L, "ANOTHER_CHANGE", -1, false, null));
- assertThat(pc.lookupChangeId("MY_CHANGE")).isEqualTo(1234L);
+ public void testRemovePackageOverride() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1234L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+
+ assertThat(compatConfig.addOverride(1234L, "com.some.package", false)).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
+
+ compatConfig.removeOverride(1234L, "com.some.package");
+ assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
}
@Test
- public void testLookupChangeIdNotPresent() {
- CompatConfig pc = new CompatConfig();
- assertThat(pc.lookupChangeId("MY_CHANGE")).isEqualTo(-1L);
+ public void testLookupChangeId() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithIdAndName(1234L, "MY_CHANGE")
+ .addEnabledChangeWithIdAndName(2345L, "MY_OTHER_CHANGE")
+ .build();
+
+ assertThat(compatConfig.lookupChangeId("MY_CHANGE")).isEqualTo(1234L);
}
@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 testLookupChangeIdNotPresent() throws Exception {
+ CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ assertThat(compatConfig.lookupChangeId("MY_CHANGE")).isEqualTo(-1L);
+ }
+
+ @Test
+ 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 compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ compatConfig.initConfigFromLib(dir);
- CompatConfig pc = new CompatConfig();
- pc.initConfigFromLib(dir);
-
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
- assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse();
- assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1235L,
+ ApplicationInfoBuilder.create().withTargetSdk(5).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1236L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue();
}
@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 compatConfig = new CompatConfig(mBuildClassifier, mContext);
+ compatConfig.initConfigFromLib(dir);
-
- CompatConfig pc = new CompatConfig();
- pc.initConfigFromLib(dir);
-
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse();
- assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue();
- assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse();
- assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1234L,
+ ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue();
+ assertThat(compatConfig.isChangeEnabled(1235L,
+ ApplicationInfoBuilder.create().withTargetSdk(5).build())).isFalse();
+ assertThat(compatConfig.isChangeEnabled(1236L,
+ ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue();
}
}
-
-
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatibilityChangeConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatibilityChangeConfigBuilder.java
new file mode 100644
index 0000000..793296e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatibilityChangeConfigBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * 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.compat;
+
+import android.compat.Compatibility;
+
+import com.android.internal.compat.CompatibilityChangeConfig;
+
+import java.util.HashSet;
+import java.util.Set;
+
+class CompatibilityChangeConfigBuilder {
+ private Set<Long> mEnabled;
+ private Set<Long> mDisabled;
+
+ private CompatibilityChangeConfigBuilder() {
+ mEnabled = new HashSet<>();
+ mDisabled = new HashSet<>();
+ }
+
+ static CompatibilityChangeConfigBuilder create() {
+ return new CompatibilityChangeConfigBuilder();
+ }
+
+ CompatibilityChangeConfigBuilder enable(Long id) {
+ mEnabled.add(id);
+ return this;
+ }
+
+ CompatibilityChangeConfigBuilder disable(Long id) {
+ mDisabled.add(id);
+ return this;
+ }
+
+ CompatibilityChangeConfig build() {
+ return new CompatibilityChangeConfig(new Compatibility.ChangeConfig(mEnabled, mDisabled));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
new file mode 100644
index 0000000..ecd07bd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
@@ -0,0 +1,383 @@
+/*
+ * 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.compat;
+
+import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE;
+import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.compat.AndroidBuildClassifier;
+import com.android.internal.compat.IOverrideValidator;
+import com.android.internal.compat.OverrideAllowedState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class OverrideValidatorImplTest {
+ private static final String PACKAGE_NAME = "my.package";
+ private static final int TARGET_SDK = 10;
+ private static final int TARGET_SDK_BEFORE = 9;
+ private static final int TARGET_SDK_AFTER = 11;
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ Context mContext;
+
+ private AndroidBuildClassifier debuggableBuild() {
+ AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class);
+ when(buildClassifier.isDebuggableBuild()).thenReturn(true);
+ return buildClassifier;
+ }
+
+ private AndroidBuildClassifier betaBuild() {
+ AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class);
+ when(buildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(buildClassifier.isFinalBuild()).thenReturn(false);
+ return buildClassifier;
+ }
+
+ private AndroidBuildClassifier finalBuild() {
+ AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class);
+ when(buildClassifier.isDebuggableBuild()).thenReturn(false);
+ when(buildClassifier.isFinalBuild()).thenReturn(true);
+ return buildClassifier;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ }
+
+ @Test
+ public void getOverrideAllowedState_debugBuildAnyChangeDebugApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withTargetSdk(TARGET_SDK)
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_debugBuildAnyChangeReleaseApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildTargetSdkChangeDebugApp_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withTargetSdk(TARGET_SDK)
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_BEFORE));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_AFTER));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildEnabledChangeDebugApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addEnabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .debuggable()
+ .build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildDisabledChangeDebugApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addDisabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_betaBuildAnyChangeReleaseApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptin_allowOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .debuggable()
+ .withTargetSdk(TARGET_SDK)
+ .withPackageName(PACKAGE_NAME).build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_AFTER));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptout_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK)
+ .debuggable()
+ .build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange).isEqualTo(
+ new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, TARGET_SDK,
+ TARGET_SDK_BEFORE));
+ assertThat(stateTargetSdkEqualChange).isEqualTo(
+ new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, TARGET_SDK, TARGET_SDK));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildEnabledChangeDebugApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addEnabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .debuggable().build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildDisabledChangeDebugApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addDisabledChangeWithId(1).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .debuggable().build());
+
+ OverrideAllowedState allowedState =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+
+ assertThat(allowedState)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
+ }
+
+ @Test
+ public void getOverrideAllowedState_finalBuildAnyChangeReleaseApp_rejectOverride()
+ throws Exception {
+ CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
+ .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addTargetSdkChangeWithId(TARGET_SDK, 2)
+ .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnabledChangeWithId(4)
+ .addDisabledChangeWithId(5).build();
+ IOverrideValidator overrideValidator = config.getOverrideValidator();
+ when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(ApplicationInfoBuilder.create()
+ .withPackageName(PACKAGE_NAME)
+ .withTargetSdk(TARGET_SDK).build());
+
+ OverrideAllowedState stateTargetSdkLessChange =
+ overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkEqualChange =
+ overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
+ OverrideAllowedState stateTargetSdkAfterChange =
+ overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
+ OverrideAllowedState stateEnabledChange =
+ overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
+ OverrideAllowedState stateDisabledChange =
+ overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
+
+ assertThat(stateTargetSdkLessChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkEqualChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateTargetSdkAfterChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateEnabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ assertThat(stateDisabledChange)
+ .isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index c406876..ce5d6d9 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -26,21 +26,20 @@
import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.testng.Assert.assertThrows;
-import android.compat.Compatibility;
import android.content.Context;
import android.content.pm.PackageManager;
-import com.android.internal.compat.CompatibilityChangeConfig;
+import androidx.test.runner.AndroidJUnit4;
-import com.google.common.collect.ImmutableSet;
+import com.android.internal.compat.AndroidBuildClassifier;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.MockitoAnnotations;
-@RunWith(MockitoJUnitRunner.class)
+@RunWith(AndroidJUnit4.class)
public class PlatformCompatTest {
private static final String PACKAGE_NAME = "my.package";
@@ -50,84 +49,77 @@
private PackageManager mPackageManager;
@Mock
CompatChange.ChangeListener mListener1, mListener2;
-
+ PlatformCompat mPlatformCompat;
+ CompatConfig mCompatConfig;
+ @Mock
+ private AndroidBuildClassifier mBuildClassifier;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getPackageUid(eq(PACKAGE_NAME), eq(0))).thenThrow(
new PackageManager.NameNotFoundException());
- CompatConfig.get().clearChanges();
+ mCompatConfig = new CompatConfig(mBuildClassifier, mContext);
+ mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
+ // Assume userdebug/eng non-final build
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
+ when(mBuildClassifier.isFinalBuild()).thenReturn(false);
}
@Test
- public void testRegisterListenerToSameIdThrows() {
- PlatformCompat pc = new PlatformCompat(mContext);
-
+ public void testRegisterListenerToSameIdThrows() throws Exception {
// Registering a listener to change 1 is successful.
- pc.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(1, mListener1);
// Registering a listener to change 2 is successful.
- pc.registerListener(2, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
// Trying to register another listener to change id 1 fails.
- assertThrows(IllegalStateException.class, () -> pc.registerListener(1, mListener1));
+ assertThrows(IllegalStateException.class,
+ () -> mPlatformCompat.registerListener(1, mListener1));
}
@Test
- public void testRegisterListenerReturn() {
- PlatformCompat pc = new PlatformCompat(mContext);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of())),
+ public void testRegisterListenerReturn() throws Exception {
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).build(),
PACKAGE_NAME);
// Change id 1 is known (added in setOverrides).
- assertThat(pc.registerListener(1, mListener1)).isTrue();
+ assertThat(mPlatformCompat.registerListener(1, mListener1)).isTrue();
// Change 2 is unknown.
- assertThat(pc.registerListener(2, mListener1)).isFalse();
+ assertThat(mPlatformCompat.registerListener(2, mListener1)).isFalse();
}
@Test
- public void testListenerCalledOnSetOverrides() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnSetOverrides() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener1);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(2)).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerNotCalledOnWrongPackage() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerNotCalledOnWrongPackage() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener1);
-
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, never()).onCompatChange("other.package");
}
@Test
- public void testListenerCalledOnSetOverridesTwoListeners() {
- PlatformCompat pc = new PlatformCompat(mContext);
- pc.registerListener(1, mListener1);
+ public void testListenerCalledOnSetOverridesTwoListeners() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
- final ImmutableSet<Long> enabled = ImmutableSet.of(1L);
- final ImmutableSet<Long> disabled = ImmutableSet.of(2L);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -136,11 +128,10 @@
reset(mListener1);
reset(mListener2);
- pc.registerListener(2, mListener2);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -148,31 +139,23 @@
}
@Test
- public void testListenerCalledOnSetOverridesForTest() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnSetOverridesForTest() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener1);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener1);
-
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(2)).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnSetOverridesTwoListenersForTest() {
- PlatformCompat pc = new PlatformCompat(mContext);
- pc.registerListener(1, mListener1);
+ public void testListenerCalledOnSetOverridesTwoListenersForTest() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
- final ImmutableSet<Long> enabled = ImmutableSet.of(1L);
- final ImmutableSet<Long> disabled = ImmutableSet.of(2L);
-
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -181,10 +164,10 @@
reset(mListener1);
reset(mListener2);
- pc.registerListener(2, mListener2);
- pc.setOverridesForTest(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled)),
+ mPlatformCompat.registerListener(2, mListener2);
+
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
@@ -192,15 +175,12 @@
}
@Test
- public void testListenerCalledOnClearOverrides() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverrides() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener2);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of())),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
@@ -208,21 +188,18 @@
reset(mListener1);
reset(mListener2);
- pc.clearOverrides(PACKAGE_NAME);
+ mPlatformCompat.clearOverrides(PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnClearOverridesMultipleOverrides() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverridesMultipleOverrides() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener2);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of(2L))),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).disable(2L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, times(1)).onCompatChange(PACKAGE_NAME);
@@ -230,21 +207,18 @@
reset(mListener1);
reset(mListener2);
- pc.clearOverrides(PACKAGE_NAME);
+ mPlatformCompat.clearOverrides(PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, times(1)).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnClearOverrideExists() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverrideExists() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
+ mPlatformCompat.registerListener(2, mListener2);
- pc.registerListener(1, mListener1);
- pc.registerListener(2, mListener2);
-
- pc.setOverrides(
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(ImmutableSet.of(1L), ImmutableSet.of())),
+ mPlatformCompat.setOverrides(
+ CompatibilityChangeConfigBuilder.create().enable(1L).build(),
PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
@@ -252,21 +226,17 @@
reset(mListener1);
reset(mListener2);
- pc.clearOverride(1, PACKAGE_NAME);
+ mPlatformCompat.clearOverride(1, PACKAGE_NAME);
verify(mListener1, times(1)).onCompatChange(PACKAGE_NAME);
verify(mListener2, never()).onCompatChange(PACKAGE_NAME);
}
@Test
- public void testListenerCalledOnClearOverrideDoesntExist() {
- PlatformCompat pc = new PlatformCompat(mContext);
+ public void testListenerCalledOnClearOverrideDoesntExist() throws Exception {
+ mPlatformCompat.registerListener(1, mListener1);
- pc.registerListener(1, mListener1);
-
- pc.clearOverride(1, PACKAGE_NAME);
+ mPlatformCompat.clearOverride(1, PACKAGE_NAME);
// Listener not called when a non existing override is removed.
verify(mListener1, never()).onCompatChange(PACKAGE_NAME);
}
-
-
}
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/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/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 72a7f50..71b568c 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -18,15 +18,18 @@
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;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -77,6 +80,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());
@@ -86,13 +105,29 @@
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).enforceCallingOrSelfPermission(anyString(), any());
@@ -102,13 +137,43 @@
mTestHandler.assertTotalMessagesEnqueued(1);
verify(mMockContext).enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.SET_TIME),
+ eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE),
anyString());
mTestHandler.waitForEmptyQueue();
mStubbedTimeDetectorStrategy.verifySuggestManualTimeCalled(manualTimeSuggestion);
}
+ @Test(expected = SecurityException.class)
+ public void testSuggestNetworkTime_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+ NetworkTimeSuggestion NetworkTimeSuggestion = createNetworkTimeSuggestion();
+
+ try {
+ mTimeDetectorService.suggestNetworkTime(NetworkTimeSuggestion);
+ fail();
+ } finally {
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+ }
+ }
+
+ @Test
+ public void testSuggestNetworkTime() throws Exception {
+ doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+
+ NetworkTimeSuggestion NetworkTimeSuggestion = createNetworkTimeSuggestion();
+ mTimeDetectorService.suggestNetworkTime(NetworkTimeSuggestion);
+ mTestHandler.assertTotalMessagesEnqueued(1);
+
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+
+ mTestHandler.waitForEmptyQueue();
+ mStubbedTimeDetectorStrategy.verifySuggestNetworkTimeCalled(NetworkTimeSuggestion);
+ }
+
@Test
public void testDump() {
when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
@@ -146,11 +211,17 @@
return new ManualTimeSuggestion(timeValue);
}
+ private static NetworkTimeSuggestion createNetworkTimeSuggestion() {
+ TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
+ return new NetworkTimeSuggestion(timeValue);
+ }
+
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
// Call tracking.
private PhoneTimeSuggestion mLastPhoneSuggestion;
private ManualTimeSuggestion mLastManualSuggestion;
+ private NetworkTimeSuggestion mLastNetworkSuggestion;
private boolean mLastAutoTimeDetectionToggleCalled;
private boolean mDumpCalled;
@@ -171,6 +242,12 @@
}
@Override
+ public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
+ resetCallTracking();
+ mLastNetworkSuggestion = timeSuggestion;
+ }
+
+ @Override
public void handleAutoTimeDetectionChanged() {
resetCallTracking();
mLastAutoTimeDetectionToggleCalled = true;
@@ -185,6 +262,7 @@
void resetCallTracking() {
mLastPhoneSuggestion = null;
mLastManualSuggestion = null;
+ mLastNetworkSuggestion = null;
mLastAutoTimeDetectionToggleCalled = false;
mDumpCalled = false;
}
@@ -197,6 +275,10 @@
assertEquals(expectedSuggestion, mLastManualSuggestion);
}
+ public void verifySuggestNetworkTimeCalled(NetworkTimeSuggestion expectedSuggestion) {
+ assertEquals(expectedSuggestion, mLastNetworkSuggestion);
+ }
+
void verifyHandleAutoTimeDetectionToggleCalled() {
assertTrue(mLastAutoTimeDetectionToggleCalled);
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 1aa3d8f..ca6fd08 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.fail;
import android.app.timedetector.ManualTimeSuggestion;
+import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.PhoneTimeSuggestion;
import android.content.Intent;
import android.icu.util.Calendar;
@@ -45,14 +46,16 @@
private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO =
new TimestampedValue<>(
123456789L /* realtimeClockMillis */,
- createUtcTime(1977, 1, 1, 12, 0, 0));
+ createUtcTime(2008, 5, 23, 12, 0, 0));
+ /**
+ * An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO}
+ * time. Can be used as the basis for time suggestions.
+ */
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
@@ -67,15 +70,16 @@
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()
+ .simulatePhoneTimeSuggestion(timeSuggestion);
- mScript.simulateTimePassing(clockIncrement)
- .simulatePhoneTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(
- expectedSystemClockMillis, true /* expectNetworkBroadcast */)
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, true /* expectNetworkBroadcast */)
.assertLatestPhoneSuggestion(phoneId, timeSuggestion);
}
@@ -94,26 +98,24 @@
@Test
public void testSuggestPhoneTime_systemClockThreshold() {
- int systemClockUpdateThresholdMillis = 1000;
+ final int systemClockUpdateThresholdMillis = 1000;
+ final int clockIncrementMillis = 100;
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();
+ mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
// Increment the the device clocks to simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+ mScript.calculateTimeInMillisForNow(timeSuggestion1.getUtcTime());
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
@@ -127,7 +129,7 @@
int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
PhoneTimeSuggestion timeSuggestion2 = mScript.generatePhoneTimeSuggestion(
phoneId, mScript.peekSystemClockMillis() + underThresholdMillis);
- mScript.simulateTimePassing(clockIncrement)
+ mScript.simulateTimePassing(clockIncrementMillis)
.simulatePhoneTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestPhoneSuggestion(phoneId, timeSuggestion2);
@@ -138,11 +140,10 @@
PhoneTimeSuggestion timeSuggestion3 = mScript.generatePhoneTimeSuggestion(
phoneId,
mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis3 =
- TimeDetectorStrategy.getTimeAt(timeSuggestion3.getUtcTime(),
- mScript.peekElapsedRealtimeMillis());
+ mScript.calculateTimeInMillisForNow(timeSuggestion3.getUtcTime());
mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
.verifySystemClockWasSetAndResetCallTracking(
@@ -162,17 +163,16 @@
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;
+ long phone2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis();
// Make a suggestion with phone2Id.
{
PhoneTimeSuggestion phone2TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
- long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phone2TimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
@@ -181,15 +181,16 @@
.assertLatestPhoneSuggestion(phone2Id, phone2TimeSuggestion);
}
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
// Now make a different suggestion with phone1Id.
{
PhoneTimeSuggestion phone1TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone1Id, phone1TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
- long expectedSystemClockMillis = phone1TimeMillis + clockIncrement;
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phone1TimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phone1TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
@@ -198,14 +199,14 @@
}
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
// 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.simulateTimePassing();
mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
@@ -220,9 +221,10 @@
{
PhoneTimeSuggestion phone2TimeSuggestion =
mScript.generatePhoneTimeSuggestion(phone2Id, phone2TimeMillis);
- mScript.simulateTimePassing(clockIncrement);
+ mScript.simulateTimePassing();
- long expectedSystemClockMillis = phone2TimeMillis + clockIncrement;
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phone2TimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phone2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
@@ -239,7 +241,7 @@
int phoneId = ARBITRARY_PHONE_ID;
PhoneTimeSuggestion timeSuggestion =
mScript.generatePhoneTimeSuggestion(phoneId, ARBITRARY_TEST_TIME_MILLIS);
- mScript.simulateTimePassing(1000)
+ mScript.simulateTimePassing()
.simulatePhoneTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestPhoneSuggestion(phoneId, timeSuggestion);
@@ -260,9 +262,8 @@
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.simulateTimePassing();
+ long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
expectedSystemClockMillis1, true /* expectNetworkBroadcast */)
@@ -299,8 +300,7 @@
long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
validReferenceTimeMillis, validUtcTimeMillis);
- long expectedSystemClockMillis4 =
- TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
+ long expectedSystemClockMillis4 = mScript.calculateTimeInMillisForNow(utcTime4);
PhoneTimeSuggestion timeSuggestion4 =
createPhoneTimeSuggestion(phoneId, utcTime4);
mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
@@ -335,8 +335,7 @@
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
- long expectedSystemClockMillis1 =
- TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
+ long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
// Turn on auto time detection.
mScript.simulateAutoTimeDetectionToggle()
@@ -357,8 +356,8 @@
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
- long expectedSystemClockMillis2 = TimeDetectorStrategy.getTimeAt(
- timeSuggestion2.getUtcTime(), mScript.peekElapsedRealtimeMillis());
+ long expectedSystemClockMillis2 =
+ mScript.calculateTimeInMillisForNow(timeSuggestion2.getUtcTime());
// The new time, though valid, should not be set in the system clock because auto time is
// disabled.
@@ -382,19 +381,21 @@
long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS;
PhoneTimeSuggestion phoneSuggestion =
mScript.generatePhoneTimeSuggestion(phoneId, testTimeMillis);
- int clockIncrementMillis = 1000;
- mScript.simulateTimePassing(clockIncrementMillis)
- .simulatePhoneTimeSuggestion(phoneSuggestion)
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(phoneSuggestion.getUtcTime());
+ mScript.simulatePhoneTimeSuggestion(phoneSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- testTimeMillis + clockIncrementMillis, true /* expectedNetworkBroadcast */)
+ expectedSystemClockMillis, 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);
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_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.
@@ -407,13 +408,14 @@
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;
+ ManualTimeSuggestion timeSuggestion =
+ mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
- mScript.simulateTimePassing(clockIncrement)
- .simulateManualTimeSuggestion(timeSuggestion)
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.simulateManualTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
expectedSystemClockMillis, false /* expectNetworkBroadcast */);
}
@@ -430,21 +432,19 @@
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.simulateTimePassing();
+ long expectedAutoClockMillis =
+ mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime());
mScript.simulatePhoneTimeSuggestion(phoneTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
expectedAutoClockMillis, true /* expectNetworkBroadcast */)
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
// Switch to manual.
mScript.simulateAutoTimeDetectionToggle()
@@ -452,26 +452,29 @@
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
// Simulate a manual suggestion 1 day different from the auto suggestion.
- long manualTimeMillis = testTimeMillis + ONE_DAY_MILLIS;
- long expectedManualClockMillis = manualTimeMillis;
+ long manualTimeMillis = testTimeMillis + Duration.ofDays(1).toMillis();
ManualTimeSuggestion manualTimeSuggestion =
mScript.generateManualTimeSuggestion(manualTimeMillis);
+ mScript.simulateTimePassing();
+
+ long expectedManualClockMillis =
+ mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUtcTime());
mScript.simulateManualTimeSuggestion(manualTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
expectedManualClockMillis, false /* expectNetworkBroadcast */)
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing(clockIncrement);
- expectedAutoClockMillis += clockIncrement;
+ mScript.simulateTimePassing();
// Switch back to auto.
mScript.simulateAutoTimeDetectionToggle();
+ expectedAutoClockMillis =
+ mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime());
mScript.verifySystemClockWasSetAndResetCallTracking(
expectedAutoClockMillis, true /* expectNetworkBroadcast */)
.assertLatestPhoneSuggestion(phoneId, phoneTimeSuggestion);
@@ -492,13 +495,143 @@
ManualTimeSuggestion timeSuggestion =
mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
- final int clockIncrement = 1000;
- mScript.simulateTimePassing(clockIncrement)
+ mScript.simulateTimePassing()
.simulateManualTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
+ @Test
+ public void testSuggestNetworkTime_autoTimeEnabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ NetworkTimeSuggestion timeSuggestion =
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ expectedSystemClockMillis, false /* expectNetworkBroadcast */);
+ }
+
+ @Test
+ public void testSuggestNetworkTime_autoTimeDisabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(false);
+
+ NetworkTimeSuggestion timeSuggestion =
+ mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS);
+
+ mScript.simulateTimePassing()
+ .simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestNetworkTime_phoneSuggestionsBeatNetworkSuggestions() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ // Three obviously different times that could not be mistaken for each other.
+ long networkTimeMillis1 = ARBITRARY_TEST_TIME_MILLIS;
+ long networkTimeMillis2 = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(30).toMillis();
+ long phoneTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis();
+ // A small increment used to simulate the passage of time, but not enough to interfere with
+ // macro-level time changes associated with suggestion age.
+ final long smallTimeIncrementMillis = 101;
+
+ // A network suggestion is made. It should be used because there is no phone suggestion.
+ NetworkTimeSuggestion networkTimeSuggestion1 =
+ mScript.generateNetworkTimeSuggestion(networkTimeMillis1);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion1)
+ .verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(networkTimeSuggestion1.getUtcTime()),
+ false /* expectNetworkBroadcast */);
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, null)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion1);
+ assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
+ assertNull(mScript.peekBestPhoneSuggestion());
+
+ // Simulate a little time passing.
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Now a phone suggestion is made. Phone suggestions are prioritized over network
+ // suggestions so it should "win".
+ PhoneTimeSuggestion phoneTimeSuggestion =
+ mScript.generatePhoneTimeSuggestion(ARBITRARY_PHONE_ID, phoneTimeMillis);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulatePhoneTimeSuggestion(phoneTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(phoneTimeSuggestion.getUtcTime()),
+ true /* expectNetworkBroadcast */);
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion1);
+ assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(phoneTimeSuggestion, mScript.peekBestPhoneSuggestion());
+
+ // Simulate some significant time passing: half the time allowed before a time signal
+ // becomes "too old to use".
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Now another network suggestion is made. Phone suggestions are prioritized over network
+ // suggestions so the latest phone suggestion should still "win".
+ NetworkTimeSuggestion networkTimeSuggestion2 =
+ mScript.generateNetworkTimeSuggestion(networkTimeMillis2);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion2)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion2);
+ assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(phoneTimeSuggestion, mScript.peekBestPhoneSuggestion());
+
+ // Simulate some significant time passing: half the time allowed before a time signal
+ // becomes "too old to use". This should mean that phoneTimeSuggestion is now too old to be
+ // used but networkTimeSuggestion2 is not.
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+
+ // NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
+ // suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
+ // to re-run the detection logic. This may change in future but until then we rely on a
+ // steady stream of suggestions to re-evaluate.
+ mScript.verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion2);
+ assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertNull(mScript.peekBestPhoneSuggestion());
+
+ // Toggle auto-time off and on to force the detection logic to run.
+ mScript.simulateAutoTimeDetectionToggle()
+ .simulateTimePassing(smallTimeIncrementMillis)
+ .simulateAutoTimeDetectionToggle();
+
+ // Verify the latest network time now wins.
+ mScript.verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(networkTimeSuggestion2.getUtcTime()),
+ false /* expectNetworkTimeBroadcast */);
+
+ // Check internal state.
+ mScript.assertLatestPhoneSuggestion(ARBITRARY_PHONE_ID, phoneTimeSuggestion)
+ .assertLatestNetworkSuggestion(networkTimeSuggestion2);
+ assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertNull(mScript.peekBestPhoneSuggestion());
+ }
+
/**
* A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
* like the real thing should, it also asserts preconditions.
@@ -674,6 +807,11 @@
return this;
}
+ Script simulateNetworkTimeSuggestion(NetworkTimeSuggestion timeSuggestion) {
+ mTimeDetectorStrategy.suggestNetworkTime(timeSuggestion);
+ return this;
+ }
+
Script simulateAutoTimeDetectionToggle() {
mFakeCallback.simulateAutoTimeZoneDetectionToggle();
mTimeDetectorStrategy.handleAutoTimeDetectionChanged();
@@ -685,6 +823,13 @@
return this;
}
+ /**
+ * Simulates time passing by an arbitrary (but relatively small) amount.
+ */
+ Script simulateTimePassing() {
+ return simulateTimePassing(999);
+ }
+
Script verifySystemClockWasNotSetAndResetCallTracking() {
mFakeCallback.verifySystemClockNotSet();
mFakeCallback.verifyIntentWasNotBroadcast();
@@ -711,14 +856,30 @@
}
/**
+ * White box test info: Asserts the latest network suggestion is as expected.
+ */
+ Script assertLatestNetworkSuggestion(NetworkTimeSuggestion expected) {
+ assertEquals(expected, mTimeDetectorStrategy.getLatestNetworkSuggestion());
+ return this;
+ }
+
+ /**
* White box test info: Returns the phone suggestion that would be used, if any, given the
- * current elapsed real time clock.
+ * current elapsed real time clock and regardless of origin prioritization.
*/
PhoneTimeSuggestion peekBestPhoneSuggestion() {
return mTimeDetectorStrategy.findBestPhoneSuggestionForTests();
}
/**
+ * White box test info: Returns the network suggestion that would be used, if any, given the
+ * current elapsed real time clock and regardless of origin prioritization.
+ */
+ NetworkTimeSuggestion peekLatestValidNetworkSuggestion() {
+ return mTimeDetectorStrategy.findLatestValidNetworkSuggestionForTests();
+ }
+
+ /**
* Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
* reference time.
*/
@@ -739,6 +900,24 @@
}
return createPhoneTimeSuggestion(phoneId, time);
}
+
+ /**
+ * Generates a NetworkTimeSuggestion using the current elapsed realtime clock for the
+ * reference time.
+ */
+ NetworkTimeSuggestion generateNetworkTimeSuggestion(long timeMillis) {
+ TimestampedValue<Long> utcTime =
+ new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis);
+ return new NetworkTimeSuggestion(utcTime);
+ }
+
+ /**
+ * Calculates what the supplied time would be when adjusted for the movement of the fake
+ * elapsed realtime clock.
+ */
+ long calculateTimeInMillisForNow(TimestampedValue<Long> utcTime) {
+ return TimeDetectorStrategy.getTimeAt(utcTime, peekElapsedRealtimeMillis());
+ }
}
private static PhoneTimeSuggestion createPhoneTimeSuggestion(int phoneId,
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/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 0becaf2..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";
/**
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/OWNERS b/telephony/OWNERS
index 2a6e8de..58a7ea0 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -14,4 +14,5 @@
refuhoo@google.com
paulye@google.com
nazaninb@google.com
-sarahchin@google.com
\ No newline at end of file
+sarahchin@google.com
+dbright@google.com
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
similarity index 92%
rename from telephony/java/android/telephony/LocationAccessPolicy.java
rename to telephony/common/android/telephony/LocationAccessPolicy.java
index d4526a4..8ac6755 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,13 +11,14 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package android.telephony;
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -59,8 +60,10 @@
DENIED_HARD,
}
+ /** Data structure for location permission query */
public static class LocationPermissionQuery {
public final String callingPackage;
+ public final String callingFeatureId;
public final int callingUid;
public final int callingPid;
public final int minSdkVersionForCoarse;
@@ -68,10 +71,11 @@
public final boolean logAsInfo;
public final String method;
- private LocationPermissionQuery(String callingPackage, int callingUid, int callingPid,
- int minSdkVersionForCoarse, int minSdkVersionForFine, boolean logAsInfo,
- String method) {
+ private LocationPermissionQuery(String callingPackage, @Nullable String callingFeatureId,
+ int callingUid, int callingPid, int minSdkVersionForCoarse,
+ int minSdkVersionForFine, boolean logAsInfo, String method) {
this.callingPackage = callingPackage;
+ this.callingFeatureId = callingFeatureId;
this.callingUid = callingUid;
this.callingPid = callingPid;
this.minSdkVersionForCoarse = minSdkVersionForCoarse;
@@ -80,8 +84,10 @@
this.method = method;
}
+ /** Builder for LocationPermissionQuery */
public static class Builder {
private String mCallingPackage;
+ private String mCallingFeatureId;
private int mCallingUid;
private int mCallingPid;
private int mMinSdkVersionForCoarse = Integer.MAX_VALUE;
@@ -100,6 +106,11 @@
/**
* Mandatory parameter, used for performing permission checks.
*/
+ public Builder setCallingFeatureId(@Nullable String callingFeatureId) {
+ mCallingFeatureId = callingFeatureId;
+ return this;
+ }
+
public Builder setCallingUid(int callingUid) {
mCallingUid = callingUid;
return this;
@@ -149,9 +160,10 @@
return this;
}
+ /** build LocationPermissionQuery */
public LocationPermissionQuery build() {
- return new LocationPermissionQuery(mCallingPackage, mCallingUid,
- mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
+ return new LocationPermissionQuery(mCallingPackage, mCallingFeatureId,
+ mCallingUid, mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
mLogAsInfo, mMethod);
}
}
@@ -235,6 +247,7 @@
}
}
+ /** Check if location permissions have been granted */
public static LocationPermissionResult checkLocationPermission(
Context context, LocationPermissionQuery query) {
// Always allow the phone process and system server to access location. This avoid
@@ -341,4 +354,4 @@
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
similarity index 94%
rename from telephony/java/com/android/internal/telephony/CarrierAppUtils.java
rename to telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 0630454..b5d3369 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.internal.telephony;
@@ -73,7 +73,7 @@
* system startup prior to any application running, as well as any time the set of carrier
* privileged apps may have changed.
*/
- public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, TelephonyManager telephonyManager,
ContentResolver contentResolver, int userId) {
if (DEBUG) {
@@ -100,7 +100,7 @@
* broadcasts. The app will continue to run (briefly) after being disabled, before the Package
* Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
*/
- public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, ContentResolver contentResolver, int userId) {
if (DEBUG) {
Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
@@ -117,7 +117,10 @@
systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed);
}
- // Must be public b/c framework unit tests can't access package-private methods.
+ /**
+ * Disable carrier apps until they are privileged
+ * Must be public b/c framework unit tests can't access package-private methods.
+ */
@VisibleForTesting
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
IPackageManager packageManager, @Nullable TelephonyManager telephonyManager,
@@ -166,10 +169,10 @@
// Only update enabled state for the app on /system. Once it has been
// updated we shouldn't touch it.
if (!ai.isUpdatedSystemApp()
- && (ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ && (ai.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || ai.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ userId);
@@ -188,10 +191,10 @@
// Also enable any associated apps for this carrier app.
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
- if (associatedApp.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || associatedApp.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ if (associatedApp.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || associatedApp.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
|| (associatedApp.flags
& ApplicationInfo.FLAG_INSTALLED) == 0) {
Slog.i(TAG, "Update associated state(" + associatedApp.packageName
@@ -216,8 +219,8 @@
// Only update enabled state for the app on /system. Once it has been
// updated we shouldn't touch it.
if (!ai.isUpdatedSystemApp()
- && ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && ai.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
Slog.i(TAG, "Update state(" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
@@ -291,8 +294,8 @@
ApplicationInfo ai = candidates.get(i);
String packageName = ai.packageName;
boolean hasPrivileges =
- telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
- TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
if (!hasPrivileges) {
candidates.remove(i);
}
diff --git a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
index 922af12..0b47547 100644
--- a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
+++ b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
@@ -24,17 +24,17 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
+import android.os.HandlerThread;
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();
+ private static HandlerThread sHandlerThread;
static {
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -43,28 +43,24 @@
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
sPackageIntentFilter.addDataScheme("package");
}
+ // Keep an instance of Context around as long as we still want the receiver:
+ // if the instance of Context gets garbage-collected, it'll unregister the receiver, so only
+ // unset when we want to unregister.
Context mRegisteredContext;
/**
- * To register the intents that needed for monitoring the state of packages
+ * To register the intents that needed for monitoring the state of packages. Once this method
+ * has been called on an instance of {@link PackageChangeReceiver}, all subsequent calls must
+ * have the same {@code user} argument.
*/
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();
- }
+ Handler handler = new Handler(thread == null ? getStaticLooper() : thread);
+ mRegisteredContext = user == null ? context : context.createContextAsUser(user, 0);
+ mRegisteredContext.registerReceiver(this, sPackageIntentFilter, null, handler);
}
/**
@@ -78,6 +74,14 @@
mRegisteredContext = null;
}
+ private static synchronized Looper getStaticLooper() {
+ if (sHandlerThread == null) {
+ sHandlerThread = new HandlerThread(PackageChangeReceiver.class.getSimpleName());
+ sHandlerThread.start();
+ }
+ return sHandlerThread.getLooper();
+ }
+
/**
* This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
*/
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index df668ea..53842cd 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -44,6 +44,7 @@
import android.telephony.TelephonyManager;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -57,7 +58,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
-
+import java.util.stream.Collectors;
/**
@@ -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;
@@ -249,6 +250,7 @@
private static Collection<SmsApplicationData> getApplicationCollectionInternal(
Context context, int userId) {
PackageManager packageManager = context.getPackageManager();
+ UserHandle userHandle = UserHandle.of(userId);
// Get the list of apps registered for SMS
Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
@@ -257,7 +259,7 @@
}
List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
@@ -284,7 +286,7 @@
intent.setDataAndType(null, "application/vnd.wap.mms-message");
List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
for (ResolveInfo resolveInfo : mmsReceivers) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
@@ -326,7 +328,7 @@
Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
for (ResolveInfo resolveInfo : sendToActivities) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
@@ -344,7 +346,7 @@
List<ResolveInfo> smsAppChangedReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
smsAppChangedReceivers);
@@ -371,7 +373,7 @@
List<ResolveInfo> providerChangedReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
providerChangedReceivers);
@@ -398,7 +400,7 @@
List<ResolveInfo> simFullReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
+ simFullReceivers);
@@ -501,7 +503,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 +557,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;
}
@@ -630,7 +632,8 @@
}
// We only make the change if the new package is valid
- PackageManager packageManager = context.getPackageManager();
+ PackageManager packageManager =
+ context.createContextAsUser(userHandle, 0).getPackageManager();
Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
context, userId);
SmsApplicationData oldAppData = oldPackageName != null ?
@@ -641,8 +644,7 @@
AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
if (oldPackageName != null) {
try {
- int uid = packageManager.getPackageInfoAsUser(
- oldPackageName, 0, userId).applicationInfo.uid;
+ int uid = packageManager.getPackageInfo(oldPackageName, 0).applicationInfo.uid;
setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
} catch (NameNotFoundException e) {
Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
@@ -757,7 +759,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 +775,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);
}
}
@@ -806,9 +808,16 @@
}
private void onPackageChanged() {
- PackageManager packageManager = mContext.getPackageManager();
+ int userId;
+ try {
+ userId = getSendingUser().getIdentifier();
+ } catch (NullPointerException e) {
+ // This should never happen in prod -- unit tests will put the receiver into a
+ // unusual state where the pending result is null, which produces a NPE when calling
+ // getSendingUserId. Just pretend like it's the system user for testing.
+ userId = UserHandle.USER_SYSTEM;
+ }
Context userContext = mContext;
- final int userId = getSendingUserId();
if (userId != UserHandle.USER_SYSTEM) {
try {
userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
@@ -819,10 +828,11 @@
}
}
}
+ PackageManager packageManager = userContext.getPackageManager();
// Ensure this component is still configured as the preferred activity
ComponentName componentName = getDefaultSendToApplication(userContext, true);
if (componentName != null) {
- configurePreferredActivity(packageManager, componentName, userId);
+ configurePreferredActivity(packageManager, componentName);
}
}
}
@@ -834,41 +844,36 @@
@UnsupportedAppUsage
private static void configurePreferredActivity(PackageManager packageManager,
- ComponentName componentName, int userId) {
+ ComponentName componentName) {
// Add the four activity preferences we want to direct to this app.
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
}
/**
* Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
*/
private static void replacePreferredActivity(PackageManager packageManager,
- ComponentName componentName, int userId, String scheme) {
+ ComponentName componentName, String scheme) {
// Build the set of existing activities that handle this scheme
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
- List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
- userId);
+ List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
+ intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
- // Build the set of ComponentNames for these activities
- final int n = resolveInfoList.size();
- ComponentName[] set = new ComponentName[n];
- for (int i = 0; i < n; i++) {
- ResolveInfo info = resolveInfoList.get(i);
- set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
- }
+ List<ComponentName> components = resolveInfoList.stream().map(info ->
+ new ComponentName(info.activityInfo.packageName, info.activityInfo.name))
+ .collect(Collectors.toList());
// Update the preferred SENDTO activity for the specified scheme
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SENDTO);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter.addDataScheme(scheme);
- packageManager.replacePreferredActivityAsUser(intentFilter,
+ packageManager.replacePreferredActivity(intentFilter,
IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
- set, componentName, userId);
+ components, componentName);
}
/**
@@ -899,6 +904,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/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 606fd5b..f5dffbc 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -95,16 +96,19 @@
* inaccesible to carrier-privileged apps).
*/
public static boolean checkCallingOrSelfReadPhoneState(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
/** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
try {
- return checkCallingOrSelfReadPhoneState(context, subId, callingPackage, message);
+ return checkCallingOrSelfReadPhoneState(context, subId, callingPackage,
+ callingFeatureId, message);
} catch (SecurityException se) {
return false;
}
@@ -132,9 +136,11 @@
* devices.
*/
public static boolean checkReadPhoneState(
- Context context, int subId, int pid, int uid, String callingPackage, String message) {
+ Context context, int subId, int pid, int uid, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
return checkReadPhoneState(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
+ context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingFeatureId,
+ message);
}
/**
@@ -174,7 +180,7 @@
@VisibleForTesting
public static boolean checkReadPhoneState(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -217,10 +223,10 @@
* @return {@code true} if the app can read phone state or has carrier privilege;
* {@code false} otherwise.
*/
- public static boolean checkReadPhoneStateOnAnyActiveSub(
- Context context, int pid, int uid, String callingPackage, String message) {
+ public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid,
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid,
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
/**
@@ -240,7 +246,7 @@
@VisibleForTesting
public static boolean checkReadPhoneStateOnAnyActiveSub(
Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -283,9 +289,10 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkCallingOrSelfReadDeviceIdentifiers(context,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message);
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, callingFeatureId,
+ message);
}
/**
@@ -306,9 +313,9 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- context, subId, callingPackage, message, true);
+ context, subId, callingPackage, callingFeatureId, message, true);
}
/**
@@ -328,9 +335,9 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- context, subId, callingPackage, message, false);
+ context, subId, callingPackage, callingFeatureId, message, false);
}
/**
@@ -352,8 +359,8 @@
* </ul>
*/
private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- Context context, int subId, String callingPackage, String message,
- boolean allowCarrierPrivilegeOnAnySub) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message, boolean allowCarrierPrivilegeOnAnySub) {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
// Allow system and root access to the device identifiers.
@@ -479,9 +486,10 @@
* to it, {@code false} otherwise.
*/
public static boolean checkReadCallLog(
- Context context, int subId, int pid, int uid, String callingPackage) {
+ Context context, int subId, int pid, int uid, String callingPackage,
+ @Nullable String callingPackageName) {
return checkReadCallLog(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage);
+ context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingPackageName);
}
/**
@@ -492,7 +500,7 @@
@VisibleForTesting
public static boolean checkReadCallLog(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage) {
+ String callingPackage, @Nullable String callingFeatureId) {
if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
!= PERMISSION_GRANTED) {
@@ -519,10 +527,11 @@
* default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
*/
public static boolean checkCallingOrSelfReadPhoneNumber(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
return checkReadPhoneNumber(
context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
/**
@@ -534,7 +543,7 @@
@VisibleForTesting
public static boolean checkReadPhoneNumber(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
// Default SMS app can always read it.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage) ==
@@ -548,7 +557,8 @@
// First, check if we can read the phone state.
try {
return checkReadPhoneState(
- context, telephonySupplier, subId, pid, uid, callingPackage, message);
+ context, telephonySupplier, subId, pid, uid, callingPackage, callingFeatureId,
+ message);
} catch (SecurityException readPhoneStateSecurityException) {
}
// Can be read with READ_SMS too.
diff --git a/telephony/java/com/android/internal/telephony/util/ArrayUtils.java b/telephony/common/com/android/internal/telephony/util/ArrayUtils.java
similarity index 86%
rename from telephony/java/com/android/internal/telephony/util/ArrayUtils.java
rename to telephony/common/com/android/internal/telephony/util/ArrayUtils.java
index 2905125..28401a6 100644
--- a/telephony/java/com/android/internal/telephony/util/ArrayUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/ArrayUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,17 +29,30 @@
/**
* Adds value to given array if not already present, providing set-like behavior.
+ *
+ * @param kind The class of the array elements.
+ * @param array The array to append to.
+ * @param element The array element to append.
+ * @return The array containing the appended element.
*/
@SuppressWarnings("unchecked")
- public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
+ @NonNull
+ public static <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
return appendElement(kind, array, element, false);
}
/**
* Adds value to given array.
+ *
+ * @param kind The class of the array elements.
+ * @param array The array to append to.
+ * @param element The array element to append.
+ * @param allowDuplicates Whether to allow duplicated elements in array.
+ * @return The array containing the appended element.
*/
@SuppressWarnings("unchecked")
- public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
+ @NonNull
+ public static <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
boolean allowDuplicates) {
final T[] result;
final int end;
@@ -59,13 +72,14 @@
/**
* Combine multiple arrays into a single array.
*
- * @param kind The class of the array elements
+ * @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).
+ * @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) {
+ @NonNull
+ public static <T> T[] concatElements(Class<T> kind, @Nullable T[]... arrays) {
if (arrays == null || arrays.length == 0) {
return createEmptyArray(kind);
}
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
similarity index 71%
rename from telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
rename to telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index a28d65c..0498d7c 100644
--- a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -22,6 +22,8 @@
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;
@@ -71,4 +73,31 @@
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/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 3940a3b..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)
@@ -485,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 9f31cb3..2f37c2a 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -419,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.
@@ -833,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
*/
@@ -2303,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
@@ -2612,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
@@ -2996,16 +3074,18 @@
"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.";
/**
* Location information during (and after) an emergency call is only provided over control
* plane signaling from the network.
+ * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_CP_ONLY = 0;
@@ -3013,6 +3093,7 @@
* Location information during (and after) an emergency call is provided over the data
* plane and serviced by the framework GNSS service, but if it fails, the carrier also
* supports control plane backup signaling.
+ * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_CP_FALLBACK = 1;
@@ -3020,6 +3101,7 @@
* Location information during (and after) an emergency call is provided over the data plane
* and serviced by the framework GNSS service only. There is no backup signalling over the
* control plane if it fails.
+ * @hide
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_DP_ONLY = 2;
@@ -3036,10 +3118,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";
/**
@@ -3047,6 +3133,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";
@@ -3054,6 +3141,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";
@@ -3062,6 +3150,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";
@@ -3071,6 +3160,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";
@@ -3078,6 +3168,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";
@@ -3088,6 +3179,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";
@@ -3099,11 +3191,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";
@@ -3112,6 +3206,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";
@@ -3127,6 +3222,7 @@
* {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
* <p>
* The default value for this configuration is {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
+ * @hide
*/
public static final String KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT = KEY_PREFIX
+ "es_supl_control_plane_support_int";
@@ -3138,6 +3234,7 @@
* <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";
@@ -3163,59 +3260,6 @@
}
}
- /**
- * 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.
@@ -3478,7 +3522,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",
@@ -3510,6 +3553,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);
@@ -3723,6 +3768,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 */
@@ -3792,7 +3851,6 @@
/* Default value is 1 hour. */
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
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 */
@@ -3820,6 +3878,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);
}
/**
@@ -3845,7 +3905,8 @@
+ " ICarrierConfigLoader is null");
return null;
}
- return loader.getConfigForSubId(subId, mContext.getOpPackageName());
+ return loader.getConfigForSubIdWithFeature(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
Rlog.e(TAG, "Error getting config for subId " + subId + ": "
+ ex.toString());
@@ -4017,13 +4078,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 ce5e3f3..84be4e8 100644
--- a/telephony/java/android/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -18,19 +18,24 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.os.Build;
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
@@ -81,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;
@@ -97,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) {
@@ -106,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));
@@ -125,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 {
/**
@@ -145,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;
@@ -164,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();
@@ -245,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;
@@ -262,7 +274,7 @@
@Override
public String toString() {
String str = "Polygon: ";
- if (Build.IS_DEBUGGABLE) {
+ if (TelephonyUtils.IS_DEBUGGABLE) {
str += mVertices;
}
return str;
@@ -270,35 +282,53 @@
}
/**
- * 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 (Build.IS_DEBUGGABLE) {
+ if (TelephonyUtils.IS_DEBUGGABLE) {
str += mCenter + ", radius = " + mRadiusMeter;
}
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/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/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 d7d85c2..60ccbf6 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;
@@ -65,6 +64,13 @@
static final boolean DBG = false;
static final boolean VDBG = false; // STOPSHIP if true
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "STATE_",
+ value = {STATE_IN_SERVICE, STATE_OUT_OF_SERVICE, STATE_EMERGENCY_ONLY,
+ STATE_POWER_OFF})
+ public @interface RegState {}
+
/**
* Normal operation condition, the phone is registered
* with an operator either in home network or in roaming.
@@ -83,6 +89,7 @@
/**
* The phone is registered and locked. Only emergency numbers are allowed. {@more}
*/
+ //TODO: This state is not used anymore. It should be deprecated in a future release.
public static final int STATE_EMERGENCY_ONLY =
TelephonyProtoEnums.SERVICE_STATE_EMERGENCY_ONLY; // 2
@@ -221,6 +228,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;
@@ -342,15 +379,15 @@
/**
* Create a new ServiceState from a intent notifier Bundle
*
- * This method is used by PhoneStateIntentReceiver, CellBroadcastReceiver, and maybe by
- * external applications.
+ * This method is used to get ServiceState object from extras upon receiving
+ * {@link Intent#ACTION_SERVICE_STATE}.
*
* @param m Bundle from intent notifier
* @return newly created ServiceState
* @hide
*/
+ @SystemApi
@NonNull
- @UnsupportedAppUsage
public static ServiceState newFromBundle(@NonNull Bundle m) {
ServiceState ret;
ret = new ServiceState();
@@ -501,13 +538,15 @@
}
/**
- * Get current data service state
+ * Get current data registration state.
*
* @see #STATE_IN_SERVICE
* @see #STATE_OUT_OF_SERVICE
* @see #STATE_EMERGENCY_ONLY
* @see #STATE_POWER_OFF
*
+ * @return current data registration state
+ *
* @hide
*/
@UnsupportedAppUsage
@@ -516,6 +555,23 @@
}
/**
+ * Get current data registration state.
+ *
+ * @see #STATE_IN_SERVICE
+ * @see #STATE_OUT_OF_SERVICE
+ * @see #STATE_EMERGENCY_ONLY
+ * @see #STATE_POWER_OFF
+ *
+ * @return current data registration state
+ *
+ * @hide
+ */
+ @SystemApi
+ public @RegState int getDataRegistrationState() {
+ return getDataRegState();
+ }
+
+ /**
* Get the current duplex mode
*
* @see #DUPLEX_MODE_UNKNOWN
@@ -1225,11 +1281,15 @@
/**
* Set intent notifier Bundle based on service state.
*
+ * Put ServiceState object and its fields into bundle which is used by TelephonyRegistry
+ * to broadcast {@link Intent#ACTION_SERVICE_STATE}.
+ *
* @param m intent notifier Bundle
* @hide
+ *
*/
- @UnsupportedAppUsage
- public void fillInNotifierBundle(Bundle m) {
+ @SystemApi
+ public void fillInNotifierBundle(@NonNull Bundle m) {
m.putParcelable(Intent.EXTRA_SERVICE_STATE, this);
// serviceState already consists of below entries.
// for backward compatibility, we continue fill in below entries.
@@ -1408,7 +1468,15 @@
return getRilDataRadioTechnology();
}
- /** @hide */
+ /**
+ * Transform RIL radio technology {@link RilRadioTechnology} value to Network
+ * type {@link NetworkType}.
+ *
+ * @param rat The RIL radio technology {@link RilRadioTechnology}.
+ * @return The network type {@link NetworkType}.
+ *
+ * @hide
+ */
public static int rilRadioTechnologyToNetworkType(@RilRadioTechnology int rat) {
switch(rat) {
case RIL_RADIO_TECHNOLOGY_GPRS:
@@ -1490,7 +1558,15 @@
}
}
- /** @hide */
+ /**
+ * Transform network type {@link NetworkType} value to RIL radio technology
+ * {@link RilRadioTechnology}.
+ *
+ * @param networkType The network type {@link NetworkType}.
+ * @return The RIL radio technology {@link RilRadioTechnology}.
+ *
+ * @hide
+ */
public static int networkTypeToRilRadioTechnology(int networkType) {
switch(networkType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -1691,7 +1767,14 @@
return bearerBitmask;
}
- /** @hide */
+ /**
+ * Convert network type bitmask to bearer bitmask.
+ *
+ * @param networkTypeBitmask The network type bitmask value
+ * @return The bearer bitmask value.
+ *
+ * @hide
+ */
public static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
if (networkTypeBitmask == 0) {
return 0;
@@ -1705,7 +1788,14 @@
return bearerBitmask;
}
- /** @hide */
+ /**
+ * Convert bearer bitmask to network type bitmask.
+ *
+ * @param bearerBitmask The bearer bitmask value.
+ * @return The network type bitmask value.
+ *
+ * @hide
+ */
public static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
if (bearerBitmask == 0) {
return 0;
@@ -1864,9 +1954,18 @@
* Returns a copy of self with location-identifying information removed.
* Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
* is true, clears other info as well.
+ *
+ * @param removeCoarseLocation Whether to also remove coarse location information.
+ * if false, it only clears fine location information such as
+ * NetworkRegistrationInfo's CellIdentity fields; If true, it will
+ * also remove other location information such as operator's MCC
+ * and MNC.
+ * @return the copied ServiceState with location info sanitized.
* @hide
*/
- public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+ @SystemApi
+ @NonNull
+ public ServiceState createLocationInfoSanitizedCopy(boolean removeCoarseLocation) {
ServiceState state = new ServiceState(this);
synchronized (state.mNetworkRegistrationInfos) {
List<NetworkRegistrationInfo> networkRegistrationInfos =
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/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 5b49117..1957170 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -31,8 +31,6 @@
import android.content.pm.PackageManager;
import android.database.CursorWindow;
import android.net.Uri;
-import android.os.Binder;
-import android.os.BaseBundle;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
@@ -2000,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). */
@@ -2399,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;
}
/**
@@ -2656,7 +2684,7 @@
ISms iccISms = getISmsServiceOrThrow();
if (iccISms != null) {
return iccISms.checkSmsShortCodeDestination(getSubscriptionId(),
- ActivityThread.currentPackageName(), destAddress, countryIso);
+ ActivityThread.currentPackageName(), null, destAddress, countryIso);
}
} catch (RemoteException e) {
Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e);
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 257c606..bbde1f4 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -210,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,
@@ -220,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);
}
/**
@@ -234,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);
}
/**
@@ -246,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;
@@ -272,6 +279,7 @@
this.mSubscriptionType = subType;
this.mGroupOwner = groupOwner;
this.mCarrierConfigAccessRules = carrierConfigAccessRules;
+ this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled;
}
/**
@@ -660,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) {
@@ -691,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;
}
@@ -736,6 +754,7 @@
dest.writeStringArray(mHplmns);
dest.writeString(mGroupOwner);
dest.writeTypedArray(mCarrierConfigAccessRules, flags);
+ dest.writeBoolean(mAreUiccApplicationsEnabled);
}
@Override
@@ -778,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
@@ -809,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 25282b2..71ea3a3 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -48,7 +48,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.Process;
@@ -65,6 +64,7 @@
import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.util.HandlerExecutor;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -836,6 +836,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>
*
@@ -907,9 +913,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
@@ -1035,6 +1041,23 @@
*/
public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
if (listener == null) return;
+ addOnSubscriptionsChangedListener(listener.mExecutor, listener);
+ }
+
+ /**
+ * Register for changes to the list of active {@link SubscriptionInfo} records or to the
+ * individual records themselves. When a change occurs the onSubscriptionsChanged method of
+ * the listener will be invoked immediately if there has been a notification. The
+ * onSubscriptionChanged method will also be triggered once initially when calling this
+ * function.
+ *
+ * @param listener an instance of {@link OnSubscriptionsChangedListener} with
+ * onSubscriptionsChanged overridden.
+ * @param executor the executor that will execute callbacks.
+ */
+ public void addOnSubscriptionsChangedListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnSubscriptionsChangedListener listener) {
String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
if (DBG) {
logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
@@ -1046,7 +1069,7 @@
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
- listener.mExecutor);
+ executor);
}
}
@@ -1181,7 +1204,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName());
+ subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1192,12 +1216,17 @@
}
/**
- * Get the active SubscriptionInfo associated with the iccId
+ * Gets an active SubscriptionInfo {@link SubscriptionInfo} associated with the Sim IccId.
+ *
* @param iccId the IccId of SIM card
* @return SubscriptionInfo, maybe null if its not active
+ *
* @hide
*/
- public SubscriptionInfo getActiveSubscriptionInfoForIccIndex(String iccId) {
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Nullable
+ @SystemApi
+ public SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String iccId) {
if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId);
if (iccId == null) {
logd("[getActiveSubscriptionInfoForIccIndex]- null iccid");
@@ -1209,7 +1238,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName());
+ result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1243,7 +1273,7 @@
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1266,7 +1296,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAllSubInfoList(mContext.getOpPackageName());
+ result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1341,7 +1372,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName());
+ activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1391,7 +1423,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName());
+ result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1508,7 +1541,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAllSubInfoCount(mContext.getOpPackageName());
+ result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -1536,7 +1570,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubInfoCount(mContext.getOpPackageName());
+ result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// ignore it
@@ -2273,7 +2308,7 @@
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
resultValue = iSub.getSubscriptionProperty(subId, propKey,
- context.getOpPackageName());
+ context.getOpPackageName(), null);
}
} catch (RemoteException ex) {
// ignore it
@@ -2414,7 +2449,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- return iSub.isActiveSubId(subId, mContext.getOpPackageName());
+ return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
}
@@ -2723,8 +2759,7 @@
/**
* Checks whether the app with the given context is authorized to manage the given subscription
- * according to its metadata. Only supported for embedded subscriptions (if
- * {@code SubscriptionInfo#isEmbedded} returns true).
+ * according to its metadata.
*
* @param info The subscription to check.
* @return whether the app is authorized to manage this subscription per its metadata.
@@ -2737,16 +2772,16 @@
* Checks whether the given app is authorized to manage the given subscription. An app can only
* be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
* {@link android.telephony.SubscriptionInfo} with the access status.
- * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded}
- * returns true).
*
* @param info The subscription to check.
* @param packageName Package name of the app to check.
* @return whether the app is authorized to manage this subscription per its access rules.
* @hide
*/
- public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
- if (info == null || info.getAllAccessRules() == null) {
+ @SystemApi
+ public boolean canManageSubscription(@Nullable SubscriptionInfo info,
+ @Nullable String packageName) {
+ if (info == null || info.getAllAccessRules() == null || packageName == null) {
return false;
}
PackageManager packageManager = mContext.getPackageManager();
@@ -2865,13 +2900,14 @@
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() {
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextFeature = null;
List<SubscriptionInfo> subInfoList = null;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfoList = iSub.getOpportunisticSubscriptions(pkgForDebug);
+ subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
}
} catch (RemoteException ex) {
// ignore it
@@ -3109,7 +3145,8 @@
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) {
Preconditions.checkNotNull(groupUuid, "groupUuid can't be null");
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextFeature = null;
if (VDBG) {
logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid);
}
@@ -3118,7 +3155,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getSubscriptionsInGroup(groupUuid, pkgForDebug);
+ result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
} else {
if (!isSystemProcess()) {
throw new IllegalStateException("telephony service is null.");
@@ -3241,6 +3278,34 @@
}
/**
+ * Set uicc applications being enabled or disabled.
+ * The value will be remembered on the subscription and will be applied whenever it's present.
+ * If the subscription in currently present, it will also apply the setting to modem
+ * immediately.
+ *
+ * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+ *
+ * @param enabled whether uicc applications are enabled or disabled.
+ * @param subscriptionId which subscription to operate on.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setUiccApplicationsEnabled(boolean enabled, int subscriptionId) {
+ if (VDBG) {
+ logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled);
+ }
+ try {
+ ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ if (iSub != null) {
+ iSub.setUiccApplicationsEnabled(enabled, subscriptionId);
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+ }
+
+ /**
* Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM.
*
* Physical SIM refers non-euicc, or aka non-programmable SIM.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fd3ec73..cfb8fb4 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
@@ -364,6 +379,10 @@
return ActivityThread.currentOpPackageName();
}
+ private String getFeatureId() {
+ return null;
+ }
+
private boolean isSystemProcess() {
return Process.myUid() == Process.SYSTEM_UID;
}
@@ -379,7 +398,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")) {
@@ -445,8 +464,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());
}
/**
@@ -733,8 +751,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";
/**
@@ -753,42 +773,6 @@
public static final String EXTRA_PRECISE_DISCONNECT_CAUSE = "precise_disconnect_cause";
/**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an String containing the data APN type.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String name)}.
- *
- * @hide
- */
- public static final String EXTRA_DATA_APN_TYPE = PhoneConstants.DATA_APN_TYPE_KEY;
-
- /**
- * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
- * for an String containing the data APN.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String name)}.
- *
- * @hide
- */
- 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;
-
- /**
* Broadcast intent action for letting the default dialer to know to show voicemail
* notification.
*
@@ -1449,6 +1433,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
@@ -1487,7 +1491,8 @@
if (telephony == null) return null;
try {
- return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName());
+ return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1528,7 +1533,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getDeviceId(mContext.getOpPackageName());
+ return telephony.getDeviceIdWithFeature(mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1572,7 +1578,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName());
+ return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1630,7 +1637,7 @@
if (telephony == null) return null;
try {
- return telephony.getImeiForSlot(slotIndex, getOpPackageName());
+ return telephony.getImeiForSlot(slotIndex, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1724,7 +1731,7 @@
if (telephony == null) return null;
try {
- String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName());
+ String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName(), getFeatureId());
if (TextUtils.isEmpty(meid)) {
Log.d(TAG, "getMeid: return null because MEID is not available");
return null;
@@ -1825,7 +1832,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName());
+ String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName(),
+ null);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Rlog.v(TAG, "Nai = " + nai);
}
@@ -1858,7 +1866,7 @@
return null;
}
- Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName());
+ Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName(), null);
if (bundle == null || bundle.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
return null;
@@ -1946,7 +1954,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getNeighboringCellInfo(mContext.getOpPackageName());
+ return telephony.getNeighboringCellInfo(mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2051,12 +2060,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() {
@@ -2068,9 +2075,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;
}
@@ -2174,7 +2181,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
@@ -2192,8 +2199,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);
@@ -2245,7 +2252,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(), "");
}
/**
@@ -2289,7 +2296,7 @@
**/
@UnsupportedAppUsage
public String getNetworkOperatorForPhone(int phoneId) {
- return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
+ return getTelephonyProperty(phoneId, TelephonyProperties.operator_numeric(), "");
}
@@ -2353,8 +2360,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);
}
/**
@@ -2377,7 +2383,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return "";
return telephony.getNetworkCountryIsoForPhone(getPhoneId(),
- null /* no permission check */);
+ null /* no permission check */, null);
} catch (RemoteException ex) {
return "";
}
@@ -2417,7 +2423,8 @@
ITelephony telephony = getITelephony();
if (telephony == null) return "";
- return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName());
+ return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return "";
}
@@ -2549,7 +2556,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2613,7 +2621,8 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2649,7 +2658,8 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2844,6 +2854,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
@@ -3049,7 +3077,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;
@@ -3057,7 +3085,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
@@ -3091,7 +3119,7 @@
* @hide
*/
@SystemApi
- public int getSimCardState() {
+ public @SimState int getSimCardState() {
int simState = getSimState();
return getSimCardStateFromSimState(simState);
}
@@ -3111,7 +3139,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);
}
@@ -3121,7 +3149,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:
@@ -3161,7 +3189,7 @@
* @hide
*/
@SystemApi
- public int getSimApplicationState() {
+ public @SimState int getSimApplicationState() {
int simState = getSimStateIncludingLoaded();
return getSimApplicationStateFromSimState(simState);
}
@@ -3184,7 +3212,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);
@@ -3195,7 +3223,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:
@@ -3252,7 +3280,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;
@@ -3342,8 +3370,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(), "");
}
/**
@@ -3380,8 +3407,7 @@
*/
@UnsupportedAppUsage
public String getSimOperatorNameForPhone(int phoneId) {
- return getTelephonyProperty(phoneId,
- TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");
+ return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_alpha(), "");
}
/**
@@ -3413,8 +3439,7 @@
*/
@UnsupportedAppUsage
public String getSimCountryIsoForPhone(int phoneId) {
- return getTelephonyProperty(phoneId,
- TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
+ return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_iso_country(), "");
}
/**
@@ -3477,7 +3502,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName());
+ return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3521,7 +3547,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
- return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName());
+ return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
@@ -3749,7 +3776,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName());
+ return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3916,7 +3944,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName());
+ return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3939,7 +3968,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName());
+ return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3989,7 +4019,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName());
+ number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4000,7 +4031,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName());
+ return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName(),
+ null);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4079,7 +4111,7 @@
ITelephony telephony = getITelephony();
if (telephony != null)
alphaTag = telephony.getLine1AlphaTagForDisplay(subId,
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4090,7 +4122,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName());
+ return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4119,7 +4152,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName());
+ return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4174,7 +4208,7 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getMsisdnForSubscriber(subId, getOpPackageName());
+ return info.getMsisdnForSubscriber(subId, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4208,7 +4242,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName());
+ return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4332,8 +4367,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony
- .getVisualVoicemailPackageName(mContext.getOpPackageName(), getSubId());
+ return telephony.getVisualVoicemailPackageName(mContext.getOpPackageName(),
+ getFeatureId(), getSubId());
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -4769,7 +4804,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return 0;
- return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName());
+ return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -4805,7 +4841,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName());
+ return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -5059,6 +5096,7 @@
DATA_CONNECTING,
DATA_CONNECTED,
DATA_SUSPENDED,
+ DATA_DISCONNECTING,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DataState{}
@@ -5075,6 +5113,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
@@ -5084,14 +5128,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;
@@ -5112,6 +5163,7 @@
case DATA_CONNECTING: return "CONNECTING";
case DATA_CONNECTED: return "CONNECTED";
case DATA_SUSPENDED: return "SUSPENDED";
+ case DATA_DISCONNECTING: return "DISCONNECTING";
}
return "UNKNOWN(" + state + ")";
}
@@ -5186,7 +5238,7 @@
} else if (listener.mSubId != null) {
subId = listener.mSubId;
}
- registry.listenForSubscriber(subId, getOpPackageName(),
+ registry.listenForSubscriber(subId, getOpPackageName(), getFeatureId(),
listener.callback, events, notifyNow);
} else {
Rlog.w(TAG, "telephony registry not ready.");
@@ -5216,7 +5268,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return -1;
- return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5251,7 +5304,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return -1;
- return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5282,7 +5336,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return null;
@@ -5374,8 +5429,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getAllCellInfo(
- getOpPackageName());
+ return telephony.getAllCellInfo(getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -5475,7 +5529,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- }, getOpPackageName());
+ }, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
}
}
@@ -5526,7 +5580,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- }, getOpPackageName(), workSource);
+ }, getOpPackageName(), getFeatureId(), workSource);
} catch (RemoteException ex) {
}
}
@@ -6424,74 +6478,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
@@ -6583,7 +6577,7 @@
}
/**
- * Gets a per-phone telephony property.
+ * Gets a per-phone telephony property from a property name.
*
* @hide
*/
@@ -6601,6 +6595,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
@@ -6793,7 +6796,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName());
+ return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -6827,7 +6831,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return -1;
return telephony.setForbiddenPlmns(
- getSubId(), APPTYPE_USIM, fplmns, getOpPackageName());
+ getSubId(), APPTYPE_USIM, fplmns, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
Rlog.e(TAG, "setForbiddenPlmns RemoteException: " + ex.getMessage());
} catch (NullPointerException ex) {
@@ -6848,7 +6852,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return new String[0];
- return telephony.getPcscfAddress(apnType, getOpPackageName());
+ return telephony.getPcscfAddress(apnType, getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
return new String[0];
}
@@ -7359,7 +7363,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName());
+ return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getAvailableNetworks RemoteException", ex);
@@ -7414,7 +7419,7 @@
}
}
return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback,
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
}
/**
@@ -7626,12 +7631,12 @@
/**
* Check whether DUN APN is required for tethering.
* <p>
- * Requires Permission: READ_PRIVILEGED_PHONE_STATE.
+ * Requires Permission: MODIFY_PHONE_STATE.
*
* @return {@code true} if DUN APN is required for tethering.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
public boolean isTetheringApnRequired() {
return isTetheringApnRequired(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
@@ -8086,7 +8091,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isRadioOn(getOpPackageName());
+ return telephony.isRadioOnWithFeature(getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isRadioOn", e);
}
@@ -8399,7 +8404,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName());
+ return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -8757,7 +8763,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isVideoCallingEnabled(getOpPackageName());
+ return telephony.isVideoCallingEnabled(getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e);
}
@@ -8773,7 +8779,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName());
+ return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#canChangeDtmfToneLength", e);
@@ -8792,7 +8799,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isWorldPhone(mSubId, getOpPackageName());
+ return telephony.isWorldPhone(mSubId, getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isWorldPhone", e);
@@ -8977,7 +8984,7 @@
}
/**
- * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
+ * Set TelephonyProperties.icc_operator_numeric for the default phone.
*
* @hide
*/
@@ -8987,18 +8994,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
*/
@@ -9008,18 +9018,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
*/
@@ -9029,18 +9042,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
*/
@@ -9050,14 +9066,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);
+ }
}
/**
@@ -9162,7 +9181,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);
+ }
}
/**
@@ -9185,8 +9208,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;
@@ -9203,7 +9226,7 @@
if (version != null && !version.isEmpty()) {
setBasebandVersionForPhone(phoneId, version);
}
- return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_BASEBAND_VERSION, "");
+ return getTelephonyProperty(phoneId, TelephonyProperties.baseband_version(), "");
}
/**
@@ -9229,8 +9252,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);
}
}
@@ -9259,8 +9283,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;
@@ -9290,8 +9314,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;
@@ -9321,8 +9344,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;
@@ -9362,7 +9384,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);
}
}
@@ -9384,7 +9408,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);
+ }
}
/**
@@ -9406,8 +9434,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);
}
}
@@ -9434,9 +9463,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);
}
}
@@ -9495,7 +9525,7 @@
ITelephony service = getITelephony();
if (service != null) {
retval = service.getSubIdForPhoneAccountHandle(
- phoneAccountHandle, mContext.getOpPackageName());
+ phoneAccountHandle, mContext.getOpPackageName(), null);
}
} catch (RemoteException ex) {
Log.e(TAG, "getSubscriptionId RemoteException", ex);
@@ -9633,7 +9663,8 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getServiceStateForSubscriber(subId, getOpPackageName());
+ return service.getServiceStateForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
@@ -10373,7 +10404,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getClientRequestStats(getOpPackageName(), subId);
+ return service.getClientRequestStats(getOpPackageName(), getFeatureId(), subId);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getClientRequestStats", e);
@@ -10426,7 +10457,8 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isManualNetworkSelectionAllowed() {
try {
ITelephony telephony = getITelephony();
@@ -10661,7 +10693,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getNumberOfModemsWithSimultaneousDataConnections(
- getSubId(), getOpPackageName());
+ getSubId(), getOpPackageName(), getFeatureId());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -11017,7 +11049,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getEmergencyNumberList(mContext.getOpPackageName());
+ return telephony.getEmergencyNumberList(mContext.getOpPackageName(),
+ null);
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -11072,7 +11105,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
emergencyNumberList = telephony.getEmergencyNumberList(
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), null);
if (emergencyNumberList != null) {
for (Integer subscriptionId : emergencyNumberList.keySet()) {
List<EmergencyNumber> numberList = emergencyNumberList.get(subscriptionId);
@@ -11192,7 +11225,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 {}
/**
@@ -11210,6 +11245,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 = {
@@ -11217,7 +11262,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 {}
/**
@@ -11246,6 +11297,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
@@ -11277,7 +11358,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);
@@ -11326,12 +11411,14 @@
android.Manifest.permission.READ_PHONE_STATE
})
public int getPreferredOpportunisticDataSubscription() {
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String packageName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String featureId = null;
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
try {
IOns iOpportunisticNetworkService = getIOns();
if (iOpportunisticNetworkService != null) {
- subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug);
+ subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(
+ packageName, featureId);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getPreferredDataSubscriptionId RemoteException", ex);
@@ -11371,9 +11458,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);
@@ -11455,7 +11545,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName());
+ return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName(),
+ null);
}
} catch (RemoteException ex) {
Log.e(TAG, "enableModem RemoteException", ex);
@@ -11560,7 +11651,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isMultiSimSupported(getOpPackageName());
+ return service.isMultiSimSupported(getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "isMultiSimSupported RemoteException", e);
@@ -11612,7 +11703,7 @@
ITelephony service = getITelephony();
if (service != null) {
return service.doesSwitchMultiSimConfigTriggerReboot(getSubId(),
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "doesSwitchMultiSimConfigTriggerReboot RemoteException", e);
@@ -11646,6 +11737,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/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 9ff8515..6a473a72 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -200,13 +200,14 @@
*/
public NetworkScan requestNetworkScan(int subId,
NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
- String callingPackage) {
+ String callingPackage, String callingFeatureId) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
synchronized (mScanInfo) {
int scanId = telephony.requestNetworkScan(
- subId, request, mMessenger, new Binder(), callingPackage);
+ subId, request, mMessenger, new Binder(), callingPackage,
+ callingFeatureId);
if (scanId == INVALID_SCAN_ID) {
Rlog.e(TAG, "Failed to initiate network scan");
return null;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 034fc22..dbfb6a2 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1056,6 +1056,11 @@
}
/** @hide */
+ public boolean isEmergencyApn() {
+ return hasApnType(TYPE_EMERGENCY);
+ }
+
+ /** @hide */
public boolean canHandleType(@ApnType int type) {
if (!mCarrierEnabled) {
return false;
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/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 4fc6a19..cfc803c 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -17,7 +17,6 @@
package com.android.ims;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.RemoteException;
import android.telephony.Rlog;
@@ -26,6 +25,8 @@
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
+import com.android.internal.telephony.util.HandlerExecutor;
+
import java.util.concurrent.Executor;
/**
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 4e79660..76ebc0f 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -23,9 +23,13 @@
*/
interface ICarrierConfigLoader {
+ /** @deprecated Use {@link #getConfigForSubIdWithFeature(int, String, String) instead */
@UnsupportedAppUsage
PersistableBundle getConfigForSubId(int subId, String callingPackage);
+ PersistableBundle getConfigForSubIdWithFeature(int subId, String callingPackage,
+ String callingFeatureId);
+
void overrideConfig(int subId, in PersistableBundle overrides, boolean persistent);
void notifyConfigChangedForSubId(int subId);
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 2c48b65..76b6951 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -83,7 +83,7 @@
* subscription id
*
*/
- int getPreferredDataSubscriptionId(String callingPackage);
+ int getPreferredDataSubscriptionId(String callingPackage, String callingFeatureId);
/**
* Update availability of a list of networks in the current location.
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 5b509b7..28ef235 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -24,113 +24,128 @@
*/
interface IPhoneSubInfo {
+ /** @deprecated Use {@link #getDeviceIdWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ String getDeviceId(String callingPackage);
+
/**
* Retrieves the unique device ID, e.g., IMEI for GSM phones.
*/
- String getDeviceId(String callingPackage);
+ String getDeviceIdWithFeature(String callingPackage, String callingFeatureId);
/**
* Retrieves the unique Network Access ID
*/
- String getNaiForSubscriber(int subId, String callingPackage);
+ String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the unique device ID of a phone for the device, e.g., IMEI
* for GSM phones.
*/
- String getDeviceIdForPhone(int phoneId, String callingPackage);
+ String getDeviceIdForPhone(int phoneId, String callingPackage, String callingFeatureId);
/**
* Retrieves the IMEI.
*/
- String getImeiForSubscriber(int subId, String callingPackage);
+ String getImeiForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the software version number for the device, e.g., IMEI/SV
* for GSM phones.
*/
- String getDeviceSvn(String callingPackage);
+ String getDeviceSvn(String callingPackage, String callingFeatureId);
/**
* Retrieves the software version number of a subId for the device, e.g., IMEI/SV
* for GSM phones.
*/
- String getDeviceSvnUsingSubId(int subId, String callingPackage);
+ String getDeviceSvnUsingSubId(int subId, String callingPackage, String callingFeatureId);
- /**
- * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
- */
+ /** @deprecated Use {@link #getSubscriberIdWithFeature(String, String) instead */
@UnsupportedAppUsage
String getSubscriberId(String callingPackage);
/**
+ * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
+ */
+ String getSubscriberIdWithFeature(String callingPackage, String callingComponenId);
+
+ /**
* Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
*/
- String getSubscriberIdForSubscriber(int subId, String callingPackage);
+ String getSubscriberIdForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the Group Identifier Level1 for GSM phones of a subId.
*/
- String getGroupIdLevel1ForSubscriber(int subId, String callingPackage);
+ String getGroupIdLevel1ForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
- /**
- * Retrieves the serial number of the ICC, if applicable.
- */
+ /** @deprecared Use {@link getIccSerialNumberWithFeature(String, String)} instead */
@UnsupportedAppUsage
String getIccSerialNumber(String callingPackage);
/**
+ * Retrieves the serial number of the ICC, if applicable.
+ */
+ String getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId);
+
+ /**
* Retrieves the serial number of a given subId.
*/
- String getIccSerialNumberForSubscriber(int subId, String callingPackage);
+ String getIccSerialNumberForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the phone number string for line 1.
*/
- String getLine1Number(String callingPackage);
+ String getLine1Number(String callingPackage, String callingFeatureId);
/**
* Retrieves the phone number string for line 1 of a subcription.
*/
- String getLine1NumberForSubscriber(int subId, String callingPackage);
+ String getLine1NumberForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier for line 1.
*/
- String getLine1AlphaTag(String callingPackage);
+ String getLine1AlphaTag(String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier for line 1 of a subId.
*/
- String getLine1AlphaTagForSubscriber(int subId, String callingPackage);
+ String getLine1AlphaTagForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves MSISDN Number.
*/
- String getMsisdn(String callingPackage);
+ String getMsisdn(String callingPackage, String callingFeatureId);
/**
* Retrieves the Msisdn of a subId.
*/
- String getMsisdnForSubscriber(int subId, String callingPackage);
+ String getMsisdnForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the voice mail number.
*/
- String getVoiceMailNumber(String callingPackage);
+ String getVoiceMailNumber(String callingPackage, String callingFeatureId);
/**
* Retrieves the voice mail number of a given subId.
*/
- String getVoiceMailNumberForSubscriber(int subId, String callingPackage);
+ String getVoiceMailNumberForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the Carrier information used to encrypt IMSI and IMPI.
*/
ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
- String callingPackage);
+ String callingPackage);
/**
* Stores the Carrier information used to encrypt IMSI and IMPI.
@@ -148,13 +163,14 @@
/**
* Retrieves the alpha identifier associated with the voice mail number.
*/
- String getVoiceMailAlphaTag(String callingPackage);
+ String getVoiceMailAlphaTag(String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier associated with the voice mail number
* of a subId.
*/
- String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage);
+ String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 91aa3ce..c07a171 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -1,18 +1,18 @@
/*
-** 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;
@@ -22,7 +22,7 @@
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.
*/
@@ -542,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
@@ -573,7 +580,8 @@
*
* @param destAddress the destination address to test for possible short code
*/
- int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso);
+ int checkSmsShortCodeDestination(int subId, String callingApk, String callingFeatureId,
+ String destAddress, String countryIso);
/**
* Gets the SMSC address from (U)SIM.
@@ -593,4 +601,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 d9d4b60..ddd3457 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -186,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();
}
@@ -197,8 +202,8 @@
}
@Override
- public int checkSmsShortCodeDestination(
- int subid, String callingApk, String destAddress, String countryIso) {
+ public int checkSmsShortCodeDestination(int subid, String callingPackage,
+ String callingFeatureId, String destAddress, String countryIso) {
throw new UnsupportedOperationException();
}
@@ -212,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/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 92aab4b..cc02a40 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -23,47 +23,56 @@
interface ISub {
/**
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return a list of all subscriptions in the database, this includes
* all subscriptions that have been seen.
*/
- List<SubscriptionInfo> getAllSubInfoList(String callingPackage);
+ List<SubscriptionInfo> getAllSubInfoList(String callingPackage, String callingFeatureId);
/**
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return the count of all subscriptions in the database, this includes
* all subscriptions that have been seen.
*/
- int getAllSubInfoCount(String callingPackage);
+ int getAllSubInfoCount(String callingPackage, String callingFeatureId);
/**
* Get the active SubscriptionInfo with the subId key
* @param subId The unique SubscriptionInfo key in database
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Get the active SubscriptionInfo associated with the iccId
* @param iccId the IccId of SIM card
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage,
+ String callingFeatureId);
/**
* Get the active SubscriptionInfo associated with the slotIndex
* @param slotIndex the slot which the subscription is inserted
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, null for Remote-SIMs or non-active slotIndex.
*/
- SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage,
+ String callingFeatureId);
/**
* Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
* by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
@@ -80,13 +89,15 @@
* </li>
* </ul>
*/
- List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage);
+ List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage,
+ String callingFeatureId);
/**
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the number of active subscriptions
*/
- int getActiveSubInfoCount(String callingPackage);
+ int getActiveSubInfoCount(String callingPackage, String callingFeatureId);
/**
* @return the maximum number of subscriptions this device will support at any one time.
@@ -96,7 +107,8 @@
/**
* @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
*/
- List<SubscriptionInfo> getAvailableSubscriptionInfoList(String callingPackage);
+ List<SubscriptionInfo> getAvailableSubscriptionInfoList(String callingPackage,
+ String callingFeatureId);
/**
* @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
@@ -225,7 +237,8 @@
* Return opportunistic subscriptions that can be visible to the caller.
* @return the list of opportunistic subscription info. If none exists, an empty list.
*/
- List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage);
+ List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage,
+ String callingFeatureId);
void removeSubscriptionsFromGroup(in int[] subIdList, in ParcelUuid groupUuid,
String callingPackage);
@@ -233,7 +246,8 @@
void addSubscriptionsIntoGroup(in int[] subIdList, in ParcelUuid groupUuid,
String callingPackage);
- List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage);
+ List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage,
+ String callingFeatureId);
int getSlotIndex(int subId);
@@ -265,7 +279,8 @@
int setSubscriptionProperty(int subId, String propKey, String propValue);
- String getSubscriptionProperty(int subId, String propKey, String callingPackage);
+ String getSubscriptionProperty(int subId, String propKey, String callingPackage,
+ String callingFeatureId);
boolean setSubscriptionEnabled(boolean enable, int subId);
@@ -278,11 +293,13 @@
*/
int getSimStateForSlotIndex(int slotIndex);
- boolean isActiveSubId(int subId, String callingPackage);
+ boolean isActiveSubId(int subId, String callingPackage, String callingFeatureId);
boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow);
int getActiveDataSubscriptionId();
boolean canDisablePhysicalSubscription();
+
+ int setUiccApplicationsEnabled(boolean enabled, int subscriptionId);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 3264c751..97b24ae 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -89,21 +89,32 @@
@UnsupportedAppUsage
void call(String callingPackage, String number);
+ /** @deprecated Use {@link #isRadioOnWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ boolean isRadioOn(String callingPackage);
+
/**
* Check to see if the radio is on or not.
* @param callingPackage the name of the package making the call.
+ * @param callingFeatureId The feature in the package.
* @return returns true if the radio is on.
*/
- boolean isRadioOn(String callingPackage);
+ boolean isRadioOnWithFeature(String callingPackage, String callingFeatureId);
+
+ /**
+ * @deprecated Use {@link #isRadioOnForSubscriberWithFeature(int, String, String) instead
+ */
+ @UnsupportedAppUsage
+ boolean isRadioOnForSubscriber(int subId, String callingPackage);
/**
* Check to see if the radio is on or not on particular subId.
* @param subId user preferred subId.
* @param callingPackage the name of the package making the call.
+ * @param callingFeatureId The feature in the package.
* @return returns true if the radio is on.
*/
- @UnsupportedAppUsage
- boolean isRadioOnForSubscriber(int subId, String callingPackage);
+ boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId);
/**
* Supply a pin to unlock the SIM. Blocks until a result is determined.
@@ -294,19 +305,19 @@
*/
boolean isDataConnectivityPossible(int subId);
- Bundle getCellLocation(String callingPkg);
+ Bundle getCellLocation(String callingPkg, String callingFeatureId);
/**
* Returns the ISO country code equivalent of the current registered
* operator's MCC (Mobile Country Code).
* @see android.telephony.TelephonyManager#getNetworkCountryIso
*/
- String getNetworkCountryIsoForPhone(int phoneId, String callingPkg);
+ String getNetworkCountryIsoForPhone(int phoneId, String callingPkg, String callingFeatureId);
/**
* Returns the neighboring cell information of the device.
*/
- List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
+ List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg, String callingFeatureId);
@UnsupportedAppUsage
int getCallState();
@@ -370,23 +381,27 @@
/**
* Returns the CDMA ERI icon index to display
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconIndex(String callingPackage);
+ int getCdmaEriIconIndex(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI icon index to display on particular subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage);
+ int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the CDMA ERI icon mode,
* 0 - ON
* 1 - FLASHING
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconMode(String callingPackage);
+ int getCdmaEriIconMode(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI icon mode on particular subId,
@@ -394,21 +409,25 @@
* 1 - FLASHING
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconModeForSubscriber(int subId, String callingPackage);
+ int getCdmaEriIconModeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the CDMA ERI text,
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String getCdmaEriText(String callingPackage);
+ String getCdmaEriText(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI text for particular subId,
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String getCdmaEriTextForSubscriber(int subId, String callingPackage);
+ String getCdmaEriTextForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns true if OTA service provisioning needs to run.
@@ -451,7 +470,8 @@
* @param subId user preferred subId.
* Returns the unread count of voicemails
*/
- int getVoiceMessageCountForSubscriber(int subId, String callingPackage);
+ int getVoiceMessageCountForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns true if current state supports both voice and data
@@ -461,7 +481,7 @@
Bundle getVisualVoicemailSettings(String callingPackage, int subId);
- String getVisualVoicemailPackageName(String callingPackage, int subId);
+ String getVisualVoicemailPackageName(String callingPackage, String callingFeatureId, int subId);
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
@@ -493,29 +513,35 @@
* Returns the network type of a subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getNetworkTypeForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns the network type for data transmission
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getDataNetworkType(String callingPackage);
+ int getDataNetworkType(String callingPackage, String callingFeatureId);
/**
* Returns the data network type of a subId
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getDataNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getDataNetworkTypeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the voice network type of a subId
* @param subId user preferred subId.
- * @param callingPackage package making the call.
+ * @param callingPackage package making the call.getLteOnCdmaMode
+ * @param callingFeatureId The feature in the package.
* Returns the network type
*/
- int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Return true if an ICC card is present
@@ -536,10 +562,11 @@
* the mode may be unknown.
*
* @param callingPackage the name of the calling package
+ * @param callingFeatureId The feature in the package.
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaMode(String callingPackage);
+ int getLteOnCdmaMode(String callingPackage, String callingFeatureId);
/**
* Return if the current radio is LTE on CDMA. This
@@ -547,21 +574,23 @@
* the mode may be unknown.
*
* @param callingPackage the name of the calling package
+ * @param callingFeatureId The feature in the package.
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaModeForSubscriber(int subId, String callingPackage);
+ int getLteOnCdmaModeForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns all observed cell information of the device.
*/
- List<CellInfo> getAllCellInfo(String callingPkg);
+ List<CellInfo> getAllCellInfo(String callingPkg, String callingFeatureId);
/**
* Request a cell information update for the specified subscription,
* reported via the CellInfoCallback.
*/
- void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg);
+ void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg,
+ String callingFeatureId);
/**
* Request a cell information update for the specified subscription,
@@ -569,8 +598,8 @@
*
* @param workSource the requestor to whom the power consumption for this should be attributed.
*/
- void requestCellInfoUpdateWithWorkSource(
- int subId, in ICellInfoCallback cb, in String callingPkg, in WorkSource ws);
+ void requestCellInfoUpdateWithWorkSource(int subId, in ICellInfoCallback cb,
+ in String callingPkg, String callingFeatureId, in WorkSource ws);
/**
* Sets minimum time in milli-seconds between onCellInfoChanged
@@ -798,10 +827,11 @@
* Get the calculated preferred network type.
* Used for device configuration by some CDMA operators.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
*
* @return the calculated preferred network type, defined in RILConstants.java.
*/
- int getCalculatedPreferredNetworkType(String callingPackage);
+ int getCalculatedPreferredNetworkType(String callingPackage, String callingFeatureId);
/*
* Get the preferred network type.
@@ -858,12 +888,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.
@@ -881,9 +912,12 @@
* Perform a radio scan and return the list of avialble networks.
*
* @param subId the id of the subscription.
+ * @param callingPackage the calling package
+ * @param callingFeatureId The feature in the package
* @return CellNetworkScanResult containing status of scan and networks.
*/
- CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage);
+ CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Perform a radio network scan and return the id of this scan.
@@ -893,10 +927,11 @@
* @param messenger Callback messages will be sent using this messenger.
* @param binder the binder object instantiated in TelephonyManager.
* @param callingPackage the calling package
+ * @param callingFeatureId The feature in the package
* @return An id for this scan.
*/
int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
- in IBinder binder, in String callingPackage);
+ in IBinder binder, in String callingPackage, String callingFeatureId);
/**
* Stop an existing radio network scan.
@@ -975,8 +1010,9 @@
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String[] getPcscfAddress(String apnType, String callingPackage);
+ String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId);
/**
* Set IMS registration state
@@ -1066,9 +1102,10 @@
*
* @param subId whose dialing number for line 1 is returned.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the displayed dialing number if set, or null if not set.
*/
- String getLine1NumberForDisplay(int subId, String callingPackage);
+ String getLine1NumberForDisplay(int subId, String callingPackage, String callingFeatureId);
/**
* Returns the displayed alphatag of the dialing number if it was set
@@ -1076,10 +1113,11 @@
*
* @param subId whose alphatag associated with line 1 is returned.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the displayed alphatag of the dialing number if set, or null if
* not set.
*/
- String getLine1AlphaTagForDisplay(int subId, String callingPackage);
+ String getLine1AlphaTagForDisplay(int subId, String callingPackage, String callingFeatureId);
/**
* Return the set of subscriber IDs that should be considered "merged together" for data usage
@@ -1091,7 +1129,7 @@
*
* @hide
*/
- String[] getMergedSubscriberIds(int subId, String callingPackage);
+ String[] getMergedSubscriberIds(int subId, String callingPackage, String callingFeatureId);
/**
* @hide
@@ -1190,26 +1228,29 @@
* Whether video calling has been enabled by the user.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the user has enabled video calling, {@code false} otherwise.
*/
- boolean isVideoCallingEnabled(String callingPackage);
+ boolean isVideoCallingEnabled(String callingPackage, String callingFeatureId);
/**
* Whether the DTMF tone length can be changed.
*
* @param subId The subscription to use.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the DTMF tone length can be changed.
*/
- boolean canChangeDtmfToneLength(int subId, String callingPackage);
+ boolean canChangeDtmfToneLength(int subId, String callingPackage, String callingFeatureId);
/**
* Whether the device is a world phone.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the devices is a world phone.
*/
- boolean isWorldPhone(int subId, String callingPackage);
+ boolean isWorldPhone(int subId, String callingPackage, String callingFeatureId);
/**
* Whether the phone supports TTY mode.
@@ -1251,25 +1292,31 @@
*/
int getImsRegTechnologyForMmTel(int subId);
+ /** @deprecated Use {@link #getDeviceIdWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ String getDeviceId(String callingPackage);
+
/**
* Returns the unique device ID of phone, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceId(String callingPackage);
+ String getDeviceIdWithFeature(String callingPackage, String callingFeatureId);
/**
* Returns the IMEI for the given slot.
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getImeiForSlot(int slotIndex, String callingPackage);
+ String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId);
/**
* Returns the Type Allocation Code from the IMEI for the given slot.
@@ -1283,10 +1330,11 @@
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getMeidForSlot(int slotIndex, String callingPackage);
+ String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId);
/**
* Returns the Manufacturer Code from the MEID for the given slot.
@@ -1300,10 +1348,12 @@
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage);
+ String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage,
+ String callingFeatureId);
/**
* Returns the subscription ID associated with the specified PhoneAccount.
@@ -1314,7 +1364,7 @@
* Returns the subscription ID associated with the specified PhoneAccountHandle.
*/
int getSubIdForPhoneAccountHandle(in PhoneAccountHandle phoneAccountHandle,
- String callingPackage);
+ String callingPackage, String callingFeatureId);
/**
* Returns the PhoneAccountHandle associated with a subscription ID.
@@ -1344,9 +1394,11 @@
* Get the service state on specified subscription
* @param subId Subscription id
* @param callingPackage The package making the call
+ * @param callingFeatureId The feature in the package
* @return Service state on specified subscription.
*/
- ServiceState getServiceStateForSubscriber(int subId, String callingPackage);
+ ServiceState getServiceStateForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the URI for the per-account voicemail ringtone set in Phone settings.
@@ -1596,10 +1648,12 @@
* Get Client request stats which will contain statistical information
* on each request made by client.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
* @param subId Subscription index
* @hide
*/
- List<ClientRequestStats> getClientRequestStats(String callingPackage, int subid);
+ List<ClientRequestStats> getClientRequestStats(String callingPackage, String callingFeatureId,
+ int subid);
/**
* Set SIM card power state.
@@ -1618,7 +1672,8 @@
* @param subId subscription ID used for authentication
* @param appType the icc application type, like {@link #APPTYPE_USIM}
*/
- String[] getForbiddenPlmns(int subId, int appType, String callingPackage);
+ String[] getForbiddenPlmns(int subId, int appType, String callingPackage,
+ String callingFeatureId);
/**
* Set the forbidden PLMN list from the givven app type (ex APPTYPE_USIM) on a particular
@@ -1627,10 +1682,12 @@
* @param subId subId the id of the subscription
* @param appType appType the uicc app type, must be USIM or SIM.
* @param fplmns plmns the Forbiden plmns list that needed to be written to the SIM.
- * @param content callingPackage the op Package name.
+ * @param callingPackage the op Package name.
+ * @param callingFeatureId the feature in the package.
* @return number of fplmns that is successfully written to the SIM
*/
- int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage);
+ int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage,
+ String callingFeatureId);
/**
* Check if phone is in emergency callback mode
@@ -1774,7 +1831,8 @@
* How many modems can have simultaneous data connections.
* @hide
*/
- int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage);
+ int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Return the network selection mode on the subscription with id {@code subId}.
@@ -1790,7 +1848,7 @@
* Return the modem radio power state for slot index.
*
*/
- int getRadioPowerState(int slotIndex, String callingPackage);
+ int getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId);
// IMS specific AIDL commands, see ImsMmTelManager.java
@@ -1920,7 +1978,7 @@
/**
* Return the emergency number list from all the active subscriptions.
*/
- Map getEmergencyNumberList(String callingPackage);
+ Map getEmergencyNumberList(String callingPackage, String callingFeatureId);
/**
* Identify if the number is emergency number, based on all the active subscriptions.
@@ -2020,12 +2078,13 @@
* Returns if the usage of multiple SIM cards at the same time is supported.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the
* functionality is restricted by the carrier.
*/
- int isMultiSimSupported(String callingPackage);
+ int isMultiSimSupported(String callingPackage, String callingFeatureId);
/**
* Switch configs to enable multi-sim or switch back to single-sim
@@ -2037,7 +2096,8 @@
* Get if altering modems configurations will trigger reboot.
* @hide
*/
- boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage);
+ boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Get the mapping from logical slots to physical slots.
@@ -2056,7 +2116,7 @@
*/
boolean isApplicationOnUicc(int subId, int appType);
- boolean isModemEnabledForSlot(int slotIndex, String callingPackage);
+ boolean isModemEnabledForSlot(int slotIndex, String callingPackage, String callingFeatureId);
boolean isDataEnabledForApn(int apnType, int subId, String callingPackage);
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 6e63514..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
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 4421c77..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)
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index dcea9bb..d672642 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -18,11 +18,11 @@
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.telephony.util.TelephonyUtils;
import com.android.internal.telephony.util.XmlUtils;
import dalvik.annotation.compat.UnsupportedAppUsage;
@@ -30,7 +30,7 @@
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 b2c3fc7..48fdca7 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -172,24 +172,6 @@
= "android.intent.action.ANY_DATA_STATE";
/**
- * Broadcast Action: An attempt to establish a data connection has failed.
- * The intent will have the following extra values:</p>
- * <dl>
- * <dt>phoneName</dt><dd>A string version of the phone name.</dd>
- * <dt>state</dt><dd>One of {@code CONNECTED}, {@code CONNECTING}, or {code DISCONNECTED}.</dd>
- * <dt>reason</dt><dd>A string indicating the reason for the failure, if available.</dd>
- * </dl>
- *
- * <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_DATA_CONNECTION_FAILED
- = "android.intent.action.DATA_CONNECTION_FAILED";
-
- /**
* Broadcast Action: The sim card state has changed.
* The intent will have the following extra values:</p>
* <dl>
@@ -225,22 +207,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";
-
- /**
* <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/HandlerExecutor.java b/telephony/java/com/android/internal/telephony/util/HandlerExecutor.java
new file mode 100644
index 0000000..8a25457
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/HandlerExecutor.java
@@ -0,0 +1,47 @@
+/*
+ * 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.os.Handler;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * An adapter {@link Executor} that posts all executed tasks onto the given
+ * {@link Handler}.
+ *
+ * @hide
+ */
+public class HandlerExecutor implements Executor {
+ private final Handler mHandler;
+
+ public HandlerExecutor(@NonNull Handler handler) {
+ if (handler == null) {
+ throw new NullPointerException();
+ }
+ mHandler = handler;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ if (!mHandler.post(command)) {
+ throw new RejectedExecutionException(mHandler + " is shutting down");
+ }
+ }
+}
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
new file mode 100644
index 0000000..61c3829
--- /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/tests/TelephonyCommonTests/AndroidManifest.xml b/tests/TelephonyCommonTests/AndroidManifest.xml
new file mode 100644
index 0000000..63f38c6
--- /dev/null
+++ b/tests/TelephonyCommonTests/AndroidManifest.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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.telephony.tests"
+ android:debuggable="true">
+
+ <application android:label="TelephonyCommonTests"
+ android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <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..4d1115f
--- /dev/null
+++ b/tests/TelephonyCommonTests/jarjar-rules.txt
@@ -0,0 +1,3 @@
+rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
+rule android.telephony.PackageChangeReceiver* com.android.internal.telephony.tests.PackageChangeReceiver@1
+rule com.android.internal.os.BackgroundThread* com.android.internal.telephony.tests.BackgroundThread@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..83fd208
--- /dev/null
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -0,0 +1,291 @@
+/*
+ * 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.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNotNull;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
+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.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+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.net.Uri;
+import android.os.Handler;
+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.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 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
+ };
+
+ private static final Set<String> SCHEMES_FOR_PREFERRED_APP = Arrays.stream(new String[]{
+ "mms",
+ "mmsto",
+ "sms",
+ "smsto"
+ }).collect(Collectors.toSet());
+
+ @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);
+ when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext);
+
+ doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+ .when(mPackageManager)
+ .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
+ doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
+ .when(mPackageManager)
+ .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
+ 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);
+ }
+
+ @Test
+ public void testPackageChanged() throws Exception {
+ setupPackageInfosForCoreApps();
+ SmsApplication.initSmsPackageMonitor(mContext);
+ verify(mContext).createContextAsUser(eq(UserHandle.ALL), anyInt());
+ ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext).registerReceiver(captor.capture(), isNotNull(),
+ isNull(), nullable(Handler.class));
+ BroadcastReceiver smsPackageMonitor = captor.getValue();
+
+ Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
+ packageChangedIntent.setData(
+ Uri.fromParts("package", TEST_COMPONENT_NAME.getPackageName(), null));
+ smsPackageMonitor.onReceive(mContext, packageChangedIntent);
+
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+ verify(mPackageManager, times(SCHEMES_FOR_PREFERRED_APP.size()))
+ .replacePreferredActivity(intentFilterCaptor.capture(),
+ eq(IntentFilter.MATCH_CATEGORY_SCHEME
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL),
+ isNotNull(List.class),
+ eq(new ComponentName(TEST_COMPONENT_NAME.getPackageName(), SEND_TO_NAME)));
+
+ Set<String> capturedSchemes = intentFilterCaptor.getAllValues().stream()
+ .map(intentFilter -> intentFilter.getDataScheme(0))
+ .collect(Collectors.toSet());
+ assertEquals(SCHEMES_FOR_PREFERRED_APP.size(), capturedSchemes.size());
+ assertTrue(SCHEMES_FOR_PREFERRED_APP.containsAll(capturedSchemes));
+ }
+
+ 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/TEST_MAPPING b/tests/net/TEST_MAPPING
new file mode 100644
index 0000000..a7853b6
--- /dev/null
+++ b/tests/net/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "FrameworksNetIntegrationTests"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index ae8285b..a7328ac 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;
@@ -36,6 +38,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -47,25 +50,23 @@
@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 Inet4Address DHCPSERVER = (Inet4Address) address("192.0.2.1");
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 +76,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);
}
@@ -95,6 +95,7 @@
assertNull(lp.getHttpProxy());
assertNull(lp.getTcpBufferSizes());
assertNull(lp.getNat64Prefix());
+ assertNull(lp.getDhcpServerAddress());
assertFalse(lp.isProvisioned());
assertFalse(lp.isIpv4Provisioned());
assertFalse(lp.isIpv6Provisioned());
@@ -121,6 +122,7 @@
lp.setMtu(MTU);
lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
+ lp.setDhcpServerAddress(DHCPSERVER);
lp.setWakeOnLanSupported(true);
return lp;
}
@@ -228,7 +230,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 +245,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 +257,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 +273,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 +351,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 +741,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 +757,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 +768,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 +784,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 +813,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 +846,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 +865,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 +931,56 @@
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);
+
+ source.setDhcpServerAddress((Inet4Address) GATEWAY1);
+
+ final LinkProperties stacked = new LinkProperties();
+ stacked.setInterfaceName("test-stacked");
+ source.addStackedLink(stacked);
+
+ assertParcelSane(source, 16 /* 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
@@ -1064,6 +1097,15 @@
}
@Test
+ public void testDhcpServerAddress() {
+ final LinkProperties lp = makeTestObject();
+ assertEquals(DHCPSERVER, lp.getDhcpServerAddress());
+
+ lp.clear();
+ assertNull(lp.getDhcpServerAddress());
+ }
+
+ @Test
public void testWakeOnLanSupported() {
final LinkProperties lp = makeTestObject();
assertTrue(lp.isWakeOnLanSupported());
diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp
index 7d9b7b7..874bd4b 100644
--- a/tests/net/integration/Android.bp
+++ b/tests/net/integration/Android.bp
@@ -36,6 +36,7 @@
"services.net",
"testables",
],
+ test_suites: ["device-tests"],
use_embedded_native_libs: true,
jni_libs: [
// For mockito extended
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());