diff options
96 files changed, 3885 insertions, 776 deletions
diff --git a/Android.bp b/Android.bp index 35879df4b852..9c33106799f0 100644 --- a/Android.bp +++ b/Android.bp @@ -554,6 +554,7 @@ java_library { "framework-platform-compat-config", // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly. "gps_debug.conf", + "icu4j-platform-compat-config", "libcore-platform-compat-config", "protolog.conf.json.gz", "services-platform-compat-config", diff --git a/StubLibraries.bp b/StubLibraries.bp index 9047df5aba5c..aabf23b9f821 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -332,19 +332,6 @@ java_library_static { "framework-wifi.stubs", "private-stub-annotations-jar", ], - defaults: ["android_defaults_stubs_current"], -} - -java_library_static { - name: "android_stubs_current", - static_libs: ["android_merged_stubs_current"], - defaults: ["android_defaults_stubs_current"], -} - -java_library_static { - name: "android_system_monolith_stubs_current", - srcs: [ ":system-api-stubs-docs" ], - static_libs: [ "private-stub-annotations-jar" ], defaults: [ "android_defaults_stubs_current", "android_stubs_dists_default", @@ -363,6 +350,21 @@ java_library_static { } java_library_static { + name: "android_stubs_current", + static_libs: ["android_merged_stubs_current"], + defaults: ["android_defaults_stubs_current"], +} + +java_library_static { + name: "android_system_monolith_stubs_current", + srcs: [ ":system-api-stubs-docs" ], + static_libs: [ "private-stub-annotations-jar" ], + defaults: [ + "android_defaults_stubs_current", + ], +} + +java_library_static { name: "android_system_merged_stubs_current", srcs: [ ":system-api-stubs-docs-non-updatable" ], static_libs: [ diff --git a/apex/Android.bp b/apex/Android.bp index cabed3b44d41..0a535a8fe9b9 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -112,6 +112,8 @@ java_defaults { ], stubs_source_visibility: ["//visibility:private"], + defaults_visibility: ["//visibility:private"], + // Collates API usages from each module for further analysis. plugins: ["java_api_finder"], @@ -147,141 +149,6 @@ java_defaults { } stubs_defaults { - name: "framework-module-stubs-defaults-publicapi", - args: mainline_framework_stubs_args, - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, - check_api: { - current: { - api_file: "api/current.txt", - removed_api_file: "api/removed.txt", - }, - api_lint: { - enabled: true, - }, - }, - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/public/api", - }, -} - -stubs_defaults { - name: "framework-module-stubs-defaults-systemapi", - args: mainline_framework_stubs_args + priv_apps, - libs: ["framework-annotations-lib"], - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, - check_api: { - current: { - api_file: "api/system-current.txt", - removed_api_file: "api/system-removed.txt", - }, - api_lint: { - enabled: true, - }, - }, - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/system/api", - }, -} - -java_defaults { - name: "framework-module-stubs-lib-defaults-publicapi", - installable: false, - sdk_version: "module_current", - libs: [ "stub-annotations" ], - java_version: "1.8", - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/public", - }, -} - -java_defaults { - name: "framework-module-stubs-lib-defaults-systemapi", - installable: false, - sdk_version: "module_current", - libs: [ "stub-annotations" ], - java_version: "1.8", - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/system", - }, -} - -java_defaults { - name: "framework-module-stubs-lib-defaults-module_libs_api", - installable: false, - sdk_version: "module_current", - libs: [ "stub-annotations" ], - java_version: "1.8", - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/module-lib", - }, -} - -// The defaults for module_libs comes in two parts - defaults for API checks -// and defaults for stub generation. This is because we want the API txt -// files to *only* include the module_libs_api, but the stubs to include -// module_libs_api as well as priv_apps. - -stubs_defaults { - name: "framework-module-api-defaults-module_libs_api", - args: mainline_framework_stubs_args + module_libs, - libs: ["framework-annotations-lib"], - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, - - // Do not generate stubs as they are not needed - generate_stubs: false, - - check_api: { - current: { - api_file: "api/module-lib-current.txt", - removed_api_file: "api/module-lib-removed.txt", - }, - api_lint: { - enabled: true, - }, - }, - dist: { - targets: ["sdk", "win_sdk"], - dir: "apistubs/android/module-lib/api", - }, -} - -stubs_defaults { - name: "framework-module-stubs-defaults-module_libs_api", - args: mainline_framework_stubs_args + module_libs + priv_apps, - libs: ["framework-annotations-lib"], - installable: false, - sdk_version: "module_current", - annotations_enabled: true, - merge_annotations_dirs: [ - "metalava-manual", - ], - filter_packages: framework_packages_to_document, -} - -stubs_defaults { name: "service-module-stubs-srcs-defaults", args: mainline_service_stubs_args, installable: false, diff --git a/apex/extservices/Android.bp b/apex/extservices/Android.bp deleted file mode 100644 index 0c6c4c23dce1..000000000000 --- a/apex/extservices/Android.bp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -apex { - name: "com.android.extservices", - defaults: ["com.android.extservices-defaults"], - manifest: "apex_manifest.json", -} - -apex_defaults { - name: "com.android.extservices-defaults", - updatable: true, - min_sdk_version: "current", - key: "com.android.extservices.key", - certificate: ":com.android.extservices.certificate", - apps: ["ExtServices"], -} - -apex_key { - name: "com.android.extservices.key", - public_key: "com.android.extservices.avbpubkey", - private_key: "com.android.extservices.pem", -} - -android_app_certificate { - name: "com.android.extservices.certificate", - certificate: "com.android.extservices", -} diff --git a/apex/extservices/apex_manifest.json b/apex/extservices/apex_manifest.json deleted file mode 100644 index c0b59cc12311..000000000000 --- a/apex/extservices/apex_manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.extservices", - "version": 300900700 -} diff --git a/apex/extservices/com.android.extservices.avbpubkey b/apex/extservices/com.android.extservices.avbpubkey Binary files differdeleted file mode 100644 index f37d3e4a14d4..000000000000 --- a/apex/extservices/com.android.extservices.avbpubkey +++ /dev/null diff --git a/apex/extservices/com.android.extservices.pem b/apex/extservices/com.android.extservices.pem deleted file mode 100644 index 7bfbd34ff9b9..000000000000 --- a/apex/extservices/com.android.extservices.pem +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEAuYshVDiRkt3tmBhqcWkKOm5GcviKpLbHSPpYQDHGDwS0dqqL -SqAd1/BgT/bVVtUkAciFApPnXn96WhNYCypptyC5FHCxM21uBCGmow+3WermD++w -5dQk4QP2ONPIpG+KzOWBl9SiBud4SpOHDyr0JycBsrXS89Tln9kAsTDuDEFfXL/J -8cX/S3IUwhPV0pAlgUIHdDp0DGFjZaJlEZBZ+HmImriC/AUNUMVb5lfbczXOEZPF -0A9+JzYschfXUxn8nu1N7RN5GDbq+chszx1FMVhuFUheukkd4dLNSDl0O0RlUnD+ -C/xz1ilDzEVZhnMtMnxS9oJ8bA/HUVMfsFnaQbgGmQ0CcxFxnfbYyGXGG1H+b8vA -MTVQi5rZXG2p+VgHIAKVrYmpETVnRPgoMqp18KuGtp5SDngi13G3YEzS7iFbqfYh -6iW2G974nD/Dq0cSire8Oljd9PEaMCMZiP5PTFJp0G/mtw7ROoyZqsSM6rX3XVTo -Y5dBmBMctSJ8rgDMi0ZNvRH+rq/E5+RT6yMAJ7DDbOJzBnQ3IIoGn8NzUT3P1FCB -HYEp1U2N7QNirIQMAuVz3IlHae9N1kl3eGAO6f2CjV7vZmFpDeWw+KSYs71mRkOb -WBgl6D9FFq4u1azrU3AwV0dj3x1eU6yVnKUy1J7ppF/mcR+VzH7ThzTdV7cCAwEA -AQKCAgEApWFU2Mv/PYhg0bPZlLLKsiA+3RWaBo0AfpTd+oIjBpnr/OWweFjVoPcZ -8cyShe4/RPOlUxHgJcO8m/MoA/PO/LLHJWf5GlzMthQEgs1sYVJVtBiydXitUn+E -hUyIR8FAV7et1lZqAXtqJhbvSF7B9u/2vIMCv+GgtuTmkAmL9RKD3Jj6eG1CS84o -oICrkx52v4rKOBgt/icEQMAKFCi1eRti3n3eCqK6JqdzbZIcAcoQnmw34mccy/im -jx+fBuxf1oywa8NyqVmyAehazBVL6lrm7ENwY9zuLK4H2fuUFYu2QFCEsMxZt6da -TgX2cTfSLnDQRfcyzeMWhu9vjHHabjpLNjiCKhIhGyO0rO1rtea8ajZHgM/2sxXq -6gLynW0dlatlxmjANlN9WQPGNdzvcIFJ0TLnI4mlJnWpqCsN9iW1d4ey13WiZUVR -DgtnR60zao+LRCCM4D3cuVLq0DjL2BlHGXnOPK/LpQG1LbI1TroZpgSEHSZlQRzT -ql9txgNqTHxijXuPL2VhhwhW7cqDoO8sLwV3BqDMIH56U0cbUBiSA/G9fKeI/DEG -i7LcrMgrBk+xnuAWoFHuzfBMAdD9i3kYyk+41tOmcza2TNJgxadVYp5woHFvYvS/ -GKaNiRz0XmcijO5Ir0yxgCq21BdkWzo5zVrTFABiKeR7YXiee8kCggEBAOeULWgR -spolJJrACWJspRvKb9FGnbGiYOnCGJoAc751kuXmNxoyWnEwgcjrSEoayNPUfOtz -IgA+twqjgl0Zec2XFPfUcgWUBrrvvUEV4NIH5ibaR7ezHGeovCWs9XoDyzHHvhDr -c6T5kXFZ60rS5h6LGUnE1hkHFJoHuTIBbn9j7eIbri8S71i7HWQ04s4KuQ+Bwbxm -UnkEhbc+zMWHXfXy7rx4/eEZcZwtEybIORcHXYNPGeqMfOlcEMHpKEOi+NvDA6cp -vTaTSwJ6ZBgYh7Tw3bNgRxSknaIhcGwMD0ojStjC5xzXT1Zr2Z3GXwYvOGcq3MeZ -z+V2cx5xuwyp7R0CggEBAM0cKKNZEZwi/1zBPUDMFB4iJoX12BxQX6e5wdlHGXgF -XeZwCnaIxOxMDxH79M5Svmpdu/jkUijI/pRvcE1iohFyIBvTUSDmlAoy4keXqMEQ -M2hA+TwVA3JLmMcV8HKy/MFlwwKJB1JDcoxGjnXsM5UjVTD2jilO7vlJZs3+0ws0 -R7qzRT3ED25QTpZyDYcKE2otc5bzIZG3yAaJtWd3NugWsKpxDgr2RFUGJiHBq72n -48FkSjfgaDTn83zYcPvS0Uykb2ho8G/N+EurstL41n3nQo0I7FLbyptOopDDwsSp -Ndejn08NVAQ+xFAafOyqHkA3Ytpl0QCZDpMBuLdvw+MCggEAOVMt1kgjPRMat4/4 -ArxANtvqyBRB7vnyIYthiaW5ARmbrntJgpuaVdCbIABWGbn9oqpD7gjHDuZ3axPE -roUi6KiQkTSusQDOlbHI2Haw+2znJRD9ldSpoGNdh7oD3htYTk9Sll+ideEthrCq -lRAV1NO8A83M7c8Z43Mr/dvq3XAAL+uIN7DpPL687NRGnJh87QDC039ExR5Ad3b9 -O5xhvwNO46rTtcgVnoJt7ji8IR46oMmQ8cWrGh0nLMkppWyPS98/ZT7ozryxYcCo -TGquFTVWvBOGJO8G8l5ytNxbYI/R9Exy52nJAuyZpvu3BBHmVWt/0Y0asIOcxZmD -owPhZQKCAQAfWAFBzReq05JQe1s/7q/YVwGqEQKgeQvVFsbvzDSxKajK0S5YJNhq -/8iByA4GBZEBsidKhqGjh+uXhVwVB1Ca9+S+O9G3BGV1FYeMxzlLn40rjlpH+zIW -okTLj6e5724+o61kUspioNn9Y77beGf9j3OyUsswttZAFB54tktL+AZKGqEnKjHt -eqo3xWAZ1clXvXBfjfIAUaRok1y8XfRvDSCcO0CZHj8c+x6SpAT5q5FbeVb6KPnj -s9p6ppzFbtb7Llm0C+1KOKCL98YRBWPJw7Bg2w86LkpM53xiQPgfk3gd5uwuaWwA -ZhMb5qBWjjynNY+OrmZ8/+bBQk8XASZfAoIBAFkHOnZOD1JJQ0QvaJ9tuCgHi216 -I8QPMMTdm3ZEDHSYMNwl7ayeseBcmB2zaqBKYz75qcU0SK4lnZkR2wIpbsHZNSVM -J0WpN6r9G4JdnVi11J04RsfSMjCUr/PTVMmPvw8xPHrCxkJmB+d56olSE80I1Jrx -djCv1LtSsT10W7FIcY82/cOi4xxGLOA70lDCf+szofQgVP8WvuOA1YaFw98ca8zc -A401CyNexk24/c3d6C19YW/MppdE0uGMxL/oHsPgwkZAf6LmvF/UF71PsBUEniLc -YFaJl3wn1cPfBBo9L4sZzyP2qokL8YHdg+wW7b4IOsYwbeqceBvqPtcUUPs= ------END RSA PRIVATE KEY----- diff --git a/apex/extservices/com.android.extservices.pk8 b/apex/extservices/com.android.extservices.pk8 Binary files differdeleted file mode 100644 index 59585a212592..000000000000 --- a/apex/extservices/com.android.extservices.pk8 +++ /dev/null diff --git a/apex/extservices/com.android.extservices.x509.pem b/apex/extservices/com.android.extservices.x509.pem deleted file mode 100644 index e0343b81d279..000000000000 --- a/apex/extservices/com.android.extservices.x509.pem +++ /dev/null @@ -1,36 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGLTCCBBWgAwIBAgIUdqdMmx/5OsCP3Ew3/hcr7+1ACHEwDQYJKoZIhvcNAQEL -BQAwgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH -DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy -b2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEiMCAGCSqGSIb3 -DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0yMDAxMTcxMDIxMzZaGA80NzU3 -MTIxMzEwMjEzNlowgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh -MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD -VQQLDAdBbmRyb2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEi -MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBANKaSeLGaFRRt779vAtTfG3t2aQZrWOByUYc7yUN -RdmJqWxU47OL5urYmanWPbz2f972Q9oi8x+8y4ny9SEY3wg0pUbzvKNTXpkxWyG1 -HE2C2zTfzuDDLpDIf2usWynt1wLVhpYC3k+7Yv2vOIK5dKkezh6PfdKmsbDae5DE -d22tTSYZ5KwNpIWrgQle26cRG5sqhAFdkpgGMF00Huz06cjUoTjs2sNSlXTRBOTP -CCy8UoRjBivQZkwHbddfsn+Z22ARPG8JDg/n4mEi8C0T6bJeQeirSPkBCkD6Djgq -7RddJ2eLYZII8l8r6A6x+6cnTkXHaV5g3LUwPvi8XEn9IUuT9WJNRje/vfYLycTQ -kP415CZMxDvsi1Ul4YsbL3enE89ryGMTpVZPogch/36DG5Sye28yISItNUy3urJa -OXbg7mh+MwPd4bQaW4CJk+AUweKaF4aV0SZFT+nCewL4xLdGdy889KazlW98NqtK -hOSxIg1jHkZq48ajuq2A+ns1yDKt1l0f9IYCz3mz/IXInokbkjPvHahJTJ+OMHXO -THD8e5gBzcK841jJk+H3EsIYOHsp66uy2IgEHN+9pAS6vI0xfrXOYuKzuSL3oxcV -FlVTimt4xokMMerdcW4KD+MC5NFEip4DUS4JKCyG0wRI3ffEs9Zcpxi3QSibrjLW -rz+hAgMBAAGjUzBRMB0GA1UdDgQWBBTP2AhZzEUUgtAFlkaMaq+RvY06fDAfBgNV -HSMEGDAWgBTP2AhZzEUUgtAFlkaMaq+RvY06fDAPBgNVHRMBAf8EBTADAQH/MA0G -CSqGSIb3DQEBCwUAA4ICAQCbwtfo37j62Sudmt32PCfRN/r5ZNDNNA2JhR8uDUmX -xXfF5YfDvSKsNLiQKcDagu6a+0C+QnzXHXCBlXZFrTJ8NAVMlmqdHGwoFoYMfJZH -R1lCTidyFMoMLJ8GRGPJjzDkKnOeAqKMCtKvXoH2r12+JB2/ov4ooLREu/wPkEXT -OymkyWNP5XLQTKWqfEQyXXFpuwZ+m35Wkr0Fm92mZeJpVeIZPK7M7aK3zyoj7XJP -YLMsR/AQs8OULdpfNMddAuN3ndlYu03LZlsF6LG5bduaDDcESJ5hdJrgBa/NBKRU -IbS+q/6WAjYKMNRT/fPGew4wUzlWKi1Ihdk79oaqKKijE1b2JSJD1/SEYiBf+JPE -bXobUrMbBwFpdhT+YLMF9FsuPQKsUIONaWiO4QcQoY/rQwGxPP6fV8ZbBrUWJewj -MpSdU9foZNa/TmOAgfS/JxH+nXnG4+H1m8mdNBsxvsYmF2ZuGb/jdEeA2cuHIJDZ -FJeWwCFxzlCGZJaUsxsnZByADBuufUVaO/9gGs0YQC/JP1i9hK4DyZdKwZpXdLi2 -Nw27Qma4WEIZnMb6Rgk1nTV+7ALcOSIhGgFOOeDTuCGfnEcz2coai5fbD/K6Q7Xu -IRNyxHQjheZPdei2x912Ex/KqKGfaFaZJxrvCSKdhzxcTFIsO4JuZs+SDpRTKcI7 -Cw== ------END CERTIFICATE----- diff --git a/apex/extservices/testing/test_manifest.json b/apex/extservices/testing/test_manifest.json deleted file mode 100644 index 23a50e37bdd3..000000000000 --- a/apex/extservices/testing/test_manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "com.android.extservices", - "version": 2147483647 -} diff --git a/api/Android.bp b/api/Android.bp index 9f99b78c11c4..4d7f58edd870 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -16,25 +16,6 @@ package { default_visibility: ["//visibility:private"], } -// *-current.txt files for use by modules in other directories like cts -filegroup { - name: "frameworks-base-api-current.txt", - srcs: ["current.txt"], - visibility: ["//visibility:public"], -} - -filegroup { - name: "frameworks-base-api-system-current.txt", - srcs: ["system-current.txt"], - visibility: ["//visibility:public"], -} - -filegroup { - name: "frameworks-base-api-system-removed.txt", - srcs: ["system-removed.txt"], - visibility: ["//visibility:public"], -} - genrule { name: "current-api-xml", tools: ["metalava"], @@ -45,7 +26,7 @@ genrule { } genrule { - name: "frameworks-base-api-current-merged.txt", + name: "frameworks-base-api-current.txt", srcs: [ ":conscrypt.module.public.api{.public.api.txt}", ":framework-media{.public.api.txt}", @@ -72,10 +53,11 @@ genrule { dest: "android.txt", }, ], + visibility: ["//visibility:public"], } genrule { - name: "frameworks-base-api-removed-merged.txt", + name: "frameworks-base-api-removed.txt", srcs: [ ":conscrypt.module.public.api{.public.removed-api.txt}", ":framework-media{.public.removed-api.txt}", @@ -100,7 +82,7 @@ genrule { } genrule { - name: "frameworks-base-api-system-current-merged.txt", + name: "frameworks-base-api-system-current.txt", srcs: [ ":framework-media{.system.api.txt}", ":framework-mediaprovider{.system.api.txt}", @@ -126,10 +108,11 @@ genrule { dest: "android.txt", }, ], + visibility: ["//visibility:public"], } genrule { - name: "frameworks-base-api-system-removed-merged.txt", + name: "frameworks-base-api-system-removed.txt", srcs: [ ":framework-media{.system.removed-api.txt}", ":framework-mediaprovider{.system.removed-api.txt}", @@ -150,10 +133,11 @@ genrule { dest: "system-removed.txt", }, ], + visibility: ["//visibility:public"], } genrule { - name: "frameworks-base-api-module-lib-current-merged.txt", + name: "frameworks-base-api-module-lib-current.txt", srcs: [ ":framework-media{.module-lib.api.txt}", ":framework-mediaprovider{.module-lib.api.txt}", @@ -182,7 +166,7 @@ genrule { } genrule { - name: "frameworks-base-api-module-lib-removed-merged.txt", + name: "frameworks-base-api-module-lib-removed.txt", srcs: [ ":framework-media{.module-lib.removed-api.txt}", ":framework-mediaprovider{.module-lib.removed-api.txt}", @@ -208,8 +192,8 @@ genrule { genrule { name: "combined-removed-dex", srcs: [ - ":frameworks-base-api-removed-merged.txt", - ":frameworks-base-api-system-removed-merged.txt", + ":frameworks-base-api-removed.txt", + ":frameworks-base-api-system-removed.txt", ":android.car-stubs-docs{.removed-api.txt}", ":android.car-system-stubs-docs{.removed-api.txt}", ], diff --git a/api/current.txt b/api/current.txt index c64fbce56d21..ee3f81ee38c6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -48333,7 +48333,9 @@ package android.telephony { method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String); method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String); method public boolean isConcurrentVoiceAndDataSupported(); + method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isDataConnectionAllowed(); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled(); + method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabledForReason(int); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled(); method public boolean isEmergencyNumber(@NonNull String); method public boolean isHearingAidCompatibilitySupported(); @@ -48354,7 +48356,8 @@ package android.telephony { method @Deprecated public String sendEnvelopeWithStatus(String); method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>); method public boolean setLine1NumberForDisplay(String, String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic(); @@ -48402,6 +48405,10 @@ package android.telephony { 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_ENABLED_REASON_CARRIER = 2; // 0x2 + field public static final int DATA_ENABLED_REASON_POLICY = 1; // 0x1 + field public static final int DATA_ENABLED_REASON_THERMAL = 3; // 0x3 + field public static final int DATA_ENABLED_REASON_USER = 0; // 0x0 field public static final int DATA_SUSPENDED = 3; // 0x3 field public static final int DATA_UNKNOWN = -1; // 0xffffffff field public static final String EXTRA_ACTIVE_SIM_SUPPORTED_COUNT = "android.telephony.extra.ACTIVE_SIM_SUPPORTED_COUNT"; diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt deleted file mode 100644 index 3b32b535f0bc..000000000000 --- a/api/module-lib-current.txt +++ /dev/null @@ -1,93 +0,0 @@ -// Signature format: 2.0 -package android.net { - - public final class TetheringConstants { - field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType"; - field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback"; - field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType"; - field public static final String EXTRA_RUN_PROVISION = "extraRunProvision"; - field public static final String EXTRA_SET_ALARM = "extraSetAlarm"; - } - - public class TetheringManager { - ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>); - method public int getLastTetherError(@NonNull String); - method @NonNull public String[] getTetherableBluetoothRegexs(); - method @NonNull public String[] getTetherableIfaces(); - method @NonNull public String[] getTetherableUsbRegexs(); - method @NonNull public String[] getTetherableWifiRegexs(); - method @NonNull public String[] getTetheredIfaces(); - method @NonNull public String[] getTetheringErroredIfaces(); - method public boolean isTetheringSupported(); - method public boolean isTetheringSupported(@NonNull String); - method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean); - method @Deprecated public int setUsbTethering(boolean); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); - method @Deprecated public int tether(@NonNull String); - method @Deprecated public int untether(@NonNull String); - } - - public static interface TetheringManager.TetheringEventCallback { - method public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps); - } - - public static class TetheringManager.TetheringInterfaceRegexps { - method @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs(); - method @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs(); - method @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs(); - } - -} - -package android.os { - - public class Binder implements android.os.IBinder { - method public final void markVintfStability(); - } - - public interface Parcelable { - method public default int getStability(); - } - - public class StatsFrameworkInitializer { - method public static void registerServiceWrappers(); - method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager); - } - - public class StatsServiceManager { - method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer(); - method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer(); - method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsdServiceRegisterer(); - } - - public static class StatsServiceManager.ServiceNotFoundException extends java.lang.Exception { - ctor public StatsServiceManager.ServiceNotFoundException(@NonNull String); - } - - public static final class StatsServiceManager.ServiceRegisterer { - method @Nullable public android.os.IBinder get(); - method @Nullable public android.os.IBinder getOrThrow() throws android.os.StatsServiceManager.ServiceNotFoundException; - } - -} - -package android.telephony { - - public abstract class CellSignalStrength { - method public static int getNumSignalStrengthLevels(); - } - - public class TelephonyManager { - method @NonNull public static int[] getAllNetworkTypes(); - } - -} - -package android.util { - - public final class Log { - method public static int logToRadioBuffer(int, @Nullable String, @Nullable String); - } - -} - diff --git a/api/module-lib-lint-baseline.txt b/api/module-lib-lint-baseline.txt deleted file mode 100644 index 56f7a02260a7..000000000000 --- a/api/module-lib-lint-baseline.txt +++ /dev/null @@ -1,29 +0,0 @@ -// Baseline format: 1.0 -ActionValue: android.net.TetheringConstants#EXTRA_ADD_TETHER_TYPE: - Inconsistent extra value; expected `android.net.extra.ADD_TETHER_TYPE`, was `extraAddTetherType` -ActionValue: android.net.TetheringConstants#EXTRA_PROVISION_CALLBACK: - Inconsistent extra value; expected `android.net.extra.PROVISION_CALLBACK`, was `extraProvisionCallback` -ActionValue: android.net.TetheringConstants#EXTRA_REM_TETHER_TYPE: - Inconsistent extra value; expected `android.net.extra.REM_TETHER_TYPE`, was `extraRemTetherType` -ActionValue: android.net.TetheringConstants#EXTRA_RUN_PROVISION: - Inconsistent extra value; expected `android.net.extra.RUN_PROVISION`, was `extraRunProvision` -ActionValue: android.net.TetheringConstants#EXTRA_SET_ALARM: - Inconsistent extra value; expected `android.net.extra.SET_ALARM`, was `extraSetAlarm` -ActionValue: android.net.TetheringManager#ACTION_TETHER_STATE_CHANGED: - Inconsistent action value; expected `android.net.action.TETHER_STATE_CHANGED`, was `android.net.conn.TETHER_STATE_CHANGED` -ActionValue: android.net.TetheringManager#EXTRA_ACTIVE_TETHER: - Inconsistent extra value; expected `android.net.extra.ACTIVE_TETHER`, was `tetherArray` -ActionValue: android.net.TetheringManager#EXTRA_AVAILABLE_TETHER: - Inconsistent extra value; expected `android.net.extra.AVAILABLE_TETHER`, was `availableArray` -ActionValue: android.net.TetheringManager#EXTRA_ERRORED_TETHER: - Inconsistent extra value; expected `android.net.extra.ERRORED_TETHER`, was `erroredArray` - - -ManagerConstructor: android.net.TetheringManager#TetheringManager(android.content.Context, java.util.function.Supplier<android.os.IBinder>): - Managers must always be obtained from Context; no direct constructors - - -PrivateSuperclass: android.location.GnssAntennaInfo.PhaseCenterVariationCorrections: - Public class android.location.GnssAntennaInfo.PhaseCenterVariationCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections -PrivateSuperclass: android.location.GnssAntennaInfo.SignalGainCorrections: - Public class android.location.GnssAntennaInfo.SignalGainCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections diff --git a/api/module-lib-removed.txt b/api/module-lib-removed.txt deleted file mode 100644 index d802177e249b..000000000000 --- a/api/module-lib-removed.txt +++ /dev/null @@ -1 +0,0 @@ -// Signature format: 2.0 diff --git a/api/system-current.txt b/api/system-current.txt index 0104ca25795c..dc90877569d5 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8992,6 +8992,7 @@ package android.provider { field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; field public static final String NAMESPACE_PERMISSIONS = "permissions"; field public static final String NAMESPACE_PRIVACY = "privacy"; + field public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot"; field public static final String NAMESPACE_ROLLBACK = "rollback"; field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot"; field public static final String NAMESPACE_RUNTIME = "runtime"; @@ -11247,7 +11248,6 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataConnectionAllowed(); method public boolean isDataConnectivityPossible(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); @@ -11280,7 +11280,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); @@ -11735,6 +11735,17 @@ package android.telephony.euicc { package android.telephony.ims { + public final class AudioCodecAttributes implements android.os.Parcelable { + ctor public AudioCodecAttributes(float, @NonNull android.util.Range<java.lang.Float>, float, @NonNull android.util.Range<java.lang.Float>); + method public int describeContents(); + method public float getBandwidthKhz(); + method @NonNull public android.util.Range<java.lang.Float> getBandwidthRangeKhz(); + method public float getBitrateKbps(); + method @NonNull public android.util.Range<java.lang.Float> getBitrateRangeKbps(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.AudioCodecAttributes> CREATOR; + } + public final class ImsCallForwardInfo implements android.os.Parcelable { ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int); method public int describeContents(); @@ -12103,6 +12114,7 @@ package android.telephony.ims { ctor public ImsStreamMediaProfile(int, int, int, int, int); method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile); method public int describeContents(); + method @Nullable public android.telephony.ims.AudioCodecAttributes getAudioCodecAttributes(); method public int getAudioDirection(); method public int getAudioQuality(); method public int getRttMode(); @@ -12110,6 +12122,7 @@ package android.telephony.ims { method public int getVideoQuality(); method public boolean isReceivingRttAudio(); method public boolean isRttCall(); + method public void setAudioCodecAttributes(@NonNull android.telephony.ims.AudioCodecAttributes); method public void setReceivingRttAudio(boolean); method public void setRttMode(int); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/api/current.txt b/core/api/current.txt index 98d61969572d..23ddda635324 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -46501,7 +46501,9 @@ package android.telephony { method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String); method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String); method public boolean isConcurrentVoiceAndDataSupported(); + method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isDataConnectionAllowed(); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled(); + method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabledForReason(int); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled(); method public boolean isEmergencyNumber(@NonNull String); method public boolean isHearingAidCompatibilitySupported(); @@ -46522,7 +46524,8 @@ package android.telephony { method @Deprecated public String sendEnvelopeWithStatus(String); method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler); method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>); method public boolean setLine1NumberForDisplay(String, String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic(); @@ -46570,6 +46573,10 @@ package android.telephony { 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_ENABLED_REASON_CARRIER = 2; // 0x2 + field public static final int DATA_ENABLED_REASON_POLICY = 1; // 0x1 + field public static final int DATA_ENABLED_REASON_THERMAL = 3; // 0x3 + field public static final int DATA_ENABLED_REASON_USER = 0; // 0x0 field public static final int DATA_SUSPENDED = 3; // 0x3 field public static final int DATA_UNKNOWN = -1; // 0xffffffff field public static final String EXTRA_ACTIVE_SIM_SUPPORTED_COUNT = "android.telephony.extra.ACTIVE_SIM_SUPPORTED_COUNT"; diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 95fc15254cd4..8b1e65fe3641 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -7883,6 +7883,7 @@ package android.provider { field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; field public static final String NAMESPACE_PERMISSIONS = "permissions"; field public static final String NAMESPACE_PRIVACY = "privacy"; + field public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot"; field public static final String NAMESPACE_ROLLBACK = "rollback"; field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot"; field public static final String NAMESPACE_RUNTIME = "runtime"; @@ -10129,7 +10130,6 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int); - method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataConnectionAllowed(); method public boolean isDataConnectivityPossible(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); @@ -10162,7 +10162,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); @@ -10617,6 +10617,17 @@ package android.telephony.euicc { package android.telephony.ims { + public final class AudioCodecAttributes implements android.os.Parcelable { + ctor public AudioCodecAttributes(float, @NonNull android.util.Range<java.lang.Float>, float, @NonNull android.util.Range<java.lang.Float>); + method public int describeContents(); + method public float getBandwidthKhz(); + method @NonNull public android.util.Range<java.lang.Float> getBandwidthRangeKhz(); + method public float getBitrateKbps(); + method @NonNull public android.util.Range<java.lang.Float> getBitrateRangeKbps(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.AudioCodecAttributes> CREATOR; + } + public final class ImsCallForwardInfo implements android.os.Parcelable { ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int); method public int describeContents(); @@ -10985,6 +10996,7 @@ package android.telephony.ims { ctor public ImsStreamMediaProfile(int, int, int, int, int); method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile); method public int describeContents(); + method @Nullable public android.telephony.ims.AudioCodecAttributes getAudioCodecAttributes(); method public int getAudioDirection(); method public int getAudioQuality(); method public int getRttMode(); @@ -10992,6 +11004,7 @@ package android.telephony.ims { method public int getVideoQuality(); method public boolean isReceivingRttAudio(); method public boolean isRttCall(); + method public void setAudioCodecAttributes(@NonNull android.telephony.ims.AudioCodecAttributes); method public void setReceivingRttAudio(boolean); method public void setRttMode(int); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 69b77a9b4c59..0d5bb115db91 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1111,9 +1111,30 @@ public class AppOpsManager { /** @hide */ public static final int OP_NO_ISOLATED_STORAGE = AppProtoEnums.APP_OP_NO_ISOLATED_STORAGE; + /** + * Reserved key for 100 + * + * @hide + */ + public static final int OP_RESERVED_100 = 100; + + /** + * Reserved key for 101 + * + * @hide + */ + public static final int OP_RESERVED_101 = 101; + + /** + * Reserved key for 102 + * + * @hide + */ + public static final int OP_RESERVED_102 = 102; + /** @hide */ @UnsupportedAppUsage - public static final int _NUM_OP = 100; + public static final int _NUM_OP = 103; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -1430,6 +1451,27 @@ public class AppOpsManager { */ public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage"; + /** + * Reserved for 100 + * + * @hide + */ + public static final String OPSTR_RESERVED_100 = "android:opstr_reserved_100"; + + /** + * Reserved for 101 + * + * @hide + */ + public static final String OPSTR_RESERVED_101 = "android:opstr_reserved_101"; + + /** + * Reserved for 102 + * + * @hide + */ + public static final String OPSTR_RESERVED_102 = "android:opstr_reserved_102"; + /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ @@ -1619,6 +1661,9 @@ public class AppOpsManager { OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, //AUTO_REVOKE_PERMISSIONS_IF_UNUSED OP_AUTO_REVOKE_MANAGED_BY_INSTALLER, //OP_AUTO_REVOKE_MANAGED_BY_INSTALLER OP_NO_ISOLATED_STORAGE, // NO_ISOLATED_STORAGE + OP_RESERVED_100, // OP_RESERVED_100 + OP_RESERVED_101, // OP_RESERVED_101 + OP_RESERVED_102, // OP_RESERVED_102 }; /** @@ -1725,6 +1770,9 @@ public class AppOpsManager { OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER, OPSTR_NO_ISOLATED_STORAGE, + OPSTR_RESERVED_100, + OPSTR_RESERVED_101, + OPSTR_RESERVED_102, }; /** @@ -1832,6 +1880,9 @@ public class AppOpsManager { "AUTO_REVOKE_PERMISSIONS_IF_UNUSED", "AUTO_REVOKE_MANAGED_BY_INSTALLER", "NO_ISOLATED_STORAGE", + "RESERVED_100", + "RESERVED_101", + "RESERVED_102", }; /** @@ -1940,6 +1991,9 @@ public class AppOpsManager { null, // no permission for OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED null, // no permission for OP_AUTO_REVOKE_MANAGED_BY_INSTALLER null, // no permission for OP_NO_ISOLATED_STORAGE + null, // OP_RESERVED_100 + null, // OP_RESERVED_101 + null, // OP_RESERVED_102 }; /** @@ -2048,6 +2102,9 @@ public class AppOpsManager { null, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED null, // AUTO_REVOKE_MANAGED_BY_INSTALLER null, // NO_ISOLATED_STORAGE + null, // OP_RESERVED_100 + null, // OP_RESERVED_101 + null, // OP_RESERVED_102 }; /** @@ -2155,6 +2212,9 @@ public class AppOpsManager { null, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED null, // AUTO_REVOKE_MANAGED_BY_INSTALLER null, // NO_ISOLATED_STORAGE + null, // OP_RESERVED_100 + null, // OP_RESERVED_101 + null, // OP_RESERVED_102 }; /** @@ -2261,6 +2321,9 @@ public class AppOpsManager { AppOpsManager.MODE_DEFAULT, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED AppOpsManager.MODE_ALLOWED, // OP_AUTO_REVOKE_MANAGED_BY_INSTALLER AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE + AppOpsManager.MODE_ERRORED, // OP_RESERVED_100 + AppOpsManager.MODE_ERRORED, // OP_RESERVED_101 + AppOpsManager.MODE_ERRORED, // OP_RESERVED_102 }; /** @@ -2371,6 +2434,9 @@ public class AppOpsManager { false, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED false, // AUTO_REVOKE_MANAGED_BY_INSTALLER true, // NO_ISOLATED_STORAGE + false, // OP_RESERVED_100 + false, // OP_RESERVED_101 + false, // OP_RESERVED_102 }; /** diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index 19242ba9bdb5..ffa537e0617e 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -88,6 +88,26 @@ public abstract class DevicePolicyManagerInternal { public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy); /** + * Checks if an app with given uid is an active device owner of its user. + * + * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held. + * + * @param uid App uid. + * @return true if the uid is an active device owner. + */ + public abstract boolean isActiveDeviceOwner(int uid); + + /** + * Checks if an app with given uid is an active profile owner of its user. + * + * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held. + * + * @param uid App uid. + * @return true if the uid is an active profile owner. + */ + public abstract boolean isActiveProfileOwner(int uid); + + /** * Checks if an app with given uid is the active supervision admin. * * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held. diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS new file mode 100644 index 000000000000..a16bb4ff3b1d --- /dev/null +++ b/core/java/android/content/pm/OWNERS @@ -0,0 +1 @@ +per-file PackageParser.java = chiuwinson@google.com diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 0adb66c72065..a30a6525fab5 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -143,8 +143,14 @@ import java.util.UUID; * <li>All installations must contain a single base APK. * </ul> * + * @deprecated This class is mostly unused and no new changes should be added to it. Use + * {@link android.content.pm.parsing.ParsingPackageUtils} and related parsing v2 infrastructure in + * the core/services parsing subpackages. Or for a quick parse of a provided APK, use + * {@link PackageManager#getPackageArchiveInfo(String, int)}. + * * @hide */ +@Deprecated public class PackageParser { public static final boolean DEBUG_JAR = false; diff --git a/core/java/android/content/pm/parsing/OWNERS b/core/java/android/content/pm/parsing/OWNERS new file mode 100644 index 000000000000..8049d5cb7fa2 --- /dev/null +++ b/core/java/android/content/pm/parsing/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 36137 + +chiuwinson@google.com +patb@google.com +toddke@google.com diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 000cb2acbb60..4d67d4623897 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -218,6 +218,15 @@ public final class DeviceConfig { public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; /** + * Namespace for features related to the Profcollect native Service. + * These features are applied at reboot. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot"; + + /** * Namespace for Rollback flags that are applied immediately. * * @hide diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index e4ba87c14626..f08756a015b2 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -218,6 +218,7 @@ public final class KeymasterDefs { public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58; public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59; public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66; + public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = -68; public static final int KM_ERROR_DEVICE_LOCKED = -72; public static final int KM_ERROR_UNIMPLEMENTED = -100; public static final int KM_ERROR_VERSION_MISMATCH = -101; @@ -265,6 +266,8 @@ public final class KeymasterDefs { sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH, "Invalid MAC or authentication tag length"); sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids"); + sErrorCodeToString.put(KM_ERROR_HARDWARE_TYPE_UNAVAILABLE, "Requested security level " + + "(likely Strongbox) is not available."); sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked"); sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented"); sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error"); diff --git a/core/java/android/timezone/TzDataSetVersion.java b/core/java/android/timezone/TzDataSetVersion.java index e1fb932b977d..52e1e58b2cfd 100644 --- a/core/java/android/timezone/TzDataSetVersion.java +++ b/core/java/android/timezone/TzDataSetVersion.java @@ -18,6 +18,7 @@ package android.timezone; import android.annotation.NonNull; +import com.android.i18n.timezone.TimeZoneDataFiles; import com.android.internal.annotations.VisibleForTesting; import java.io.IOException; @@ -75,8 +76,7 @@ public final class TzDataSetVersion { @NonNull public static TzDataSetVersion read() throws IOException, TzDataSetException { try { - return new TzDataSetVersion( - com.android.i18n.timezone.TzDataSetVersion.readTimeZoneModuleVersion()); + return new TzDataSetVersion(TimeZoneDataFiles.readTimeZoneModuleVersion()); } catch (com.android.i18n.timezone.TzDataSetVersion.TzDataSetException e) { throw new TzDataSetException(e.getMessage(), e); } diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java index c3e2ecc9e0f3..33bc121d8555 100644 --- a/core/java/android/uwb/AngleMeasurement.java +++ b/core/java/android/uwb/AngleMeasurement.java @@ -17,6 +17,10 @@ package android.uwb; import android.annotation.FloatRange; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; /** * Angle measurement @@ -26,7 +30,7 @@ import android.annotation.FloatRange; * * @hide */ -public final class AngleMeasurement { +public final class AngleMeasurement implements Parcelable { private final double mRadians; private final double mErrorRadians; private final double mConfidenceLevel; @@ -39,7 +43,7 @@ public final class AngleMeasurement { /** * Angle measurement in radians - * + * * @return angle in radians */ @FloatRange(from = -Math.PI, to = +Math.PI) @@ -74,6 +78,61 @@ public final class AngleMeasurement { } /** + * @hide + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AngleMeasurement) { + AngleMeasurement other = (AngleMeasurement) obj; + return mRadians == other.getRadians() + && mErrorRadians == other.getErrorRadians() + && mConfidenceLevel == other.getConfidenceLevel(); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mRadians, mErrorRadians, mConfidenceLevel); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeDouble(mRadians); + dest.writeDouble(mErrorRadians); + dest.writeDouble(mConfidenceLevel); + } + + public static final @android.annotation.NonNull Creator<AngleMeasurement> CREATOR = + new Creator<AngleMeasurement>() { + @Override + public AngleMeasurement createFromParcel(Parcel in) { + Builder builder = new Builder(); + builder.setRadians(in.readDouble()); + builder.setErrorRadians(in.readDouble()); + builder.setConfidenceLevel(in.readDouble()); + return builder.build(); + } + + @Override + public AngleMeasurement[] newArray(int size) { + return new AngleMeasurement[size]; + } + }; + + /** * Builder class for {@link AngleMeasurement}. */ public static final class Builder { diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java index a7b5eae728cb..cd5af691ed51 100644 --- a/core/java/android/uwb/AngleOfArrivalMeasurement.java +++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java @@ -18,13 +18,17 @@ package android.uwb; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; /** * Represents an angle of arrival measurement between two devices using Ultra Wideband * * @hide */ -public final class AngleOfArrivalMeasurement { +public final class AngleOfArrivalMeasurement implements Parcelable { private final AngleMeasurement mAzimuthAngleMeasurement; private final AngleMeasurement mAltitudeAngleMeasurement; @@ -71,6 +75,63 @@ public final class AngleOfArrivalMeasurement { } /** + * @hide + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof AngleOfArrivalMeasurement) { + AngleOfArrivalMeasurement other = (AngleOfArrivalMeasurement) obj; + return mAzimuthAngleMeasurement.equals(other.getAzimuth()) + && mAltitudeAngleMeasurement.equals(other.getAltitude()); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mAzimuthAngleMeasurement, mAltitudeAngleMeasurement); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mAzimuthAngleMeasurement, flags); + dest.writeParcelable(mAltitudeAngleMeasurement, flags); + } + + public static final @android.annotation.NonNull Creator<AngleOfArrivalMeasurement> CREATOR = + new Creator<AngleOfArrivalMeasurement>() { + @Override + public AngleOfArrivalMeasurement createFromParcel(Parcel in) { + Builder builder = new Builder(); + + builder.setAzimuthAngleMeasurement( + in.readParcelable(AngleMeasurement.class.getClassLoader())); + + builder.setAltitudeAngleMeasurement( + in.readParcelable(AngleMeasurement.class.getClassLoader())); + + return builder.build(); + } + + @Override + public AngleOfArrivalMeasurement[] newArray(int size) { + return new AngleOfArrivalMeasurement[size]; + } + }; + + /** * Builder class for {@link AngleOfArrivalMeasurement}. */ public static final class Builder { diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java index 4cd5d83f4efc..c959840c51ba 100644 --- a/core/java/android/uwb/DistanceMeasurement.java +++ b/core/java/android/uwb/DistanceMeasurement.java @@ -17,6 +17,11 @@ package android.uwb; import android.annotation.FloatRange; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; /** * A data point for the distance measurement @@ -26,7 +31,7 @@ import android.annotation.FloatRange; * * @hide */ -public final class DistanceMeasurement { +public final class DistanceMeasurement implements Parcelable { private final double mMeters; private final double mErrorMeters; private final double mConfidenceLevel; @@ -70,6 +75,61 @@ public final class DistanceMeasurement { } /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof DistanceMeasurement) { + DistanceMeasurement other = (DistanceMeasurement) obj; + return mMeters == other.getMeters() + && mErrorMeters == other.getErrorMeters() + && mConfidenceLevel == other.getConfidenceLevel(); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mMeters, mErrorMeters, mConfidenceLevel); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeDouble(mMeters); + dest.writeDouble(mErrorMeters); + dest.writeDouble(mConfidenceLevel); + } + + public static final @android.annotation.NonNull Creator<DistanceMeasurement> CREATOR = + new Creator<DistanceMeasurement>() { + @Override + public DistanceMeasurement createFromParcel(Parcel in) { + Builder builder = new Builder(); + builder.setMeters(in.readDouble()); + builder.setErrorMeters(in.readDouble()); + builder.setConfidenceLevel(in.readDouble()); + return builder.build(); + } + + @Override + public DistanceMeasurement[] newArray(int size) { + return new DistanceMeasurement[size]; + } + }; + + /** * Builder to get a {@link DistanceMeasurement} object. */ public static final class Builder { diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java index 33a34e3954c2..f1c316289653 100644 --- a/core/java/android/uwb/RangingMeasurement.java +++ b/core/java/android/uwb/RangingMeasurement.java @@ -20,17 +20,20 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; +import android.os.Parcel; +import android.os.Parcelable; import android.os.SystemClock; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Objects; /** * Representation of a ranging measurement between the local device and a remote device * * @hide */ -public final class RangingMeasurement { +public final class RangingMeasurement implements Parcelable { private final UwbAddress mRemoteDeviceAddress; private final @Status int mStatus; private final long mElapsedRealtimeNanos; @@ -128,6 +131,71 @@ public final class RangingMeasurement { } /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RangingMeasurement) { + RangingMeasurement other = (RangingMeasurement) obj; + return mRemoteDeviceAddress.equals(other.getRemoteDeviceAddress()) + && mStatus == other.getStatus() + && mElapsedRealtimeNanos == other.getElapsedRealtimeNanos() + && mDistanceMeasurement.equals(other.getDistance()) + && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrival()); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos, + mDistanceMeasurement, mAngleOfArrivalMeasurement); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mRemoteDeviceAddress, flags); + dest.writeInt(mStatus); + dest.writeLong(mElapsedRealtimeNanos); + dest.writeParcelable(mDistanceMeasurement, flags); + dest.writeParcelable(mAngleOfArrivalMeasurement, flags); + } + + public static final @android.annotation.NonNull Creator<RangingMeasurement> CREATOR = + new Creator<RangingMeasurement>() { + @Override + public RangingMeasurement createFromParcel(Parcel in) { + Builder builder = new Builder(); + builder.setRemoteDeviceAddress( + in.readParcelable(UwbAddress.class.getClassLoader())); + builder.setStatus(in.readInt()); + builder.setElapsedRealtimeNanos(in.readLong()); + builder.setDistanceMeasurement( + in.readParcelable(DistanceMeasurement.class.getClassLoader())); + builder.setAngleOfArrivalMeasurement( + in.readParcelable(AngleOfArrivalMeasurement.class.getClassLoader())); + return builder.build(); + } + + @Override + public RangingMeasurement[] newArray(int size) { + return new RangingMeasurement[size]; + } + }; + + /** * Builder for a {@link RangingMeasurement} object. */ public static final class Builder { diff --git a/core/java/android/uwb/RangingParams.java b/core/java/android/uwb/RangingParams.java index a50de3e61425..f23d9ed0dd3a 100644 --- a/core/java/android/uwb/RangingParams.java +++ b/core/java/android/uwb/RangingParams.java @@ -19,15 +19,18 @@ package android.uwb; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; import android.os.PersistableBundle; -import android.util.Duration; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -36,7 +39,7 @@ import java.util.Set; * * @hide */ -public final class RangingParams { +public final class RangingParams implements Parcelable { private final boolean mIsInitiator; private final boolean mIsController; private final Duration mSamplePeriod; @@ -200,6 +203,99 @@ public final class RangingParams { } /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RangingParams) { + RangingParams other = (RangingParams) obj; + + return mIsInitiator == other.mIsInitiator + && mIsController == other.mIsController + && mSamplePeriod.equals(other.mSamplePeriod) + && mLocalDeviceAddress.equals(other.mLocalDeviceAddress) + && mRemoteDeviceAddresses.equals(other.mRemoteDeviceAddresses) + && mChannelNumber == other.mChannelNumber + && mTransmitPreambleCodeIndex == other.mTransmitPreambleCodeIndex + && mReceivePreambleCodeIndex == other.mReceivePreambleCodeIndex + && mStsPhyPacketType == other.mStsPhyPacketType + && mSpecificationParameters.size() == other.mSpecificationParameters.size() + && mSpecificationParameters.kindofEquals(other.mSpecificationParameters); + } + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mIsInitiator, mIsController, mSamplePeriod, mLocalDeviceAddress, + mRemoteDeviceAddresses, mChannelNumber, mTransmitPreambleCodeIndex, + mReceivePreambleCodeIndex, mStsPhyPacketType, mSpecificationParameters); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeBoolean(mIsInitiator); + dest.writeBoolean(mIsController); + dest.writeLong(mSamplePeriod.getSeconds()); + dest.writeInt(mSamplePeriod.getNano()); + dest.writeParcelable(mLocalDeviceAddress, flags); + + UwbAddress[] remoteAddresses = new UwbAddress[mRemoteDeviceAddresses.size()]; + mRemoteDeviceAddresses.toArray(remoteAddresses); + dest.writeParcelableArray(remoteAddresses, flags); + + dest.writeInt(mChannelNumber); + dest.writeInt(mTransmitPreambleCodeIndex); + dest.writeInt(mReceivePreambleCodeIndex); + dest.writeInt(mStsPhyPacketType); + dest.writePersistableBundle(mSpecificationParameters); + } + + public static final @android.annotation.NonNull Creator<RangingParams> CREATOR = + new Creator<RangingParams>() { + @Override + public RangingParams createFromParcel(Parcel in) { + Builder builder = new Builder(); + builder.setIsInitiator(in.readBoolean()); + builder.setIsController(in.readBoolean()); + builder.setSamplePeriod(Duration.ofSeconds(in.readLong(), in.readInt())); + builder.setLocalDeviceAddress( + in.readParcelable(UwbAddress.class.getClassLoader())); + + UwbAddress[] remoteAddresses = + in.readParcelableArray(null, UwbAddress.class); + for (UwbAddress remoteAddress : remoteAddresses) { + builder.addRemoteDeviceAddress(remoteAddress); + } + + builder.setChannelNumber(in.readInt()); + builder.setTransmitPreambleCodeIndex(in.readInt()); + builder.setReceivePreambleCodeIndex(in.readInt()); + builder.setStsPhPacketType(in.readInt()); + builder.setSpecificationParameters(in.readPersistableBundle()); + + return builder.build(); + } + + @Override + public RangingParams[] newArray(int size) { + return new RangingParams[size]; + } + }; + + /** * Builder class for {@link RangingParams}. */ public static final class Builder { diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java index 5aca12aaf2cf..45180bfa6981 100644 --- a/core/java/android/uwb/RangingReport.java +++ b/core/java/android/uwb/RangingReport.java @@ -17,16 +17,20 @@ package android.uwb; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * This class contains the UWB ranging data * * @hide */ -public final class RangingReport { +public final class RangingReport implements Parcelable { private final List<RangingMeasurement> mRangingMeasurements; private RangingReport(@NonNull List<RangingMeasurement> rangingMeasurements) { @@ -49,6 +53,56 @@ public final class RangingReport { } /** + * @hide + */ + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + + if (obj instanceof RangingReport) { + RangingReport other = (RangingReport) obj; + return mRangingMeasurements.equals(other.getMeasurements()); + } + + return false; + } + + /** + * @hide + */ + @Override + public int hashCode() { + return Objects.hash(mRangingMeasurements); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedList(mRangingMeasurements); + } + + public static final @android.annotation.NonNull Creator<RangingReport> CREATOR = + new Creator<RangingReport>() { + @Override + public RangingReport createFromParcel(Parcel in) { + Builder builder = new Builder(); + builder.addMeasurements(in.createTypedArrayList(RangingMeasurement.CREATOR)); + return builder.build(); + } + + @Override + public RangingReport[] newArray(int size) { + return new RangingReport[size]; + } + }; + + /** * Builder for {@link RangingReport} object */ public static final class Builder { diff --git a/core/java/android/uwb/TEST_MAPPING b/core/java/android/uwb/TEST_MAPPING new file mode 100644 index 000000000000..9e50bd64d089 --- /dev/null +++ b/core/java/android/uwb/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "UwbManagerTests" + } + ] +}
\ No newline at end of file diff --git a/core/java/android/uwb/UwbAddress.java b/core/java/android/uwb/UwbAddress.java index 48fcb10e1a1a..828324c54c5a 100644 --- a/core/java/android/uwb/UwbAddress.java +++ b/core/java/android/uwb/UwbAddress.java @@ -18,16 +18,26 @@ package android.uwb; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Arrays; /** * A class representing a UWB address * * @hide */ -public final class UwbAddress { +public final class UwbAddress implements Parcelable { public static final int SHORT_ADDRESS_BYTE_LENGTH = 2; public static final int EXTENDED_ADDRESS_BYTE_LENGTH = 8; + private final byte[] mAddressBytes; + + private UwbAddress(byte[] address) { + mAddressBytes = address; + } + /** * Create a {@link UwbAddress} from a byte array. * @@ -37,12 +47,16 @@ public final class UwbAddress { * * @param address a byte array to convert to a {@link UwbAddress} * @return a {@link UwbAddress} created from the input byte array - * @throw IllegableArumentException when the length is not one of + * @throws IllegalArgumentException when the length is not one of * {@link #SHORT_ADDRESS_BYTE_LENGTH} or {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes */ @NonNull - public static UwbAddress fromBytes(byte[] address) throws IllegalArgumentException { - throw new UnsupportedOperationException(); + public static UwbAddress fromBytes(@NonNull byte[] address) throws IllegalArgumentException { + if (address.length != SHORT_ADDRESS_BYTE_LENGTH + && address.length != EXTENDED_ADDRESS_BYTE_LENGTH) { + throw new IllegalArgumentException("Invalid UwbAddress length " + address.length); + } + return new UwbAddress(address); } /** @@ -52,7 +66,7 @@ public final class UwbAddress { */ @NonNull public byte[] toBytes() { - throw new UnsupportedOperationException(); + return mAddressBytes; } /** @@ -61,22 +75,55 @@ public final class UwbAddress { * {@link #EXTENDED_ADDRESS_BYTE_LENGTH}. */ public int size() { - throw new UnsupportedOperationException(); + return mAddressBytes.length; } @NonNull @Override public String toString() { - throw new UnsupportedOperationException(); + StringBuilder builder = new StringBuilder("0x"); + for (byte addressByte : mAddressBytes) { + builder.append(String.format("%02X", addressByte)); + } + return builder.toString(); } @Override public boolean equals(@Nullable Object obj) { - throw new UnsupportedOperationException(); + if (obj instanceof UwbAddress) { + return Arrays.equals(mAddressBytes, ((UwbAddress) obj).toBytes()); + } + return false; } @Override public int hashCode() { - throw new UnsupportedOperationException(); + return Arrays.hashCode(mAddressBytes); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mAddressBytes.length); + dest.writeByteArray(mAddressBytes); } + + public static final @android.annotation.NonNull Creator<UwbAddress> CREATOR = + new Creator<UwbAddress>() { + @Override + public UwbAddress createFromParcel(Parcel in) { + byte[] address = new byte[in.readInt()]; + in.readByteArray(address); + return UwbAddress.fromBytes(address); + } + + @Override + public UwbAddress[] newArray(int size) { + return new UwbAddress[size]; + } + }; } diff --git a/core/proto/android/app/enums.proto b/core/proto/android/app/enums.proto index bd5cb62f7fde..98ba029236e6 100644 --- a/core/proto/android/app/enums.proto +++ b/core/proto/android/app/enums.proto @@ -207,4 +207,7 @@ enum AppOpEnum { APP_OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97; APP_OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98; APP_OP_NO_ISOLATED_STORAGE = 99; + APP_OP_RESERVED_100 = 100; + APP_OP_RESERVED_101 = 101; + APP_OP_RESERVED_102 = 102; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 781bb2ad1857..4548f3aa6347 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1671,7 +1671,7 @@ to be explicitly declared in this resource to be enabled. * SDK level 28 makes the following algorithms mandatory : "cbc(aes)", "hmac(md5)", "hmac(sha1)", "hmac(sha256)", "hmac(sha384)", "hmac(sha512)", "rfc4106(gcm(aes))" - * SDK level 30 makes the following algorithms mandatory : "rfc3686(ctr(aes))", + * SDK level 31 makes the following algorithms mandatory : "rfc3686(ctr(aes))", "xcbc(aes)", "rfc7539esp(chacha20,poly1305)" --> <string-array name="config_optionalIpSecAlgorithms" translatable="false"> diff --git a/apex/extservices/testing/Android.bp b/core/tests/uwbtests/Android.bp index 88a47246c824..c41c346b131a 100644 --- a/apex/extservices/testing/Android.bp +++ b/core/tests/uwbtests/Android.bp @@ -1,10 +1,10 @@ -// Copyright (C) 2020 The Android Open Source Project +// Copyright 2020 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,14 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -apex_test { - name: "test_com.android.extservices", - visibility: [ - "//system/apex/tests", +android_test { + name: "UwbManagerTests", + static_libs: [ + "androidx.test.ext.junit", + "androidx.test.rules", ], - defaults: ["com.android.extservices-defaults"], - manifest: "test_manifest.json", - file_contexts: ":com.android.extservices-file_contexts", - // Test APEX, should never be installed - installable: false, + libs: [ + "android.test.runner", + ], + srcs: ["src/**/*.java"], + platform_apis: true, + certificate: "platform", + test_suites: ["device-tests"], } diff --git a/core/tests/uwbtests/AndroidManifest.xml b/core/tests/uwbtests/AndroidManifest.xml new file mode 100644 index 000000000000..dc991ff636d2 --- /dev/null +++ b/core/tests/uwbtests/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.uwb"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <!-- This is a self-instrumenting test package. --> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.uwb" + android:label="UWB Manager Tests"> + </instrumentation> + +</manifest> + diff --git a/core/tests/uwbtests/AndroidTest.xml b/core/tests/uwbtests/AndroidTest.xml new file mode 100644 index 000000000000..ff4b668cc625 --- /dev/null +++ b/core/tests/uwbtests/AndroidTest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for UWB Manager 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="UwbManagerTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct"/> + <option name="test-tag" value="UwbManagerTests"/> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="android.uwb" /> + <option name="hidden-api-checks" value="false"/> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/> + </test> +</configuration> diff --git a/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java new file mode 100644 index 000000000000..7769c28202f2 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/AngleMeasurementTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link AngleMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AngleMeasurementTest { + private static final double EPSILON = 0.00000000001; + + @Test + public void testBuilder() { + double radians = 0.1234; + double errorRadians = 0.5678; + double confidence = 0.5; + + AngleMeasurement.Builder builder = new AngleMeasurement.Builder(); + tryBuild(builder, false); + + builder.setRadians(radians); + tryBuild(builder, false); + + builder.setErrorRadians(errorRadians); + tryBuild(builder, false); + + builder.setConfidenceLevel(confidence); + AngleMeasurement measurement = tryBuild(builder, true); + + assertEquals(measurement.getRadians(), radians, 0); + assertEquals(measurement.getErrorRadians(), errorRadians, 0); + assertEquals(measurement.getConfidenceLevel(), confidence, 0); + } + + private AngleMeasurement tryBuild(AngleMeasurement.Builder builder, boolean expectSuccess) { + AngleMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected AngleMeasurement.Builder.build() to fail, but it succeeded"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected AngleMeasurement.Builder.build() to succeed, but it failed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + AngleMeasurement measurement = UwbTestUtils.getAngleMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + AngleMeasurement fromParcel = AngleMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java new file mode 100644 index 000000000000..077b08f41b59 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link AngleOfArrivalMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AngleOfArrivalMeasurementTest { + + @Test + public void testBuilder() { + AngleMeasurement azimuth = UwbTestUtils.getAngleMeasurement(); + AngleMeasurement altitude = UwbTestUtils.getAngleMeasurement(); + + AngleOfArrivalMeasurement.Builder builder = new AngleOfArrivalMeasurement.Builder(); + tryBuild(builder, false); + + builder.setAltitudeAngleMeasurement(altitude); + tryBuild(builder, false); + + builder.setAzimuthAngleMeasurement(azimuth); + AngleOfArrivalMeasurement measurement = tryBuild(builder, true); + + assertEquals(azimuth, measurement.getAzimuth()); + assertEquals(altitude, measurement.getAltitude()); + } + + private AngleMeasurement getAngleMeasurement(double radian, double error, double confidence) { + return new AngleMeasurement.Builder() + .setRadians(radian) + .setErrorRadians(error) + .setConfidenceLevel(confidence) + .build(); + } + + private AngleOfArrivalMeasurement tryBuild(AngleOfArrivalMeasurement.Builder builder, + boolean expectSuccess) { + AngleOfArrivalMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected AngleOfArrivalMeasurement.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected AngleOfArrivalMeasurement.Builder.build() to succeed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + AngleOfArrivalMeasurement measurement = UwbTestUtils.getAngleOfArrivalMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + AngleOfArrivalMeasurement fromParcel = + AngleOfArrivalMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java new file mode 100644 index 000000000000..439c884723be --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/DistanceMeasurementTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link DistanceMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class DistanceMeasurementTest { + private static final double EPSILON = 0.00000000001; + + @Test + public void testBuilder() { + double meters = 0.12; + double error = 0.54; + double confidence = 0.99; + + DistanceMeasurement.Builder builder = new DistanceMeasurement.Builder(); + tryBuild(builder, false); + + builder.setMeters(meters); + tryBuild(builder, false); + + builder.setErrorMeters(error); + tryBuild(builder, false); + + builder.setConfidenceLevel(confidence); + DistanceMeasurement measurement = tryBuild(builder, true); + + assertEquals(meters, measurement.getMeters(), 0); + assertEquals(error, measurement.getErrorMeters(), 0); + assertEquals(confidence, measurement.getConfidenceLevel(), 0); + } + + private DistanceMeasurement tryBuild(DistanceMeasurement.Builder builder, + boolean expectSuccess) { + DistanceMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected DistanceMeasurement.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected DistanceMeasurement.Builder.build() to succeed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + DistanceMeasurement measurement = UwbTestUtils.getDistanceMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + DistanceMeasurement fromParcel = + DistanceMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java new file mode 100644 index 000000000000..a7559d86221e --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; +import android.os.SystemClock; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link RangingMeasurement}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RangingMeasurementTest { + + @Test + public void testBuilder() { + int status = RangingMeasurement.RANGING_STATUS_SUCCESS; + UwbAddress address = UwbTestUtils.getUwbAddress(false); + long time = SystemClock.elapsedRealtimeNanos(); + AngleOfArrivalMeasurement angleMeasurement = UwbTestUtils.getAngleOfArrivalMeasurement(); + DistanceMeasurement distanceMeasurement = UwbTestUtils.getDistanceMeasurement(); + + RangingMeasurement.Builder builder = new RangingMeasurement.Builder(); + + builder.setStatus(status); + tryBuild(builder, false); + + builder.setElapsedRealtimeNanos(time); + tryBuild(builder, false); + + builder.setAngleOfArrivalMeasurement(angleMeasurement); + tryBuild(builder, false); + + builder.setDistanceMeasurement(distanceMeasurement); + tryBuild(builder, false); + + builder.setRemoteDeviceAddress(address); + RangingMeasurement measurement = tryBuild(builder, true); + + assertEquals(status, measurement.getStatus()); + assertEquals(address, measurement.getRemoteDeviceAddress()); + assertEquals(time, measurement.getElapsedRealtimeNanos()); + assertEquals(angleMeasurement, measurement.getAngleOfArrival()); + assertEquals(distanceMeasurement, measurement.getDistance()); + } + + private RangingMeasurement tryBuild(RangingMeasurement.Builder builder, + boolean expectSuccess) { + RangingMeasurement measurement = null; + try { + measurement = builder.build(); + if (!expectSuccess) { + fail("Expected RangingMeasurement.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected DistanceMeasurement.Builder.build() to succeed"); + } + } + return measurement; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + RangingMeasurement measurement = UwbTestUtils.getRangingMeasurement(); + measurement.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + RangingMeasurement fromParcel = RangingMeasurement.CREATOR.createFromParcel(parcel); + assertEquals(measurement, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java b/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java new file mode 100644 index 000000000000..8095c995b8a9 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/RangingParamsTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.os.Parcel; +import android.os.PersistableBundle; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.Duration; + +/** + * Test of {@link RangingParams}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RangingParamsTest { + + @Test + public void testParams_Build() { + UwbAddress local = UwbAddress.fromBytes(new byte[] {(byte) 0xA0, (byte) 0x57}); + UwbAddress remote = UwbAddress.fromBytes(new byte[] {(byte) 0x4D, (byte) 0x8C}); + int channel = 9; + int rxPreamble = 16; + int txPreamble = 21; + boolean isController = true; + boolean isInitiator = false; + @RangingParams.StsPhyPacketType int stsPhyType = RangingParams.STS_PHY_PACKET_TYPE_SP2; + Duration samplePeriod = Duration.ofSeconds(1, 234); + PersistableBundle specParams = new PersistableBundle(); + specParams.putString("protocol", "some_protocol"); + + RangingParams params = new RangingParams.Builder() + .setChannelNumber(channel) + .setReceivePreambleCodeIndex(rxPreamble) + .setTransmitPreambleCodeIndex(txPreamble) + .setLocalDeviceAddress(local) + .addRemoteDeviceAddress(remote) + .setIsController(isController) + .setIsInitiator(isInitiator) + .setSamplePeriod(samplePeriod) + .setStsPhPacketType(stsPhyType) + .setSpecificationParameters(specParams) + .build(); + + assertEquals(params.getLocalDeviceAddress(), local); + assertEquals(params.getRemoteDeviceAddresses().size(), 1); + assertEquals(params.getRemoteDeviceAddresses().get(0), remote); + assertEquals(params.getChannelNumber(), channel); + assertEquals(params.isController(), isController); + assertEquals(params.isInitiator(), isInitiator); + assertEquals(params.getRxPreambleIndex(), rxPreamble); + assertEquals(params.getTxPreambleIndex(), txPreamble); + assertEquals(params.getStsPhyPacketType(), stsPhyType); + assertEquals(params.getSamplingPeriod(), samplePeriod); + assertTrue(params.getSpecificationParameters().kindofEquals(specParams)); + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + RangingParams params = new RangingParams.Builder() + .setChannelNumber(9) + .setReceivePreambleCodeIndex(16) + .setTransmitPreambleCodeIndex(21) + .setLocalDeviceAddress(UwbTestUtils.getUwbAddress(false)) + .addRemoteDeviceAddress(UwbTestUtils.getUwbAddress(true)) + .setIsController(false) + .setIsInitiator(true) + .setSamplePeriod(Duration.ofSeconds(2)) + .setStsPhPacketType(RangingParams.STS_PHY_PACKET_TYPE_SP1) + .build(); + params.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + RangingParams fromParcel = RangingParams.CREATOR.createFromParcel(parcel); + assertEquals(params, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/RangingReportTest.java b/core/tests/uwbtests/src/android/uwb/RangingReportTest.java new file mode 100644 index 000000000000..64c48ba4b6f4 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/RangingReportTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +/** + * Test of {@link RangingReport}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RangingReportTest { + + @Test + public void testBuilder() { + List<RangingMeasurement> measurements = UwbTestUtils.getRangingMeasurements(5); + + RangingReport.Builder builder = new RangingReport.Builder(); + builder.addMeasurements(measurements); + RangingReport report = tryBuild(builder, true); + verifyMeasurementsEqual(measurements, report.getMeasurements()); + + + builder = new RangingReport.Builder(); + for (RangingMeasurement measurement : measurements) { + builder.addMeasurement(measurement); + } + report = tryBuild(builder, true); + verifyMeasurementsEqual(measurements, report.getMeasurements()); + } + + private void verifyMeasurementsEqual(List<RangingMeasurement> expected, + List<RangingMeasurement> actual) { + assertEquals(expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { + assertEquals(expected.get(i), actual.get(i)); + } + } + + private RangingReport tryBuild(RangingReport.Builder builder, + boolean expectSuccess) { + RangingReport report = null; + try { + report = builder.build(); + if (!expectSuccess) { + fail("Expected RangingReport.Builder.build() to fail"); + } + } catch (IllegalStateException e) { + if (expectSuccess) { + fail("Expected RangingReport.Builder.build() to succeed"); + } + } + return report; + } + + @Test + public void testParcel() { + Parcel parcel = Parcel.obtain(); + RangingReport report = UwbTestUtils.getRangingReports(5); + report.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + RangingReport fromParcel = RangingReport.CREATOR.createFromParcel(parcel); + assertEquals(report, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java b/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java new file mode 100644 index 000000000000..ccc88a9a5399 --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/UwbAddressTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import static org.junit.Assert.assertEquals; + +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test of {@link UwbAddress}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class UwbAddressTest { + + @Test + public void testFromBytes_Short() { + runFromBytes(UwbAddress.SHORT_ADDRESS_BYTE_LENGTH); + } + + @Test + public void testFromBytes_Extended() { + runFromBytes(UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH); + } + + private void runFromBytes(int len) { + byte[] addressBytes = getByteArray(len); + UwbAddress address = UwbAddress.fromBytes(addressBytes); + assertEquals(address.size(), len); + assertEquals(addressBytes, address.toBytes()); + } + + private byte[] getByteArray(int len) { + byte[] res = new byte[len]; + for (int i = 0; i < len; i++) { + res[i] = (byte) i; + } + return res; + } + + @Test + public void testParcel_Short() { + runParcel(true); + } + + @Test + public void testParcel_Extended() { + runParcel(false); + } + + private void runParcel(boolean useShortAddress) { + Parcel parcel = Parcel.obtain(); + UwbAddress address = UwbTestUtils.getUwbAddress(useShortAddress); + address.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + UwbAddress fromParcel = UwbAddress.CREATOR.createFromParcel(parcel); + assertEquals(address, fromParcel); + } +} diff --git a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java new file mode 100644 index 000000000000..62e0b629539b --- /dev/null +++ b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.uwb; + +import android.os.SystemClock; + +import java.util.ArrayList; +import java.util.List; + +public class UwbTestUtils { + private UwbTestUtils() {} + + public static AngleMeasurement getAngleMeasurement() { + return new AngleMeasurement.Builder() + .setRadians(getDoubleInRange(-Math.PI, Math.PI)) + .setErrorRadians(getDoubleInRange(0, Math.PI)) + .setConfidenceLevel(getDoubleInRange(0, 1)) + .build(); + } + + public static AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() { + return new AngleOfArrivalMeasurement.Builder() + .setAltitudeAngleMeasurement(getAngleMeasurement()) + .setAzimuthAngleMeasurement(getAngleMeasurement()) + .build(); + } + + public static DistanceMeasurement getDistanceMeasurement() { + return new DistanceMeasurement.Builder() + .setMeters(getDoubleInRange(0, 100)) + .setErrorMeters(getDoubleInRange(0, 10)) + .setConfidenceLevel(getDoubleInRange(0, 1)) + .build(); + } + + public static RangingMeasurement getRangingMeasurement() { + return getRangingMeasurement(getUwbAddress(false)); + } + + public static RangingMeasurement getRangingMeasurement(UwbAddress address) { + return new RangingMeasurement.Builder() + .setDistanceMeasurement(getDistanceMeasurement()) + .setAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement()) + .setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()) + .setRemoteDeviceAddress(address != null ? address : getUwbAddress(false)) + .setStatus(RangingMeasurement.RANGING_STATUS_SUCCESS) + .build(); + } + + public static List<RangingMeasurement> getRangingMeasurements(int num) { + List<RangingMeasurement> result = new ArrayList<>(); + for (int i = 0; i < num; i++) { + result.add(getRangingMeasurement()); + } + return result; + } + + public static RangingReport getRangingReports(int numMeasurements) { + RangingReport.Builder builder = new RangingReport.Builder(); + for (int i = 0; i < numMeasurements; i++) { + builder.addMeasurement(getRangingMeasurement()); + } + return builder.build(); + } + + private static double getDoubleInRange(double min, double max) { + return min + (max - min) * Math.random(); + } + + public static UwbAddress getUwbAddress(boolean isShortAddress) { + byte[] addressBytes = new byte[isShortAddress ? UwbAddress.SHORT_ADDRESS_BYTE_LENGTH : + UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH]; + for (int i = 0; i < addressBytes.length; i++) { + addressBytes[i] = (byte) getDoubleInRange(1, 255); + } + return UwbAddress.fromBytes(addressBytes); + } +} diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index f53a7dc922f0..2162b8ac4885 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -48,18 +48,38 @@ public class Credentials { public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER"; - /** Key prefix for CA certificates. */ + /** + * Key prefix for CA certificates. + * + * @deprecated Keystore no longer supports unstructured blobs. Public certificates are + * stored in typed slots associated with a given alias. + */ + @Deprecated public static final String CA_CERTIFICATE = "CACERT_"; - /** Key prefix for user certificates. */ + /** + * Key prefix for user certificates. + * + * @deprecated Keystore no longer supports unstructured blobs. Public certificates are + * stored in typed slots associated with a given alias. + */ + @Deprecated public static final String USER_CERTIFICATE = "USRCERT_"; - /** Key prefix for user private and secret keys. */ + /** + * Key prefix for user private and secret keys. + * + * @deprecated Keystore no longer uses alias prefixes to discriminate between entry types. + */ + @Deprecated public static final String USER_PRIVATE_KEY = "USRPKEY_"; - /** Key prefix for user secret keys. - * @deprecated use {@code USER_PRIVATE_KEY} for this category instead. + /** + * Key prefix for user secret keys. + * + * @deprecated use {@code USER_PRIVATE_KEY} for this category instead. */ + @Deprecated public static final String USER_SECRET_KEY = "USRSKEY_"; /** Key prefix for VPN. */ @@ -71,7 +91,13 @@ public class Credentials { /** Key prefix for WIFI. */ public static final String WIFI = "WIFI_"; - /** Key prefix for App Source certificates. */ + /** + * Key prefix for App Source certificates. + * + * @deprecated This was intended for FS-verity but never used. FS-verity is not + * going to use this constant moving forward. + */ + @Deprecated public static final String APP_SOURCE_CERTIFICATE = "FSV_"; /** Key containing suffix of lockdown VPN profile. */ @@ -149,6 +175,7 @@ public class Credentials { pw.close(); return bao.toByteArray(); } + /** * Convert objects from PEM format, which is used for * CA_CERTIFICATE and USER_CERTIFICATE entries. @@ -166,7 +193,8 @@ public class Credentials { PemObject o; while ((o = pr.readPemObject()) != null) { if (o.getType().equals("CERTIFICATE")) { - Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent())); + Certificate c = cf.generateCertificate( + new ByteArrayInputStream(o.getContent())); result.add((X509Certificate) c); } else { throw new IllegalArgumentException("Unknown type " + o.getType()); diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index d5b34c432e79..1c1c2eeee794 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -16,9 +16,9 @@ package android.security; -import android.app.KeyguardManager; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.KeyguardManager; import android.content.Context; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; @@ -78,8 +78,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final Date mEndDate; - private final int mFlags; - /** * Parameter specification for the "{@code AndroidKeyPairGenerator}" * instance of the {@link java.security.KeyPairGenerator} API. The @@ -144,7 +142,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mSerialNumber = serialNumber; mStartDate = startDate; mEndDate = endDate; - mFlags = flags; } /** @@ -229,7 +226,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * @hide */ public int getFlags() { - return mFlags; + return 0; } /** @@ -243,9 +240,15 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * screen after boot. * * @see KeyguardManager#isDeviceSecure() + * + * @deprecated Encryption at rest is on by default. If extra binding to the lockscreen screen + * credential is desired use + * {@link KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}. + * This flag will be ignored from Android S. */ + @Deprecated public boolean isEncryptionRequired() { - return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0; + return false; } /** @@ -292,8 +295,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private Date mEndDate; - private int mFlags; - /** * Creates a new instance of the {@code Builder} with the given * {@code context}. The {@code context} passed in may be used to pop up @@ -431,10 +432,15 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * secure lock screen after boot. * * @see KeyguardManager#isDeviceSecure() + * + * @deprecated Data at rest encryption is enabled by default. If extra binding to the + * lockscreen credential is desired, use + * {@link KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}. + * This flag will be ignored from Android S. */ @NonNull + @Deprecated public Builder setEncryptionRequired() { - mFlags |= KeyStore.FLAG_ENCRYPTED; return this; } @@ -455,7 +461,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { mSerialNumber, mStartDate, mEndDate, - mFlags); + 0); } } } diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java index 66c87ed2ec1e..51d29b13ce80 100644 --- a/keystore/java/android/security/KeyStoreParameter.java +++ b/keystore/java/android/security/KeyStoreParameter.java @@ -48,18 +48,16 @@ import java.security.KeyStore.ProtectionParameter; */ @Deprecated public final class KeyStoreParameter implements ProtectionParameter { - private final int mFlags; private KeyStoreParameter( int flags) { - mFlags = flags; } /** * @hide */ public int getFlags() { - return mFlags; + return 0; } /** @@ -74,9 +72,16 @@ public final class KeyStoreParameter implements ProtectionParameter { * screen after boot. * * @see KeyguardManager#isDeviceSecure() + * + * @deprecated Data at rest encryption is enabled by default. If extra binding to the + * lockscreen credential is desired, use + * {@link android.security.keystore.KeyGenParameterSpec + * .Builder#setUserAuthenticationRequired(boolean)}. + * This flag will be ignored from Android S. */ + @Deprecated public boolean isEncryptionRequired() { - return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0; + return false; } /** @@ -100,7 +105,6 @@ public final class KeyStoreParameter implements ProtectionParameter { */ @Deprecated public final static class Builder { - private int mFlags; /** * Creates a new instance of the {@code Builder} with the given @@ -126,14 +130,15 @@ public final class KeyStoreParameter implements ProtectionParameter { * the user unlocks the secure lock screen after boot. * * @see KeyguardManager#isDeviceSecure() + * + * @deprecated Data at rest encryption is enabled by default. If extra binding to the + * lockscreen credential is desired, use + * {@link android.security.keystore.KeyGenParameterSpec + * .Builder#setUserAuthenticationRequired(boolean)}. + * This flag will be ignored from Android S. */ @NonNull public Builder setEncryptionRequired(boolean required) { - if (required) { - mFlags |= KeyStore.FLAG_ENCRYPTED; - } else { - mFlags &= ~KeyStore.FLAG_ENCRYPTED; - } return this; } @@ -145,8 +150,7 @@ public final class KeyStoreParameter implements ProtectionParameter { */ @NonNull public KeyStoreParameter build() { - return new KeyStoreParameter( - mFlags); + return new KeyStoreParameter(0 /* flags */); } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index bc03ca617dea..077c7aacd7fb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -23,6 +23,7 @@ import android.app.AlertDialog.Builder; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.os.UserHandle; import android.provider.Settings; import android.service.quicksettings.Tile; import android.telephony.SubscriptionManager; @@ -230,7 +231,8 @@ public class CellularTile extends QSTileImpl<SignalState> { @Override public boolean isAvailable() { - return mController.hasMobileDataFeature(); + return mController.hasMobileDataFeature() + && mHost.getUserContext().getUserId() == UserHandle.USER_SYSTEM; } private static final class CallbackInfo { diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml index 693ca52b4ed1..569617a21f15 100644 --- a/packages/VpnDialogs/AndroidManifest.xml +++ b/packages/VpnDialogs/AndroidManifest.xml @@ -23,6 +23,9 @@ <uses-permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN" /> <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/> + <!-- Query all packages on device on R+ --> + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> + <application android:label="VpnDialogs" android:allowBackup="false"> diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 60e59e389cf0..28afcbbb2a86 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -85,6 +85,7 @@ public class SettingsToPropertiesMapper { DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS, DeviceConfig.NAMESPACE_MEDIA_NATIVE, DeviceConfig.NAMESPACE_NETD_NATIVE, + DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, DeviceConfig.NAMESPACE_RUNTIME_NATIVE, DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT, DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 2991339493a5..8be24a6e2e3d 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3987,7 +3987,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#playSoundEffect(int, float) */ public void playSoundEffectVolume(int effectType, float volume) { // do not try to play the sound effect if the system stream is muted - if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) { + if (isStreamMute(STREAM_SYSTEM)) { return; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 611b8c69077d..ab289ea6f081 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -708,17 +708,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { private byte[] getSupportedShortAudioDescriptorsFromConfig( List<DeviceConfig> deviceConfig, @AudioCodec int[] audioFormatCodes) { DeviceConfig deviceConfigToUse = null; + String audioDeviceName = SystemProperties.get( + Constants.PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT, + "VX_AUDIO_DEVICE_IN_HDMI_ARC"); for (DeviceConfig device : deviceConfig) { - // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name - if (device.name.equals("VX_AUDIO_DEVICE_IN_HDMI_ARC")) { + if (device.name.equals(audioDeviceName)) { deviceConfigToUse = device; break; } } if (deviceConfigToUse == null) { - // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name - Slog.w(TAG, "sadConfig.xml does not have required device info for " - + "VX_AUDIO_DEVICE_IN_HDMI_ARC"); + Slog.w(TAG, "sadConfig.xml does not have required device info for " + audioDeviceName); return new byte[0]; } HashMap<Integer, byte[]> map = new HashMap<>(); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 2c0ddaf35182..804cc92cca08 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1667,6 +1667,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (avr == null) { return; } + setArcStatus(false); // Seq #44. removeAction(RequestArcInitiationAction.class); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index 7d766285bdfa..fe97f701e089 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -122,7 +122,25 @@ public class HdmiCecMessageValidator { addValidationInfo(Constants.MESSAGE_RECORD_STATUS, new RecordStatusInfoValidator(), DEST_DIRECT); - // TODO: Handle messages for the Timer Programming. + addValidationInfo( + Constants.MESSAGE_CLEAR_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_CLEAR_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE, new AsciiValidator(1, 14), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_TIMER_CLEARED_STATUS, + new TimerClearedStatusValidator(), + DEST_DIRECT); + addValidationInfo(Constants.MESSAGE_TIMER_STATUS, new TimerStatusValidator(), DEST_DIRECT); // Messages for the System Information. FixedLengthValidator oneByteValidator = new FixedLengthValidator(1); @@ -343,6 +361,277 @@ public class HdmiCecMessageValidator { return true; } + /** + * Check if the given value is a valid day of month. A valid value is one which falls within the + * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value day of month + * @return true if the day of month is valid + */ + private boolean isValidDayOfMonth(int value) { + return isWithinRange(value, 1, 31); + } + + /** + * Check if the given value is a valid month of year. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value month of year + * @return true if the month of year is valid + */ + private boolean isValidMonthOfYear(int value) { + return isWithinRange(value, 1, 12); + } + + /** + * Check if the given value is a valid hour. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value hour + * @return true if the hour is valid + */ + private boolean isValidHour(int value) { + return isWithinRange(value, 0, 23); + } + + /** + * Check if the given value is a valid minute. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value minute + * @return true if the minute is valid + */ + private boolean isValidMinute(int value) { + return isWithinRange(value, 0, 59); + } + + /** + * Check if the given value is a valid duration hours. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value duration hours + * @return true if the duration hours is valid + */ + private boolean isValidDurationHours(int value) { + return isWithinRange(value, 0, 99); + } + + /** + * Check if the given value is a valid recording sequence. A valid value is adheres to range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value recording sequence + * @return true if the given recording sequence is valid + */ + private boolean isValidRecordingSequence(int value) { + value = value & 0xFF; + // Validate bit 7 is set to zero + if ((value & 0x80) != 0x00) { + return false; + } + // Validate than not more than one bit is set + return (Integer.bitCount(value) <= 1); + } + + /** + * Check if the given value is a valid analogue broadcast type. A valid value is one which falls + * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section + * 17) + * + * @param value analogue broadcast type + * @return true if the analogue broadcast type is valid + */ + private boolean isValidAnalogueBroadcastType(int value) { + return isWithinRange(value, 0x00, 0x02); + } + + /** + * Check if the given value is a valid analogue frequency. A valid value is one which falls + * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section + * 17) + * + * @param value analogue frequency + * @return true if the analogue frequency is valid + */ + private boolean isValidAnalogueFrequency(int value) { + value = value & 0xFFFF; + return (value != 0x000 && value != 0xFFFF); + } + + /** + * Check if the given value is a valid broadcast system. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value broadcast system + * @return true if the broadcast system is valid + */ + private boolean isValidBroadcastSystem(int value) { + return isWithinRange(value, 0, 31); + } + + /** + * Check if the given value is a ARIB type. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is ARIB type + */ + private boolean isAribDbs(int value) { + return (value == 0x00 || isWithinRange(value, 0x08, 0x0A)); + } + + /** + * Check if the given value is a ATSC type. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is ATSC type + */ + private boolean isAtscDbs(int value) { + return (value == 0x01 || isWithinRange(value, 0x10, 0x12)); + } + + /** + * Check if the given value is a DVB type. A valid value is one which falls within the range + * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is DVB type + */ + private boolean isDvbDbs(int value) { + return (value == 0x02 || isWithinRange(value, 0x18, 0x1B)); + } + + /** + * Check if the given value is a valid Digital Broadcast System. A valid value is one which + * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions + * (Section 17) + * + * @param value Digital Broadcast System + * @return true if the Digital Broadcast System is valid + */ + private boolean isValidDigitalBroadcastSystem(int value) { + return (isAribDbs(value) || isAtscDbs(value) || isDvbDbs(value)); + } + + /** + * Check if the given value is a valid Digital Service Identification. A valid value is one + * which falls within the range description defined in CEC 1.4 Specification : Operand + * Descriptions (Section 17) + * + * @param params Digital Timer Message parameters + * @param offset start offset of Digital Service Identification + * @return true if the Digital Service Identification is valid + */ + private boolean isValidDigitalServiceIdentification(byte[] params, int offset) { + // MSB contains Service Identification Method + int serviceIdentificationMethod = params[offset] & 0x80; + // Last 7 bits contains Digital Broadcast System + int digitalBroadcastSystem = params[offset] & 0x7F; + offset = offset + 1; + if (serviceIdentificationMethod == 0x00) { + // Services identified by Digital IDs + if (isAribDbs(digitalBroadcastSystem)) { + // Validate ARIB type have 6 byte data + return params.length - offset >= 6; + } else if (isAtscDbs(digitalBroadcastSystem)) { + // Validate ATSC type have 4 byte data + return params.length - offset >= 4; + } else if (isDvbDbs(digitalBroadcastSystem)) { + // Validate DVB type have 6 byte data + return params.length - offset >= 6; + } + } else if (serviceIdentificationMethod == 0x80) { + // Services identified by Channel + if (isValidDigitalBroadcastSystem(digitalBroadcastSystem)) { + // First 6 bits contain Channel Number Format + int channelNumberFormat = params[offset] & 0xFC; + if (channelNumberFormat == 0x04) { + // Validate it contains 1-part Channel Number data (16 bits) + return params.length - offset >= 3; + } else if (channelNumberFormat == 0x08) { + // Validate it contains Major Channel Number and Minor Channel Number (26 bits) + return params.length - offset >= 4; + } + } + } + return false; + } + + /** + * Check if the given value is a valid External Plug. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value External Plug + * @return true if the External Plug is valid + */ + private boolean isValidExternalPlug(int value) { + return isWithinRange(value, 1, 255); + } + + /** + * Check if the given value is a valid External Source. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value External Source Specifier + * @return true if the External Source is valid + */ + private boolean isValidExternalSource(byte[] params, int offset) { + int externalSourceSpecifier = params[offset]; + offset = offset + 1; + if (externalSourceSpecifier == 0x04) { + // External Plug + return isValidExternalPlug(params[offset]); + } else if (externalSourceSpecifier == 0x05) { + // External Physical Address + // Validate it contains 2 bytes Physical Address + if (params.length - offset >= 2) { + return isValidPhysicalAddress(params, offset); + } + } + return false; + } + + private boolean isValidProgrammedInfo(int programedInfo) { + return (isWithinRange(programedInfo, 0x00, 0x0B)); + } + + private boolean isValidNotProgrammedErrorInfo(int nonProgramedErrorInfo) { + return (isWithinRange(nonProgramedErrorInfo, 0x00, 0x0E)); + } + + private boolean isValidTimerStatusData(byte[] params, int offset) { + int programedIndicator = params[offset] & 0x10; + boolean durationAvailable = false; + if (programedIndicator == 0x10) { + // Programmed + int programedInfo = params[offset] & 0x0F; + if (isValidProgrammedInfo(programedInfo)) { + if (programedInfo == 0x09 || programedInfo == 0x0B) { + durationAvailable = true; + } else { + return true; + } + } + } else { + // Non programmed + int nonProgramedErrorInfo = params[offset] & 0x0F; + if (isValidNotProgrammedErrorInfo(nonProgramedErrorInfo)) { + if (nonProgramedErrorInfo == 0x0E) { + durationAvailable = true; + } else { + return true; + } + } + } + offset = offset + 1; + // Duration Available (2 bytes) + if (durationAvailable && params.length - offset >= 2) { + return (isValidDurationHours(params[offset]) && isValidMinute(params[offset + 1])); + } + return false; + } + private class PhysicalAddressValidator implements ParameterValidator { @Override public int isValid(byte[] params) { @@ -472,4 +761,106 @@ public class HdmiCecMessageValidator { return toErrorCode(isWithinRange(params[0], mMinValue, mMaxValue)); } } + + /** + * Check if the given Analogue Timer message parameters are valid. Valid parameters should + * adhere to message description of Analogue Timer defined in CEC 1.4 Specification : Message + * Descriptions for Timer Programming Feature (CEC Table 12) + */ + private class AnalogueTimerValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 11) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + isValidDayOfMonth(params[0]) // Day of Month + && isValidMonthOfYear(params[1]) // Month of Year + && isValidHour(params[2]) // Start Time - Hour + && isValidMinute(params[3]) // Start Time - Minute + && isValidDurationHours(params[4]) // Duration - Duration Hours + && isValidMinute(params[5]) // Duration - Minute + && isValidRecordingSequence(params[6]) // Recording Sequence + && isValidAnalogueBroadcastType(params[7]) // Analogue Broadcast Type + && isValidAnalogueFrequency( + HdmiUtils.twoBytesToInt(params, 8)) // Analogue Frequency + && isValidBroadcastSystem(params[10])); // Broadcast System + } + } + + /** + * Check if the given Digital Timer message parameters are valid. Valid parameters should adhere + * to message description of Digital Timer defined in CEC 1.4 Specification : Message + * Descriptions for Timer Programming Feature (CEC Table 12) + */ + private class DigitalTimerValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 11) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + isValidDayOfMonth(params[0]) // Day of Month + && isValidMonthOfYear(params[1]) // Month of Year + && isValidHour(params[2]) // Start Time - Hour + && isValidMinute(params[3]) // Start Time - Minute + && isValidDurationHours(params[4]) // Duration - Duration Hours + && isValidMinute(params[5]) // Duration - Minute + && isValidRecordingSequence(params[6]) // Recording Sequence + && isValidDigitalServiceIdentification( + params, 7)); // Digital Service Identification + } + } + + /** + * Check if the given External Timer message parameters are valid. Valid parameters should + * adhere to message description of External Timer defined in CEC 1.4 Specification : Message + * Descriptions for Timer Programming Feature (CEC Table 12) + */ + private class ExternalTimerValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 9) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + isValidDayOfMonth(params[0]) // Day of Month + && isValidMonthOfYear(params[1]) // Month of Year + && isValidHour(params[2]) // Start Time - Hour + && isValidMinute(params[3]) // Start Time - Minute + && isValidDurationHours(params[4]) // Duration - Duration Hours + && isValidMinute(params[5]) // Duration - Minute + && isValidRecordingSequence(params[6]) // Recording Sequence + && isValidExternalSource(params, 7)); // External Source + } + } + + /** + * Check if the given timer cleared status parameter is valid. A valid parameter should lie + * within the range description defined in CEC 1.4 Specification : Operand Descriptions + * (Section 17) + */ + private class TimerClearedStatusValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 1) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isWithinRange(params[0], 0x00, 0x02) || (params[0] & 0xFF) == 0x80); + } + } + + /** + * Check if the given timer status data parameter is valid. A valid parameter should lie within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + */ + private class TimerStatusValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 1) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isValidTimerStatusData(params, 0)); + } + } } diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 72559b4825e7..ddc5ef2000a1 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -24,7 +24,6 @@ import static android.net.TrafficStats.UID_TETHERING; import android.Manifest; import android.annotation.IntDef; import android.app.AppOpsManager; -import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; @@ -112,8 +111,7 @@ public final class NetworkStatsAccess { boolean hasCarrierPrivileges = tm != null && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; - boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { @@ -128,8 +126,9 @@ public final class NetworkStatsAccess { return NetworkStatsAccess.Level.DEVICESUMMARY; } - boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. + boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid) + || dpmi.isActiveDeviceOwner(callingUid)); if (isProfileOwner) { // Apps with the AppOps permission, profile owners, and apps with the privileged // permission can access data usage for all apps in this user/profile. diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 71e7c8adc5db..12c24d418611 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -552,7 +552,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. final PendingIntent pollIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), + PendingIntent.FLAG_IMMUTABLE); final long currentRealtime = SystemClock.elapsedRealtime(); mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 0da47ca90f5e..faf3f06a3035 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -12474,6 +12474,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public boolean isActiveDeviceOwner(int uid) { + synchronized (getLockObject()) { + return getActiveAdminWithPolicyForUidLocked( + null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, uid) != null; + } + } + + @Override + public boolean isActiveProfileOwner(int uid) { + synchronized (getLockObject()) { + return getActiveAdminWithPolicyForUidLocked( + null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, uid) != null; + } + } + + @Override public boolean isActiveSupervisionApp(int uid) { synchronized (getLockObject()) { final ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked( diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index ae693c748e17..2ba94e8557ac 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1226,7 +1226,7 @@ public final class SystemServer { mSystemServiceManager.startService(IorapForwardingService.class); t.traceEnd(); - if (Build.IS_DEBUGGABLE) { + if (Build.IS_DEBUGGABLE && ProfcollectForwardingService.enabled()) { t.traceBegin("ProfcollectForwardingService"); mSystemServiceManager.startService(ProfcollectForwardingService.class); t.traceEnd(); diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index d14ed5a15cf9..19449654f2ec 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -31,6 +31,7 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UpdateEngine; import android.os.UpdateEngineCallback; +import android.provider.DeviceConfig; import android.util.Log; import com.android.server.IoThread; @@ -68,6 +69,14 @@ public final class ProfcollectForwardingService extends SystemService { sSelfService = this; } + /** + * Check whether profcollect is enabled through device config. + */ + public static boolean enabled() { + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, "enabled", + false); + } + @Override public void onStart() { if (DEBUG) { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java index 470294073535..553df3bafd00 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -130,6 +130,17 @@ public class HdmiCecMessageValidatorTest { } @Test + public void isValid_setTimerProgramTitle() { + assertMessageValidity("40:67:47:61:6D:65:20:6F:66:20:54:68:72:6F:6E:65:73").isEqualTo(OK); + assertMessageValidity("40:67:4A").isEqualTo(OK); + + assertMessageValidity("4F:67:47:4F:54").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:67:47:4F:54").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:67").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:67:47:9A:54").isEqualTo(ERROR_PARAMETER); + } + + @Test public void isValid_setMenuLanguage() { assertMessageValidity("4F:32:53:50:41").isEqualTo(OK); assertMessageValidity("0F:32:45:4E:47:8C:49:D3:48").isEqualTo(OK); @@ -182,6 +193,166 @@ public class HdmiCecMessageValidatorTest { assertMessageValidity("40:0A:30").isEqualTo(ERROR_PARAMETER); } + @Test + public void isValid_setAnalogueTimer_clearAnalogueTimer() { + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:13:AD:06").isEqualTo(OK); + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:03:34").isEqualTo(OK); + + assertMessageValidity("0F:33:0C:08:10:1E:04:30:08:00:13:AD:06") + .isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:34:04:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:13:AD:06") + .isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("04:34:20:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("04:33:0C:00:10:1E:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("04:34:04:0C:18:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("04:33:0C:08:10:50:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("04:34:04:0C:16:0F:64:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("04:33:0C:08:10:1E:04:64:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:34:04:0C:16:0F:08:37:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:33:0C:08:10:1E:04:30:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER); + // Out of range Analogue Broadcast Type + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER); + // Out of range Analogue Frequency + assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER); + // Out of range Broadcast System + assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setDigitalTimer_clearDigitalTimer() { + // Services identified by Digital IDs - ARIB Broadcast System + assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30").isEqualTo(OK); + // Service identified by Digital IDs - ATSC Broadcast System + assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39:5A").isEqualTo(OK); + // Service identified by Digital IDs - DVB Broadcast System + assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC").isEqualTo(OK); + // Service identified by Channel - 1 part channel number + assertMessageValidity("04:97:12:06:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(OK); + // Service identified by Channel - 2 part channel number + assertMessageValidity("04:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(OK); + + assertMessageValidity("4F:97:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE); + assertMessageValidity("04:97:1E:12:20:58:01:01:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("04:99:24:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("04:97:12:10:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("04:99:0C:08:20:05:04:1E:00:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("04:97:15:09:00:4B:00:2D:04:82:09:C8:72:C8") + .isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("04:99:1E:07:12:20:78:28:01:01:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("04:97:05:0C:06:0A:19:48:40:19:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:99:12:06:0C:2D:5A:19:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("04:97:0C:08:15:05:04:1E:21:00:C4:C2:11:D8:75:30") + .isEqualTo(ERROR_PARAMETER); + + // Invalid Digital Broadcast System + assertMessageValidity("04:99:1E:07:12:20:50:28:01:04:8B:5E:39:5A") + .isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("04:97:05:0C:06:0A:19:3B:40:93:8B:44:03:11:04:FC") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for ARIB Broadcast system + assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for ATSC Broadcast system + assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER); + // Insufficient data for DVB Broadcast system + assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04") + .isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 part channel number + assertMessageValidity("04:97:15:09:00:0F:00:2D:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER); + // Invalid Channel Number format + assertMessageValidity("04:99:12:06:0C:2D:5A:19:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setExternalTimer_clearExternalTimer() { + assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(OK); + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(OK); + + assertMessageValidity("4F:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F4:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04").isEqualTo(ERROR_PARAMETER_SHORT); + // Out of range Day of Month + assertMessageValidity("40:A2:28:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Month of Year + assertMessageValidity("40:A1:0C:0F:15:05:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Hour + assertMessageValidity("40:A2:14:09:1A:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Start Time - Minute + assertMessageValidity("40:A1:0C:08:15:48:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Duration Hours + assertMessageValidity("40:A2:14:09:12:28:66:19:10:05:10:00").isEqualTo(ERROR_PARAMETER); + // Out of range Duration - Minute + assertMessageValidity("40:A1:0C:08:15:05:04:3F:02:04:20").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("40:A2:14:09:12:28:4B:19:84:05:10:00").isEqualTo(ERROR_PARAMETER); + // Invalid Recording Sequence + assertMessageValidity("40:A1:0C:08:15:05:04:1E:14:04:20").isEqualTo(ERROR_PARAMETER); + // Invalid external source specifier + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER); + // Invalid External PLug + assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_timerClearedStatus() { + assertMessageValidity("40:43:01:7E").isEqualTo(OK); + assertMessageValidity("40:43:80").isEqualTo(OK); + + assertMessageValidity("4F:43:01").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:43:80").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:43").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:43:03").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_timerStatus() { + // Programmed - Space available + assertMessageValidity("40:35:58").isEqualTo(OK); + // Programmed - Not enough space available + assertMessageValidity("40:35:B9:32:1C:4F").isEqualTo(OK); + // Not programmed - Date out of range + assertMessageValidity("40:35:82:3B").isEqualTo(OK); + // Not programmed - Duplicate + assertMessageValidity("40:35:EE:52:0C").isEqualTo(OK); + + assertMessageValidity("4F:35:58").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:35:82").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:35").isEqualTo(ERROR_PARAMETER_SHORT); + // Programmed - Invalid programmed info + assertMessageValidity("40:35:BD").isEqualTo(ERROR_PARAMETER); + // Non programmed - Invalid not programmed error info + assertMessageValidity("40:35:DE").isEqualTo(ERROR_PARAMETER); + // Programmed - Might not be enough space available - Invalid duration hours + assertMessageValidity("40:35:BB:96:1C").isEqualTo(ERROR_PARAMETER); + // Not programmed - Duplicate - Invalid duration minutes + assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER); + } + private IntegerSubject assertMessageValidity(String message) { return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message))); } diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index a85eb53605d6..1238e7b69a87 100755 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -1468,8 +1468,11 @@ public final class Call { /** * Writes the string {@param input} into the outgoing text stream for this RTT call. Since - * RTT transmits text in real-time, this method should be called once for each character - * the user enters into the device. + * RTT transmits text in real-time, this method should be called once for each user action. + * For example, when the user enters text as discrete characters using the keyboard, this + * method should be called once for each character. However, if the user enters text by + * pasting or autocomplete, the entire contents of the pasted or autocompleted text should + * be sent in one call to this method. * * This method is not thread-safe -- calling it from multiple threads simultaneously may * lead to interleaved text. diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index a3cc0abea4ce..2de15991b858 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -1721,6 +1721,7 @@ public final class SmsManager { * * {@hide} */ + @UnsupportedAppUsage @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean deleteMessageFromIcc(int messageIndex) { boolean success = false; diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 2e51ef16baf1..3aa9345fe694 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -1365,6 +1365,7 @@ public class SubscriptionManager { * include those that were inserted before, maybe empty but not null. * @hide */ + @NonNull @UnsupportedAppUsage public List<SubscriptionInfo> getAllSubscriptionInfoList() { if (VDBG) logd("[getAllSubscriptionInfoList]+"); @@ -1382,7 +1383,7 @@ public class SubscriptionManager { } if (result == null) { - result = new ArrayList<>(); + result = Collections.emptyList(); } return result; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 56c2500ee295..73244859c336 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -305,6 +305,8 @@ public class TelephonyManager { private static boolean sServiceHandleCacheEnabled = true; @GuardedBy("sCacheLock") + private static ITelephony sITelephony; + @GuardedBy("sCacheLock") private static IPhoneSubInfo sIPhoneSubInfo; @GuardedBy("sCacheLock") private static ISub sISub; @@ -4185,7 +4187,7 @@ public class TelephonyManager { } } - /** + /** * @param keyAvailability bitmask that defines the availabilty of keys for a type. * @param keyType the key type which is being checked. (WLAN, EPDG) * @return true if the digit at position keyType is 1, else false. @@ -5504,13 +5506,39 @@ public class TelephonyManager { } } - /** - * @hide - */ + /** + * @hide + */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private ITelephony getITelephony() { - return ITelephony.Stub.asInterface(TelephonyFrameworkInitializer - .getTelephonyServiceManager().getTelephonyServiceRegisterer().get()); + // Keeps cache disabled until test fixes are checked into AOSP. + if (!sServiceHandleCacheEnabled) { + return ITelephony.Stub.asInterface( + TelephonyFrameworkInitializer + .getTelephonyServiceManager() + .getTelephonyServiceRegisterer() + .get()); + } + + if (sITelephony == null) { + ITelephony temp = ITelephony.Stub.asInterface( + TelephonyFrameworkInitializer + .getTelephonyServiceManager() + .getTelephonyServiceRegisterer() + .get()); + synchronized (sCacheLock) { + if (sITelephony == null && temp != null) { + try { + sITelephony = temp; + sITelephony.asBinder().linkToDeath(sServiceDeath, 0); + } catch (Exception e) { + // something has gone horribly wrong + sITelephony = null; + } + } + } + } + return sITelephony; } private IOns getIOns() { @@ -9160,8 +9188,10 @@ public class TelephonyManager { * app has carrier privileges (see {@link #hasCarrierPrivileges}). * * @param enable Whether to enable mobile data. + * @deprecated use setDataEnabledForReason with reason DATA_ENABLED_REASON_USER instead. * */ + @Deprecated @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean enable) { @@ -9170,19 +9200,16 @@ public class TelephonyManager { /** * @hide - * @deprecated use {@link #setDataEnabled(boolean)} instead. + * @deprecated use {@link #setDataEnabledForReason(int, boolean)} instead. */ @SystemApi @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int subId, boolean enable) { try { - Log.d(TAG, "setDataEnabled: enabled=" + enable); - ITelephony telephony = getITelephony(); - if (telephony != null) - telephony.setUserDataEnabled(subId, enable); - } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelephony#setUserDataEnabled", e); + setDataEnabledForReason(subId, DATA_ENABLED_REASON_USER, enable); + } catch (RuntimeException e) { + Log.e(TAG, "Error calling setDataEnabledForReason e:" + e); } } @@ -9390,15 +9417,12 @@ public class TelephonyManager { @Deprecated @SystemApi public boolean getDataEnabled(int subId) { - boolean retVal = false; try { - ITelephony telephony = getITelephony(); - if (telephony != null) - retVal = telephony.isUserDataEnabled(subId); - } catch (RemoteException | NullPointerException e) { - Log.e(TAG, "Error calling ITelephony#isUserDataEnabled", e); + return isDataEnabledForReason(DATA_ENABLED_REASON_USER); + } catch (RuntimeException e) { + Log.e(TAG, "Error calling isDataEnabledForReason e:" + e); } - return retVal; + return false; } /** @@ -10956,19 +10980,18 @@ public class TelephonyManager { * * @param enabled control enable or disable carrier data. * @see #resetAllCarrierActions() + * @deprecated use {@link #setDataEnabledForReason(int, boolean) with + * reason {@link #DATA_ENABLED_REASON_CARRIER}} instead. * @hide */ + @Deprecated @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean enabled) { try { - ITelephony service = getITelephony(); - if (service != null) { - service.carrierActionSetMeteredApnsEnabled( - getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled); - } - } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelephony#setCarrierDataEnabled", e); + setDataEnabledForReason(DATA_ENABLED_REASON_CARRIER, enabled); + } catch (RuntimeException e) { + Log.e(TAG, "Error calling setDataEnabledForReason e:" + e); } } @@ -11054,21 +11077,145 @@ public class TelephonyManager { /** * Policy control of data connection. Usually used when data limit is passed. * @param enabled True if enabling the data, otherwise disabling. + * @deprecated use {@link #setDataEnabledForReason(int, boolean) with + * reason {@link #DATA_ENABLED_REASON_POLICY}} instead. * @hide */ + @Deprecated @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setPolicyDataEnabled(boolean enabled) { try { + setDataEnabledForReason(DATA_ENABLED_REASON_POLICY, enabled); + } catch (RuntimeException e) { + Log.e(TAG, "Error calling setDataEnabledForReason e:" + e); + } + } + + /** @hide */ + @IntDef({ + DATA_ENABLED_REASON_USER, + DATA_ENABLED_REASON_POLICY, + DATA_ENABLED_REASON_CARRIER, + DATA_ENABLED_REASON_THERMAL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DataEnabledReason{} + + /** + * To indicate that user enabled or disabled data. + */ + public static final int DATA_ENABLED_REASON_USER = 0; + + /** + * To indicate that data control due to policy. Usually used when data limit is passed. + * Policy data on/off won't affect user settings but will bypass the + * settings and turns off data internally if set to {@code false}. + */ + public static final int DATA_ENABLED_REASON_POLICY = 1; + + /** + * To indicate enable or disable carrier data by the system based on carrier signalling or + * carrier privileged apps. Carrier data on/off won't affect user settings but will bypass the + * settings and turns off data internally if set to {@code false}. + */ + public static final int DATA_ENABLED_REASON_CARRIER = 2; + + /** + * To indicate enable or disable data by thermal service. + * Thermal data on/off won't affect user settings but will bypass the + * settings and turns off data internally if set to {@code false}. + */ + public static final int DATA_ENABLED_REASON_THERMAL = 3; + + /** + * Control of data connection and provide the reason triggering the data connection control. + * This can be called for following reasons + * <ol> + * <li>data limit is passed {@link #DATA_ENABLED_REASON_POLICY} + * <li>data disabled by carrier {@link #DATA_ENABLED_REASON_CARRIER} + * <li>data disabled by user {@link #DATA_ENABLED_REASON_USER} + * <li>data disabled due to thermal {@link #DATA_ENABLED_REASON_THERMAL} + * </ol> + * If any of the reason is off, then it will result in + * bypassing user preference and result in data to be turned off. + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies + * to the given subId. Otherwise, applies to + * {@link SubscriptionManager#getDefaultDataSubscriptionId()} + * + * + * @param reason the reason the data enable change is taking place + * @param enabled True if enabling the data, otherwise disabling. + * + * <p>Requires Permission: + * The calling app has carrier privileges (see {@link #hasCarrierPrivileges}) if the reason is + * {@link #DATA_ENABLED_REASON_USER} or {@link #DATA_ENABLED_REASON_CARRIER} or the call app + * has {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} irrespective of + * the reason. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void setDataEnabledForReason(@DataEnabledReason int reason, boolean enabled) { + setDataEnabledForReason(getSubId(), reason, enabled); + } + + private void setDataEnabledForReason(int subId, @DataEnabledReason int reason, + boolean enabled) { + try { ITelephony service = getITelephony(); if (service != null) { - service.setPolicyDataEnabled(enabled, getSubId()); + service.setDataEnabledForReason(subId, reason, enabled); + } else { + throw new IllegalStateException("telephony service is null."); } - } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelephony#setPolicyDataEnabled", e); + } catch (RemoteException ex) { + Log.e(TAG, "Telephony#setDataEnabledForReason RemoteException", ex); + ex.rethrowFromSystemServer(); } } /** + * Return whether data is enabled for certain reason . + * + * If {@link #isDataEnabledForReason} returns false, it means in data enablement for a + * specific reason is turned off. If any of the reason is off, then it will result in + * bypassing user preference and result in data to be turned off. Call + * {@link #isDataConnectionAllowed} in order to know whether + * data connection is allowed on the device. + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies + * to the given subId. Otherwise, applies to + * {@link SubscriptionManager#getDefaultDataSubscriptionId()} + * + * @param reason the reason the data enable change is taking place + * @return whether data is enabled for a reason. + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or + * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE, + android.Manifest.permission.READ_PHONE_STATE}) + public boolean isDataEnabledForReason(@DataEnabledReason int reason) { + return isDataEnabledForReason(getSubId(), reason); + } + + private boolean isDataEnabledForReason(int subId, @DataEnabledReason int reason) { + try { + ITelephony service = getITelephony(); + if (service != null) { + return service.isDataEnabledForReason(subId, reason); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + Log.e(TAG, "Telephony#isDataEnabledForReason RemoteException", ex); + ex.rethrowFromSystemServer(); + } + return false; + } + + /** * Get Client request stats which will contain statistical information * on each request made by client. * Callers require either READ_PRIVILEGED_PHONE_STATE or @@ -11203,10 +11350,14 @@ public class TelephonyManager { * <LI>And possibly others.</LI> * </UL> * @return {@code true} if the overall data connection is allowed; {@code false} if not. - * @hide + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or + * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} or + * android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE */ - @SystemApi - @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE, + android.Manifest.permission.READ_PHONE_STATE, + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}) public boolean isDataConnectionAllowed() { boolean retVal = false; try { @@ -13321,6 +13472,10 @@ public class TelephonyManager { */ private static void resetServiceCache() { synchronized (sCacheLock) { + if (sITelephony != null) { + sITelephony.asBinder().unlinkToDeath(sServiceDeath, 0); + sITelephony = null; + } if (sISub != null) { sISub.asBinder().unlinkToDeath(sServiceDeath, 0); sISub = null; @@ -13337,9 +13492,9 @@ public class TelephonyManager { } } - /** - * @hide - */ + /** + * @hide + */ static IPhoneSubInfo getSubscriberInfoService() { // Keeps cache disabled until test fixes are checked into AOSP. if (!sServiceHandleCacheEnabled) { diff --git a/telephony/java/android/telephony/ims/AudioCodecAttributes.aidl b/telephony/java/android/telephony/ims/AudioCodecAttributes.aidl new file mode 100644 index 000000000000..bbab548bcd37 --- /dev/null +++ b/telephony/java/android/telephony/ims/AudioCodecAttributes.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.telephony.ims; + +parcelable AudioCodecAttributes; diff --git a/telephony/java/android/telephony/ims/AudioCodecAttributes.java b/telephony/java/android/telephony/ims/AudioCodecAttributes.java new file mode 100644 index 000000000000..7b6ab00b93e4 --- /dev/null +++ b/telephony/java/android/telephony/ims/AudioCodecAttributes.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Range; + +/** + * Parcelable object to handle audio codec attributes. + * It provides the audio codec bitrate, bandwidth and their upper/lower bound. + * + * @hide + */ +@SystemApi +public final class AudioCodecAttributes implements Parcelable { + // The audio codec bitrate in kbps. + private float mBitrateKbps; + // The range of the audio codec bitrate in kbps. + private Range<Float> mBitrateRangeKbps; + // The audio codec bandwidth in kHz. + private float mBandwidthKhz; + // The range of the audio codec bandwidth in kHz. + private Range<Float> mBandwidthRangeKhz; + + + /** + * Constructor. + * + * @param bitrateKbps The audio codec bitrate in kbps. + * @param bitrateRangeKbps The range of the audio codec bitrate in kbps. + * @param bandwidthKhz The audio codec bandwidth in kHz. + * @param bandwidthRangeKhz The range of the audio codec bandwidth in kHz. + */ + + public AudioCodecAttributes(float bitrateKbps, @NonNull Range<Float> bitrateRangeKbps, + float bandwidthKhz, @NonNull Range<Float> bandwidthRangeKhz) { + mBitrateKbps = bitrateKbps; + mBitrateRangeKbps = bitrateRangeKbps; + mBandwidthKhz = bandwidthKhz; + mBandwidthRangeKhz = bandwidthRangeKhz; + } + + private AudioCodecAttributes(Parcel in) { + mBitrateKbps = in.readFloat(); + mBitrateRangeKbps = new Range<>(in.readFloat(), in.readFloat()); + mBandwidthKhz = in.readFloat(); + mBandwidthRangeKhz = new Range<>(in.readFloat(), in.readFloat()); + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeFloat(mBitrateKbps); + out.writeFloat(mBitrateRangeKbps.getLower()); + out.writeFloat(mBitrateRangeKbps.getUpper()); + out.writeFloat(mBandwidthKhz); + out.writeFloat(mBandwidthRangeKhz.getLower()); + out.writeFloat(mBandwidthRangeKhz.getUpper()); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<AudioCodecAttributes> CREATOR = + new Creator<AudioCodecAttributes>() { + @Override + public AudioCodecAttributes createFromParcel(Parcel in) { + return new AudioCodecAttributes(in); + } + + @Override + public AudioCodecAttributes[] newArray(int size) { + return new AudioCodecAttributes[size]; + } + }; + + /** + * @return the exact value of the audio codec bitrate in kbps. + */ + public float getBitrateKbps() { + return mBitrateKbps; + } + + /** + * @return the range of the audio codec bitrate in kbps + */ + public @NonNull Range<Float> getBitrateRangeKbps() { + return mBitrateRangeKbps; + } + + /** + * @return the exact value of the audio codec bandwidth in kHz. + */ + public float getBandwidthKhz() { + return mBandwidthKhz; + } + + /** + * @return the range of the audio codec bandwidth in kHz. + */ + public @NonNull Range<Float> getBandwidthRangeKhz() { + return mBandwidthRangeKhz; + } + + @NonNull + @Override + public String toString() { + return "{ bitrateKbps=" + mBitrateKbps + + ", bitrateRangeKbps=" + mBitrateRangeKbps + + ", bandwidthKhz=" + mBandwidthKhz + + ", bandwidthRangeKhz=" + mBandwidthRangeKhz + " }"; + } +} diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index 94407f1dcd3a..8b6dac82b0eb 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -29,12 +29,10 @@ import android.os.RemoteException; import android.provider.Settings; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.feature.ImsFeature; -import android.telephony.ims.feature.RcsFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; @@ -77,7 +75,7 @@ public class ImsRcsManager { "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; /** - * Receives RCS availability status updates from the ImsService. + * Receives RCS Feature availability status updates from the ImsService. * * @see #isAvailable(int) * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) @@ -101,8 +99,7 @@ public class ImsRcsManager { long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged( - new RcsFeature.RcsImsCapabilities(config))); + mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config)); } finally { restoreCallingIdentity(callingIdentity); } @@ -137,7 +134,7 @@ public class ImsRcsManager { * * @param capabilities The new availability of the capabilities. */ - public void onAvailabilityChanged(@NonNull RcsFeature.RcsImsCapabilities capabilities) { + public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { } /**@hide*/ @@ -394,7 +391,7 @@ public class ImsRcsManager { * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { @@ -428,7 +425,7 @@ public class ImsRcsManager { * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) + public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java index 131cb1a505fb..4aca48b58582 100644 --- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java +++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java @@ -17,6 +17,7 @@ package android.telephony.ims; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -89,6 +90,9 @@ public final class ImsStreamMediaProfile implements Parcelable { /** @hide */ @UnsupportedAppUsage public int mAudioDirection; + // Audio codec attributes + private AudioCodecAttributes mAudioCodecAttributes; + // Video related information /** @hide */ public int mVideoQuality; @@ -190,6 +194,7 @@ public final class ImsStreamMediaProfile implements Parcelable { public void copyFrom(ImsStreamMediaProfile profile) { mAudioQuality = profile.mAudioQuality; mAudioDirection = profile.mAudioDirection; + mAudioCodecAttributes = profile.mAudioCodecAttributes; mVideoQuality = profile.mVideoQuality; mVideoDirection = profile.mVideoDirection; mRttMode = profile.mRttMode; @@ -198,12 +203,13 @@ public final class ImsStreamMediaProfile implements Parcelable { @NonNull @Override public String toString() { - return "{ audioQuality=" + mAudioQuality + - ", audioDirection=" + mAudioDirection + - ", videoQuality=" + mVideoQuality + - ", videoDirection=" + mVideoDirection + - ", rttMode=" + mRttMode + - ", hasRttAudioSpeech=" + mIsReceivingRttAudio + " }"; + return "{ audioQuality=" + mAudioQuality + + ", audioDirection=" + mAudioDirection + + ", audioCodecAttribute=" + mAudioCodecAttributes + + ", videoQuality=" + mVideoQuality + + ", videoDirection=" + mVideoDirection + + ", rttMode=" + mRttMode + + ", hasRttAudioSpeech=" + mIsReceivingRttAudio + " }"; } @Override @@ -215,6 +221,7 @@ public final class ImsStreamMediaProfile implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(mAudioQuality); out.writeInt(mAudioDirection); + out.writeTypedObject(mAudioCodecAttributes, flags); out.writeInt(mVideoQuality); out.writeInt(mVideoDirection); out.writeInt(mRttMode); @@ -224,6 +231,7 @@ public final class ImsStreamMediaProfile implements Parcelable { private void readFromParcel(Parcel in) { mAudioQuality = in.readInt(); mAudioDirection = in.readInt(); + mAudioCodecAttributes = in.readTypedObject(AudioCodecAttributes.CREATOR); mVideoQuality = in.readInt(); mVideoDirection = in.readInt(); mRttMode = in.readInt(); @@ -274,6 +282,23 @@ public final class ImsStreamMediaProfile implements Parcelable { return mAudioDirection; } + /** + * Get the audio codec attributes {@link AudioCodecAttributes} which may be {@code null} if + * ImsService doesn't support this information. + * @return audio codec attributes + */ + public @Nullable AudioCodecAttributes getAudioCodecAttributes() { + return mAudioCodecAttributes; + } + + /** + * Set the audio codec attributes {@link AudioCodecAttributes} which includes bitrate and + * bandwidth information. + */ + public void setAudioCodecAttributes(@NonNull AudioCodecAttributes audioCodecAttributes) { + mAudioCodecAttributes = audioCodecAttributes; + } + public int getVideoQuality() { return mVideoQuality; } diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl new file mode 100644 index 000000000000..cd1ee8400d3e --- /dev/null +++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.telephony.ims; + +parcelable RcsContactTerminatedReason; diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java new file mode 100644 index 000000000000..ee02564267c0 --- /dev/null +++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.annotation.NonNull; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * When the resource for the presence subscribe event has been terminated, the method + * SubscribeResponseCallback#onResourceTerminated wil be called with a list of + * RcsContactTerminatedReason. + * @hide + */ +public final class RcsContactTerminatedReason implements Parcelable { + private final Uri mContactUri; + private final String mReason; + + public RcsContactTerminatedReason(Uri contact, String reason) { + mContactUri = contact; + mReason = reason; + } + + private RcsContactTerminatedReason(Parcel in) { + mContactUri = in.readParcelable(Uri.class.getClassLoader()); + mReason = in.readString(); + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(mContactUri, flags); + out.writeString(mReason); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<RcsContactTerminatedReason> CREATOR = + new Creator<RcsContactTerminatedReason>() { + @Override + public RcsContactTerminatedReason createFromParcel(Parcel in) { + return new RcsContactTerminatedReason(in); + } + + @Override + public RcsContactTerminatedReason[] newArray(int size) { + return new RcsContactTerminatedReason[size]; + } + }; + + public Uri getContactUri() { + return mContactUri; + } + + public String getReason() { + return mReason; + } +} diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 0c88ade4bb77..0aeaecc2af5e 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -47,6 +47,30 @@ public class RcsUceAdapter { private static final String TAG = "RcsUceAdapter"; /** + * This carrier supports User Capability Exchange as, defined by the framework using + * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0; + + /** + * This carrier supports User Capability Exchange as, defined by the framework using a + * presence server. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "CAPABILITY_TYPE_", value = { + CAPABILITY_TYPE_OPTIONS_UCE, + CAPABILITY_TYPE_PRESENCE_UCE + }) + public @interface RcsImsCapabilityFlag {} + + /** * An unknown error has caused the request to fail. * @hide */ @@ -106,11 +130,6 @@ public class RcsUceAdapter { * @hide */ public static final int ERROR_LOST_NETWORK = 12; - /** - * The request has failed because the same request has already been added to the queue. - * @hide - */ - public static final int ERROR_ALREADY_IN_QUEUE = 13; /**@hide*/ @Retention(RetentionPolicy.SOURCE) @@ -125,12 +144,90 @@ public class RcsUceAdapter { ERROR_REQUEST_TOO_LARGE, ERROR_REQUEST_TIMEOUT, ERROR_INSUFFICIENT_MEMORY, - ERROR_LOST_NETWORK, - ERROR_ALREADY_IN_QUEUE + ERROR_LOST_NETWORK }) public @interface ErrorCode {} /** + * A capability update has been requested due to the Entity Tag (ETag) expiring. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; + /** + * A capability update has been requested due to moving to LTE with VoPS disabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; + /** + * A capability update has been requested due to moving to LTE with VoPS enabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; + /** + * A capability update has been requested due to moving to eHRPD. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; + /** + * A capability update has been requested due to moving to HSPA+. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; + /** + * A capability update has been requested due to moving to 3G. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; + /** + * A capability update has been requested due to moving to 2G. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; + /** + * A capability update has been requested due to moving to WLAN + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; + /** + * A capability update has been requested due to moving to IWLAN + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; + /** + * A capability update has been requested but the reason is unknown. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; + /** + * A capability update has been requested due to moving to 5G NR with VoPS disabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; + /** + * A capability update has been requested due to moving to 5G NR with VoPS enabled. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "ERROR_", value = { + CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN, + CAPABILITY_UPDATE_TRIGGER_UNKNOWN, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED + }) + public @interface StackPublishTriggerType {} + + /** * The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for * UCE. * @hide @@ -205,7 +302,7 @@ public class RcsUceAdapter { public void onPublishStateChanged(int publishState) { if (mLocalCallback == null) return; - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { mExecutor.execute(() -> mLocalCallback.onChanged(publishState)); } finally { @@ -238,38 +335,49 @@ public class RcsUceAdapter { } /** - * Provides a one-time callback for the response to a UCE request. After this callback is called - * by the framework, the reference to this callback will be discarded on the service side. + * A callback for the response to a UCE request. The method + * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the + * capabilities are received for each requested contact. + * <p> + * This request will take a varying amount of time depending on if the contacts requested are + * cached or if it requires a network query. The timeout time of these requests can vary + * depending on the network, however in poor cases it could take up to a minute for a request + * to timeout. In that time only a subset of capabilities may have been retrieved. + * <p> + * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has + * been called, the reference to this callback will be discarded on the service side. * @see #requestCapabilities(Executor, List, CapabilitiesCallback) * @hide */ - public static class CapabilitiesCallback { + public interface CapabilitiesCallback { /** - * Notify this application that the pending capability request has returned successfully. + * Notify this application that the pending capability request has returned successfully + * for one or more of the requested contacts. * @param contactCapabilities List of capabilities associated with each contact requested. */ - public void onCapabilitiesReceived( - @NonNull List<RcsContactUceCapability> contactCapabilities) { + void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities); - } + /** + * The pending request has completed successfully due to all requested contacts information + * being delivered. + */ + void onComplete(); /** * The pending request has resulted in an error and may need to be retried, depending on the * error code. * @param errorCode The reason for the framework being unable to process the request. */ - public void onError(@ErrorCode int errorCode) { - - } + void onError(@ErrorCode int errorCode); } private final Context mContext; private final int mSubId; /** - * Not to be instantiated directly, use - * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class. + * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate + * this manager class. * @hide */ RcsUceAdapter(Context context, int subId) { @@ -280,6 +388,9 @@ public class RcsUceAdapter { /** * Request the User Capability Exchange capabilities for one or more contacts. * <p> + * This will return the cached capabilities of the contact and will not perform a capability + * poll on the network unless there are contacts being queried with stale information. + * <p> * Be sure to check the availability of this feature using * {@link ImsRcsManager#isAvailable(int)} and ensuring * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or @@ -302,7 +413,7 @@ public class RcsUceAdapter { @NonNull List<Uri> contactNumbers, @NonNull CapabilitiesCallback c) throws ImsException { if (c == null) { - throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); + throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); } if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); @@ -321,7 +432,7 @@ public class RcsUceAdapter { IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { @Override public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities)); @@ -330,8 +441,17 @@ public class RcsUceAdapter { } } @Override + public void onComplete() { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onComplete()); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override public void onError(int errorCode) { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { executor.execute(() -> c.onError(errorCode)); } finally { @@ -351,6 +471,88 @@ public class RcsUceAdapter { } /** + * Ignore the device cache and perform a capability discovery for one contact, also called + * "availability fetch." + * <p> + * This will always perform a query to the network as long as requests are over the carrier + * availability fetch throttling threshold. If too many network requests are sent too quickly, + * #ERROR_TOO_MANY_REQUESTS will be returned. + * + * <p> + * Be sure to check the availability of this feature using + * {@link ImsRcsManager#isAvailable(int)} and ensuring + * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or + * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is + * enabled or else this operation will fail with + * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}. + * + * @param contactNumber The contact of the capabilities is being requested for. + * @param c A one-time callback for when the request for capabilities completes or there is + * an error processing the request. + * @hide + */ + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void requestNetworkAvailability(@NonNull @CallbackExecutor Executor executor, + @NonNull Uri contactNumber, @NonNull CapabilitiesCallback c) throws ImsException { + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + if (contactNumber == null) { + throw new IllegalArgumentException("Must include non-null contact number."); + } + if (c == null) { + throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); + } + + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "requestNetworkAvailability: IImsRcsController is null"); + throw new ImsException("Cannot find remote IMS service", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + + IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { + @Override + public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> + c.onCapabilitiesReceived(contactCapabilities)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override + public void onComplete() { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onComplete()); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override + public void onError(int errorCode) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onError(errorCode)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + }; + + try { + imsRcsController.requestNetworkAvailability(mSubId, mContext.getOpPackageName(), + mContext.getAttributionTag(), contactNumber, internalCallback); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#requestNetworkAvailability", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + /** * Gets the last publish result from the UCE service if the device is using an RCS presence * server. * @return The last publish result from the UCE service. If the device is using SIP OPTIONS, diff --git a/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl new file mode 100644 index 000000000000..a4ffbef9fa84 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.net.Uri; +import android.telephony.ims.aidl.IOptionsRequestCallback; + +import java.util.List; + +/** + * Listener interface for the ImsService to use to notify the framework of UCE events. + * {@hide} + */ +oneway interface ICapabilityExchangeEventListener { + /** + * Trigger the framework to provide a capability update using + * {@link RcsCapabilityExchangeImplBase#publishCapabilities}. + * <p> + * This is typically used when trying to generate an initial PUBLISH for a new + * subscription to the network. The device will cache all presence publications + * after boot until this method is called the first time. + * @param publishTriggerType {@link StackPublishTriggerType} The reason for the + * capability update request. + * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the + * {@link RcsFeature} has not received the + * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare + * cases when the Telephony stack has crashed. + */ + void onRequestPublishCapabilities(int publishTriggerType); + + /** + * Notify the framework that the device's capabilities have been unpublished from the network. + * + * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently + * connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the + * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the + * Telephony stack has crashed. + */ + void onUnpublish(); + + /** + * Inform the framework of a query for this device's UCE capabilities. + * <p> + * The framework will respond via the + * {@link IOptionsRequestCallback#respondToCapabilityRequest} or + * {@link IOptionsRequestCallback#respondToCapabilityRequestWithError} method. + * @param contactUri The URI associated with the remote contact that is requesting capabilities. + * @param remoteCapabilities The remote contact's capability information. + * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently + * connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when + * the Telephony stack has crashed. + */ + void onRemoteCapabilityRequest(in Uri contactUri, + in List<String> remoteCapabilities, + IOptionsRequestCallback cb); +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl index 6d25a09e079f..8e84e9373f65 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -47,6 +47,9 @@ interface IImsRcsController { // ImsUceAdapter specific void requestCapabilities(int subId, String callingPackage, String callingFeatureId, in List<Uri> contactNumbers, IRcsUceControllerCallback c); + void requestNetworkAvailability(int subId, String callingPackage, + String callingFeatureId, in Uri contactNumber, + IRcsUceControllerCallback c); int getUcePublishState(int subId); boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId); void setUceSettingEnabled(int subId, boolean isEnabled); diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl index 4b98b79f1095..b47e3c75b558 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl @@ -18,8 +18,12 @@ package android.telephony.ims.aidl; import android.net.Uri; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.IOptionsResponseCallback; +import android.telephony.ims.aidl.IPublishResponseCallback; import android.telephony.ims.aidl.IRcsFeatureListener; +import android.telephony.ims.aidl.ISubscribeResponseCallback; import android.telephony.ims.feature.CapabilityChangeRequest; import java.util.List; @@ -40,6 +44,12 @@ interface IImsRcsFeature { IImsCapabilityCallback c); oneway void queryCapabilityConfiguration(int capability, int radioTech, IImsCapabilityCallback c); + // RcsCapabilityExchangeImplBase specific api + oneway void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener); + oneway void publishCapabilities(in String pidfXml, IPublishResponseCallback cb); + oneway void subscribeForCapabilities(in List<Uri> uris, ISubscribeResponseCallback cb); + oneway void sendOptionsCapabilityRequest(in Uri contactUri, + in List<String> myCapabilities, IOptionsResponseCallback cb); // RcsPresenceExchangeImplBase specific api oneway void requestCapabilities(in List<Uri> uris, int operationToken); oneway void updateCapabilities(in RcsContactUceCapability capabilities, int operationToken); @@ -50,4 +60,4 @@ interface IImsRcsFeature { in RcsContactUceCapability ownCapabilities, int operationToken); oneway void respondToCapabilityRequestWithError(in Uri contactUri, int code, in String reason, int operationToken); -}
\ No newline at end of file +} diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl new file mode 100644 index 000000000000..d55670dd313b --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.telephony.ims.RcsContactUceCapability; + +/** + * Interface used by the framework to respond to OPTIONS requests. + * {@hide} + */ +oneway interface IOptionsRequestCallback { + /** + * Respond to a remote capability request from the contact specified with the capabilities + * of this device. + * @param ownCapabilities The capabilities of this device. + */ + void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities); + + /** + * Respond to a remote capability request from the contact specified with the + * specified error. + * @param contactUri A URI containing the remote contact. + * @param code The SIP response code to respond with. + * @param reason A non-null String containing the reason associated with the SIP code. + */ + void respondToCapabilityRequestWithError(int code, String reason); +} diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl new file mode 100644 index 000000000000..a8c8329fe55e --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import java.util.List; + +/** + * Interface used by the framework to receive the response from the remote user + * through {@link RcsCapabilityExchangeImplBase#sendOptionsCapabilityRequest} + * {@hide} + */ +oneway interface IOptionsResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, String reason, in List<String> theirCaps); +} diff --git a/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl new file mode 100644 index 000000000000..481e7f8b37b9 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import java.util.List; + +/** + * Interface used by the framework to receive the response of the publish + * request through {@link RcsCapabilityExchangeImplBase#publishCapabilities} + * {@hide} + */ +oneway interface IPublishResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, String reason); +} diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl index 5975930d5cfa..0bd3e5ed354e 100644 --- a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl @@ -25,5 +25,6 @@ import android.telephony.ims.RcsContactUceCapability; */ oneway interface IRcsUceControllerCallback { void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities); + void onComplete(); void onError(int errorCode); } diff --git a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl new file mode 100644 index 000000000000..4deaba1b7a49 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.net.Uri; +import android.telephony.ims.RcsContactTerminatedReason; + +import java.util.List; +import java.util.Map; + +/** + * Interface used by the framework to receive the response of the subscribe + * request through {@link RcsCapabilityExchangeImplBase#subscribeForCapabilities} + * {@hide} + */ +oneway interface ISubscribeResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, in String reason); + void onNotifyCapabilitiesUpdate(in List<String> pidfXmls); + void onResourceTerminated(in List<RcsContactTerminatedReason> uriTerminatedReason); + void onTerminated(in String reason, in String retryAfter); +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java new file mode 100644 index 000000000000..47a96af1cba1 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback; + +import java.util.List; + +/** + * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsOptionsResponseAidlWrapper implements OptionsResponseCallback { + + private final IOptionsResponseCallback mResponseBinder; + + public RcsOptionsResponseAidlWrapper(IOptionsResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason, List<String> theirCaps) + throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason, theirCaps); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java new file mode 100644 index 000000000000..22985d0cf85c --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback; + +/** + * Implementation of the callback PublishResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsPublishResponseAidlWrapper implements PublishResponseCallback { + + private final IPublishResponseCallback mResponseBinder; + + public RcsPublishResponseAidlWrapper(IPublishResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason) throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java new file mode 100644 index 000000000000..37588ed98585 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.aidl; + +import android.net.Uri; +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.RcsContactTerminatedReason; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallback { + + private final ISubscribeResponseCallback mResponseBinder; + + public RcsSubscribeResponseAidlWrapper(ISubscribeResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason) throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason); + } catch (RemoteException e) { + } + } + + @Override + public void onNotifyCapabilitiesUpdate(List<String> pidfXmls) throws ImsException { + try { + mResponseBinder.onNotifyCapabilitiesUpdate(pidfXmls); + } catch (RemoteException e) { + } + } + + @Override + public void onResourceTerminated(List<Pair<Uri, String>> uriTerminatedReason) + throws ImsException { + try { + mResponseBinder.onResourceTerminated(getTerminatedReasonList(uriTerminatedReason)); + } catch (RemoteException e) { + } + } + + private List<RcsContactTerminatedReason> getTerminatedReasonList( + List<Pair<Uri, String>> uriTerminatedReason) { + List<RcsContactTerminatedReason> uriTerminatedReasonList = new ArrayList<>(); + if (uriTerminatedReason != null) { + for (Pair<Uri, String> pair : uriTerminatedReason) { + RcsContactTerminatedReason reason = + new RcsContactTerminatedReason(pair.first, pair.second); + uriTerminatedReasonList.add(reason); + } + } + return uriTerminatedReasonList; + } + + @Override + public void onTerminated(String reason, String retryAfter) throws ImsException { + try { + mResponseBinder.onTerminated(reason, retryAfter); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 87a5094a95f3..87a6873d00b2 100644 --- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.Set; /** - * Request to send to IMS provider, which will try to enable/disable capabilities that are added to - * the request. + * Used by the framework to enable and disable MMTEL and RCS capabilities. See + * MmTelFeature#changeEnabledCapabilities and RcsFeature#changeEnabledCapabilities. * {@hide} */ @SystemApi diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index b8ae146784d4..5de2ddc578a1 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -23,12 +23,22 @@ import android.annotation.SystemApi; import android.net.Uri; import android.os.RemoteException; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.RcsUceAdapter; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsFeature; +import android.telephony.ims.aidl.IOptionsResponseCallback; +import android.telephony.ims.aidl.IPublishResponseCallback; import android.telephony.ims.aidl.IRcsFeatureListener; +import android.telephony.ims.aidl.ISubscribeResponseCallback; +import android.telephony.ims.aidl.RcsOptionsResponseAidlWrapper; +import android.telephony.ims.aidl.RcsPublishResponseAidlWrapper; +import android.telephony.ims.aidl.RcsSubscribeResponseAidlWrapper; import android.telephony.ims.stub.ImsRegistrationImplBase; -import android.telephony.ims.stub.RcsPresenceExchangeImplBase; -import android.telephony.ims.stub.RcsSipOptionsImplBase; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback; import android.util.Log; import com.android.internal.telephony.util.TelephonyUtils; @@ -64,9 +74,14 @@ public class RcsFeature extends ImsFeature { mExecutor = executor; } + /** + * @deprecated This method is deprecated. Please call the method + * setCapabilityExchangeEventListener instead. + */ @Override + @Deprecated public void setListener(IRcsFeatureListener listener) { - mReference.setListener(listener); + Log.w(LOG_TAG, "The method setListener is deprecated"); } @Override @@ -106,44 +121,66 @@ public class RcsFeature extends ImsFeature { return executeMethodAsyncForResult(mReference::getFeatureState, "getFeatureState"); } + // RcsCapabilityExchangeImplBase specific APIs + @Override + public void setCapabilityExchangeEventListener( + @NonNull ICapabilityExchangeEventListener listener) throws RemoteException { + executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener), + "setCapabilityExchangeEventListener"); + } + + @Override + public void publishCapabilities(@NonNull String pidfXml, + @NonNull IPublishResponseCallback callback) throws RemoteException { + PublishResponseCallback callbackWrapper = new RcsPublishResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .publishCapabilities(pidfXml, callbackWrapper), "publishCapabilities"); + } + + @Override + public void subscribeForCapabilities(@NonNull List<Uri> uris, + @NonNull ISubscribeResponseCallback callback) throws RemoteException { + SubscribeResponseCallback wrapper = new RcsSubscribeResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .subscribeForCapabilities(uris, wrapper), "subscribeForCapabilities"); + } + + @Override + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> myCapabilities, @NonNull IOptionsResponseCallback callback) + throws RemoteException { + OptionsResponseCallback callbackWrapper = new RcsOptionsResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .sendOptionsCapabilityRequest(contactUri, myCapabilities, callbackWrapper), + "sendOptionsCapabilityRequest"); + } + // RcsPresenceExchangeImplBase specific APIS @Override public void requestCapabilities(List<Uri> uris, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getPresenceExchangeInternal() - .requestCapabilities(uris, operationToken), "requestCapabilities"); + throw new RemoteException("Unsupported operation: requestCapabilities"); } @Override public void updateCapabilities(RcsContactUceCapability capabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getPresenceExchangeInternal() - .updateCapabilities(capabilities, operationToken), - "updateCapabilities"); - + throw new RemoteException("Unsupported operation: updateCapabilities"); } // RcsSipOptionsImplBase specific APIS @Override public void sendCapabilityRequest(Uri contactUri, RcsContactUceCapability capabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .sendCapabilityRequest(contactUri, capabilities, operationToken), - "sendCapabilityRequest"); - + throw new RemoteException("Unsupported operation: sendCapabilityRequest"); } @Override public void respondToCapabilityRequest(String contactUri, RcsContactUceCapability ownCapabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .respondToCapabilityRequest(contactUri, ownCapabilities, - operationToken), "respondToCapabilityRequest"); - + throw new RemoteException("Unsupported operation: respondToCapabilityRequest"); } @Override public void respondToCapabilityRequestWithError(Uri contactUri, int code, String reason, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .respondToCapabilityRequestWithError(contactUri, code, reason, - operationToken), "respondToCapabilityRequestWithError"); + throw new RemoteException("Unsupported operation: respondToCapabilityRequestWithError"); } // Call the methods with a clean calling identity on the executor and wait indefinitely for @@ -182,8 +219,8 @@ public class RcsFeature extends ImsFeature { * Contains the capabilities defined and supported by a {@link RcsFeature} in the * form of a bitmask. The capabilities that are used in the RcsFeature are * defined as: - * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} - * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} + * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} + * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} * * The enabled capabilities of this RcsFeature will be set by the framework * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. @@ -223,7 +260,7 @@ public class RcsFeature extends ImsFeature { */ public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; - public RcsImsCapabilities(@RcsImsCapabilityFlag int capabilities) { + public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super(capabilities); } @@ -232,25 +269,24 @@ public class RcsFeature extends ImsFeature { } @Override - public void addCapabilities(@RcsImsCapabilityFlag int capabilities) { + public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.addCapabilities(capabilities); } @Override - public void removeCapabilities(@RcsImsCapabilityFlag int capabilities) { + public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.removeCapabilities(capabilities); } @Override - public boolean isCapable(@RcsImsCapabilityFlag int capabilities) { + public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { return super.isCapable(capabilities); } } private final RcsFeatureBinder mImsRcsBinder; - private IRcsFeatureListener mListenerBinder; - private RcsPresenceExchangeImplBase mPresExchange; - private RcsSipOptionsImplBase mSipOptions; + private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl; + private ICapabilityExchangeEventListener mCapExchangeEventListener; /** * Create a new RcsFeature. @@ -314,7 +350,7 @@ public class RcsFeature extends ImsFeature { * @hide */ public boolean queryCapabilityConfiguration( - @RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { // Base Implementation - Override to provide functionality return false; @@ -342,37 +378,22 @@ public class RcsFeature extends ImsFeature { } /** - * Retrieve the implementation of SIP OPTIONS for this {@link RcsFeature}. - * <p> - * Will only be requested by the framework if capability exchange via SIP OPTIONS is - * configured as capable during a - * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} - * operation and the RcsFeature sets the status of the capability to true using - * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. + * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either + * presence or OPTIONS for capability exchange. * - * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if - * it is supported by the device. - * @hide - */ - public @NonNull RcsSipOptionsImplBase getOptionsExchangeImpl() { - // Base Implementation, override to implement functionality - return new RcsSipOptionsImplBase(); - } - - /** - * Retrieve the implementation of UCE presence for this {@link RcsFeature}. - * Will only be requested by the framework if presence exchang is configured as capable during - * a {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} + * Will only be requested by the framework if capability exchange is configured + * as capable during a + * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} * operation and the RcsFeature sets the status of the capability to true using * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. * - * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence + * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements presence * exchange if it is supported by the device. * @hide */ - public @NonNull RcsPresenceExchangeImplBase getPresenceExchangeImpl() { - // Base Implementation, override to implement functionality. - return new RcsPresenceExchangeImplBase(); + public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl() { + // Base Implementation, override to implement functionality + return new RcsCapabilityExchangeImplBase(); } /**{@inheritDoc}*/ @@ -395,39 +416,20 @@ public class RcsFeature extends ImsFeature { return mImsRcsBinder; } - /**@hide*/ - public IRcsFeatureListener getListener() { - synchronized (mLock) { - return mListenerBinder; - } - } - - private void setListener(IRcsFeatureListener listener) { - synchronized (mLock) { - mListenerBinder = listener; - if (mListenerBinder != null) { - onFeatureReady(); - } - } - } - - private RcsPresenceExchangeImplBase getPresenceExchangeInternal() { - synchronized (mLock) { - if (mPresExchange == null) { - mPresExchange = getPresenceExchangeImpl(); - mPresExchange.initialize(this); - } - return mPresExchange; + private void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) { + mCapExchangeEventListener = listener; + if (mCapExchangeEventListener != null) { + onFeatureReady(); } } - private RcsSipOptionsImplBase getOptionsExchangeInternal() { + private RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() { synchronized (mLock) { - if (mSipOptions == null) { - mSipOptions = getOptionsExchangeImpl(); - mSipOptions.initialize(this); + if (mCapabilityExchangeImpl == null) { + mCapabilityExchangeImpl = createCapabilityExchangeImpl(); + mCapabilityExchangeImpl.setEventListener(mCapExchangeEventListener); } - return mSipOptions; + return mCapabilityExchangeImpl; } } } diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java index fda295a27111..0b13efb7b4b4 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java @@ -87,12 +87,8 @@ public class RcsCapabilityExchange { /** @hide */ protected final IRcsFeatureListener getListener() throws ImsException { - IRcsFeatureListener listener = mFeature.getListener(); - if (listener == null) { - throw new ImsException("Connection to Framework has not been established, wait for " - + "onFeatureReady().", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - return mFeature.getListener(); + throw new ImsException("This method is deprecated.", + ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); } /** diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java new file mode 100644 index 000000000000..b5704bfb3569 --- /dev/null +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims.stub; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.telephony.ims.ImsException; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; +import android.util.Log; +import android.util.Pair; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Base class for different types of Capability exchange. + * @hide + */ +public class RcsCapabilityExchangeImplBase { + + private static final String LOG_TAG = "RcsCapExchangeImplBase"; + + /** + * Service is unknown. + */ + public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; + + /** + * The command failed with an unknown error. + */ + public static final int COMMAND_CODE_GENERIC_FAILURE = 1; + + /** + * Invalid parameter(s). + */ + public static final int COMMAND_CODE_INVALID_PARAM = 2; + + /** + * Fetch error. + */ + public static final int COMMAND_CODE_FETCH_ERROR = 3; + + /** + * Request timed out. + */ + public static final int COMMAND_CODE_REQUEST_TIMEOUT = 4; + + /** + * Failure due to insufficient memory available. + */ + public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5; + + /** + * Network connection is lost. + * @hide + */ + public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 6; + + /** + * Requested feature/resource is not supported. + * @hide + */ + public static final int COMMAND_CODE_NOT_SUPPORTED = 7; + + /** + * Contact or resource is not found. + */ + public static final int COMMAND_CODE_NOT_FOUND = 8; + + /** + * Service is not available. + */ + public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 9; + + /** + * Command resulted in no change in state, ignoring. + */ + public static final int COMMAND_CODE_NO_CHANGE = 10; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "COMMAND_CODE_", value = { + COMMAND_CODE_SERVICE_UNKNOWN, + COMMAND_CODE_GENERIC_FAILURE, + COMMAND_CODE_INVALID_PARAM, + COMMAND_CODE_FETCH_ERROR, + COMMAND_CODE_REQUEST_TIMEOUT, + COMMAND_CODE_INSUFFICIENT_MEMORY, + COMMAND_CODE_LOST_NETWORK_CONNECTION, + COMMAND_CODE_NOT_SUPPORTED, + COMMAND_CODE_NOT_FOUND, + COMMAND_CODE_SERVICE_UNAVAILABLE, + COMMAND_CODE_NO_CHANGE + }) + public @interface CommandCode {} + + /** + * Interface used by the framework to receive the response of the publish request. + */ + public interface PublishResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the {@link RcsFeature} + * is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases + * when the Telephony stack has crashed. + */ + void onCommandError(@CommandCode int code) throws ImsException; + + + /** + * Provide the framework with a subsequent network response update to + * {@link #publishCapabilities(String, PublishResponseCallback)}. + * + * @param code The SIP response code sent from the network for the operation + * token specified. + * @param reason The optional reason response from the network. If the network + * provided no reason with the code, the string should be empty. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the {@link RcsFeature} + * is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases + * when the Telephony stack has crashed. + */ + void onNetworkResponse(@IntRange(from = 100, to = 699) int code, + @NonNull String reason) throws ImsException; + } + + /** + * Interface used by the framework to respond to OPTIONS requests. + */ + public interface OptionsResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} + * has not received the {@link ImsFeature#onFeatureReady()} callback. This may also happen + * in rare cases when the Telephony stack has crashed. + */ + void onCommandError(@CommandCode int code) throws ImsException; + + /** + * Send the response of a SIP OPTIONS capability exchange to the framework. + * @param code The SIP response code that was sent by the network in response + * to the request sent by {@link #sendOptionsCapabilityRequest}. + * @param reason The optional SIP response reason sent by the network. + * If none was sent, this should be an empty string. + * @param theirCaps the contact's UCE capabilities associated with the + * capability request. + * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not + * currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the + * {@link RcsFeature} has not received the + * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare + * cases when the Telephony stack has crashed. + */ + void onNetworkResponse(int code, @NonNull String reason, + @Nullable List<String> theirCaps) throws ImsException; + } + + /** + * Interface used by the framework to receive the response of the subscribe request. + */ + public interface SubscribeResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in + * rare cases when the Telephony stack has crashed. + */ + void onCommandError(@CommandCode int code) throws ImsException; + + /** + * Notify the framework of the response to the SUBSCRIBE request from + * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}. + * + * @param code The SIP response code sent from the network for the operation + * token specified. + * @param reason The optional reason response from the network. If the network + * provided no reason with the code, the string should be empty. + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently connected to the framework. This can happen if the + * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the + * {@link RcsFeature} has not received the {@link ImsFeature#onFeatureReady()} callback. + * This may also happen in rare cases when the Telephony stack has crashed. + */ + void onNetworkResponse(@IntRange(from = 100, to = 699) int code, + @NonNull String reason) throws ImsException; + + /** + * Provides the framework with latest XML PIDF documents included in the + * network response for the requested contacts' capabilities requested by the + * Framework using {@link #requestCapabilities(List, int)}. This should be + * called every time a new NOTIFY event is received with new capability + * information. + * + * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is + * not currently + * connected to the framework. This can happen if the {@link RcsFeature} is not + * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received + * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in + * rare cases when the + * Telephony stack has crashed. + */ + void onNotifyCapabilitiesUpdate(@NonNull List<String> pidfXmls) throws ImsException; + + /** + * A resource in the resource list for the presence subscribe event has been terminated. + * <p> + * This allows the framework to know that there will not be any capability information for + * a specific contact URI that they subscribed for. + */ + void onResourceTerminated( + @NonNull List<Pair<Uri, String>> uriTerminatedReason) throws ImsException; + + /** + * The subscription associated with a previous #requestCapabilities operation + * has been terminated. This will mostly be due to the subscription expiring, + * but may also happen due to an error. + * <p> + * This allows the framework to know that there will no longer be any + * capability updates for the requested operationToken. + */ + void onTerminated(String reason, String retryAfter) throws ImsException; + } + + + private ICapabilityExchangeEventListener mListener; + + /** + * Set the event listener to send the request to Framework. + */ + public void setEventListener(ICapabilityExchangeEventListener listener) { + mListener = listener; + } + + /** + * Get the event listener. + */ + public ICapabilityExchangeEventListener getEventListener() { + return mListener; + } + + /** + * The user capabilities of one or multiple contacts have been requested by the framework. + * <p> + * The response from the network to the SUBSCRIBE request must be sent back to the framework + * using {@link #onSubscribeNetworkResponse(int, String, int)}. As NOTIFY requests come in from + * the network, the requested contact’s capabilities should be sent back to the framework using + * {@link #onSubscribeNotifyRequest} and {@link onSubscribeResourceTerminated} + * should be called with the presence information for the contacts specified. + * <p> + * Once the subscription is terminated, {@link #onSubscriptionTerminated} must be called for + * the framework to finish listening for NOTIFY responses. + * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE + * capabilities for. + * @param cb The callback of the subscribe request. + */ + public void subscribeForCapabilities(@NonNull List<Uri> uris, + @NonNull SubscribeResponseCallback cb) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation."); + try { + cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } + + /** + * The capabilities of this device have been updated and should be published to the network. + * <p> + * If this operation succeeds, network response updates should be sent to the framework using + * {@link #onNetworkResponse(int, String)}. + * @param pidfXml The XML PIDF document containing the capabilities of this device to be sent + * to the carrier’s presence server. + * @param cb The callback of the publish request + */ + public void publishCapabilities(@NonNull String pidfXml, @NonNull PublishResponseCallback cb) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "publishCapabilities called with no implementation."); + try { + cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } + + /** + * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism + * in order to receive the capabilities of the remote user in response. + * <p> + * The implementer must call {@link #onNetworkResponse} to send the response of this + * query back to the framework. + * @param contactUri The URI of the remote user that we wish to get the capabilities of. + * @param myCapabilities The capabilities of this device to send to the remote user. + * @param callback The callback of this request which is sent from the remote user. + */ + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> myCapabilities, @NonNull OptionsResponseCallback callback) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "sendOptionsCapabilityRequest called with no implementation."); + try { + callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } +} diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 61c22bb09753..79456360c377 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -975,13 +975,6 @@ interface ITelephony { boolean setPreferredNetworkType(int subId, int networkType); /** - * User enable/disable Mobile Data. - * - * @param enable true to turn on, else false - */ - void setUserDataEnabled(int subId, boolean enable); - - /** * Get the user enabled state of Mobile Data. * * TODO: remove and use isUserDataEnabled. @@ -1002,12 +995,29 @@ interface ITelephony { boolean isUserDataEnabled(int subId); /** - * Get the overall enabled state of Mobile Data. - * + * Check if data is enabled on the device. It can be disabled by + * user, carrier, policy or thermal. * @return true on enabled */ boolean isDataEnabled(int subId); + /** + * Control of data connection and provide the reason triggering the data connection control. + * + * @param subId user preferred subId. + * @param reason the reason the data enable change is taking place + * @param enable true to turn on, else false + */ + void setDataEnabledForReason(int subId, int reason, boolean enable); + + /** + * Return whether data is enabled for certain reason + * @param subId user preferred subId. . + * @param reason the reason the data enable change is taking place + * @return true on enabled + */ + boolean isDataEnabledForReason(int subId, int reason); + /** * Checks if manual network selection is allowed. * @@ -1605,15 +1615,6 @@ interface ITelephony { int getCarrierIdFromMccMnc(int slotIndex, String mccmnc, boolean isSubscriptionMccMnc); /** - * Action set from carrier signalling broadcast receivers to enable/disable metered apns - * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required - * @param subId the subscription ID that this action applies to. - * @param enabled control enable or disable metered apns. - * @hide - */ - void carrierActionSetMeteredApnsEnabled(int subId, boolean visible); - - /** * Action set from carrier signalling broadcast receivers to enable/disable radio * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required * @param subId the subscription ID that this action applies to. @@ -1651,14 +1652,6 @@ interface ITelephony { void setCallWaitingStatus(int subId, boolean enabled, IIntegerConsumer callback); /** - * Policy control of data connection. Usually used when data limit is passed. - * @param enabled True if enabling the data, otherwise disabling. - * @param subId Subscription index - * @hide - */ - void setPolicyDataEnabled(boolean enabled, int subId); - - /** * Get Client request stats which will contain statistical information * on each request made by client. * @param callingPackage package making the call. diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index d524299d7ede..4abf784e9c81 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -30,77 +30,96 @@ public interface RILConstants { // from RIL_Errno int SUCCESS = 0; - int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */ + int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */ int GENERIC_FAILURE = 2; - int PASSWORD_INCORRECT = 3; /* for PIN/PIN2 methods only! */ - int SIM_PIN2 = 4; /* Operation requires SIM PIN2 to be entered */ - int SIM_PUK2 = 5; /* Operation requires SIM PIN2 to be entered */ + int PASSWORD_INCORRECT = 3; /* for PIN/PIN2 methods only! */ + int SIM_PIN2 = 4; /* Operation requires SIM PIN2 to be entered */ + int SIM_PUK2 = 5; /* Operation requires SIM PIN2 to be entered */ int REQUEST_NOT_SUPPORTED = 6; int REQUEST_CANCELLED = 7; - int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in - class C */ - int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device registers to - network */ - int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */ - int SIM_ABSENT = 11; /* ICC card is absent */ - int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified - location */ - int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */ - int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is enabled */ - int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due - to wrong SIM/ME and no - retries needed */ - int MISSING_RESOURCE = 16; /* no logical channel available */ - int NO_SUCH_ELEMENT = 17; /* application not found on SIM */ - int DIAL_MODIFIED_TO_USSD = 18; /* DIAL request modified to USSD */ - int DIAL_MODIFIED_TO_SS = 19; /* DIAL request modified to SS */ - int DIAL_MODIFIED_TO_DIAL = 20; /* DIAL request modified to DIAL with different data*/ - int USSD_MODIFIED_TO_DIAL = 21; /* USSD request modified to DIAL */ - int USSD_MODIFIED_TO_SS = 22; /* USSD request modified to SS */ - int USSD_MODIFIED_TO_USSD = 23; /* USSD request modified to different USSD request */ - int SS_MODIFIED_TO_DIAL = 24; /* SS request modified to DIAL */ - int SS_MODIFIED_TO_USSD = 25; /* SS request modified to USSD */ - int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */ - int SS_MODIFIED_TO_SS = 27; /* SS request modified to different SS request */ - int SIM_ALREADY_POWERED_OFF = 29; /* SAP: 0x03, Error card aleready powered off */ - int SIM_ALREADY_POWERED_ON = 30; /* SAP: 0x05, Error card already powered on */ - int SIM_DATA_NOT_AVAILABLE = 31; /* SAP: 0x06, Error data not available */ + int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice + call in class C */ + int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device + registers to network */ + int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */ + int SIM_ABSENT = 11; /* ICC card is absent */ + int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified + location */ + int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */ + int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is + enabled */ + int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due to wrong + SIM/ME and no retries needed */ + int MISSING_RESOURCE = 16; /* no logical channel available */ + int NO_SUCH_ELEMENT = 17; /* application not found on SIM */ + int DIAL_MODIFIED_TO_USSD = 18; /* DIAL request modified to USSD */ + int DIAL_MODIFIED_TO_SS = 19; /* DIAL request modified to SS */ + int DIAL_MODIFIED_TO_DIAL = 20; /* DIAL request modified to DIAL with + different data*/ + int USSD_MODIFIED_TO_DIAL = 21; /* USSD request modified to DIAL */ + int USSD_MODIFIED_TO_SS = 22; /* USSD request modified to SS */ + int USSD_MODIFIED_TO_USSD = 23; /* USSD request modified to different USSD + request */ + int SS_MODIFIED_TO_DIAL = 24; /* SS request modified to DIAL */ + int SS_MODIFIED_TO_USSD = 25; /* SS request modified to USSD */ + int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */ + int SS_MODIFIED_TO_SS = 27; /* SS request modified to different SS + request */ + int SIM_ALREADY_POWERED_OFF = 29; /* SAP: 0x03, Error card aleready powered off */ + int SIM_ALREADY_POWERED_ON = 30; /* SAP: 0x05, Error card already powered on */ + int SIM_DATA_NOT_AVAILABLE = 31; /* SAP: 0x06, Error data not available */ int SIM_SAP_CONNECT_FAILURE = 32; int SIM_SAP_MSG_SIZE_TOO_LARGE = 33; int SIM_SAP_MSG_SIZE_TOO_SMALL = 34; int SIM_SAP_CONNECT_OK_CALL_ONGOING = 35; - int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not supported */ - int NO_MEMORY = 37; /* Not sufficient memory to process the request */ - int INTERNAL_ERR = 38; /* Hit unexpected vendor internal error scenario */ - int SYSTEM_ERR = 39; /* Hit platform or system error */ - int MODEM_ERR = 40; /* Hit unexpected modem error */ - int INVALID_STATE = 41; /* Unexpected request for the current state */ - int NO_RESOURCES = 42; /* Not sufficient resource to process the request */ - int SIM_ERR = 43; /* Received error from SIM card */ - int INVALID_ARGUMENTS = 44; /* Received invalid arguments in request */ - int INVALID_SIM_STATE = 45; /* Can not process the request in current SIM state */ - int INVALID_MODEM_STATE = 46; /* Can not process the request in current Modem state */ - int INVALID_CALL_ID = 47; /* Received invalid call id in request */ - int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */ - int NETWORK_ERR = 49; /* Received error from network */ - int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent requests */ - int SIM_BUSY = 51; /* SIM is busy */ - int SIM_FULL = 52; /* The target EF is full */ - int NETWORK_REJECT = 53; /* Request is rejected by network */ - int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */ - int EMPTY_RECORD = 55; /* The request record is empty */ - int INVALID_SMS_FORMAT = 56; /* Invalid sms format */ - int ENCODING_ERR = 57; /* Message not encoded properly */ - int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */ - int NO_SUCH_ENTRY = 59; /* No such entry present to perform the request */ - int NETWORK_NOT_READY = 60; /* Network is not ready to perform the request */ - int NOT_PROVISIONED = 61; /* Device doesnot have this value provisioned */ - int NO_SUBSCRIPTION = 62; /* Device doesnot have subscription */ - int NO_NETWORK_FOUND = 63; /* Network cannot be found */ - int DEVICE_IN_USE = 64; /* Operation cannot be performed because the device - is currently in use */ - int ABORTED = 65; /* Operation aborted */ - int INVALID_RESPONSE = 66; /* Invalid response sent by vendor code */ + int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not + supported */ + int NO_MEMORY = 37; /* Not sufficient memory to process the + request */ + int INTERNAL_ERR = 38; /* Hit unexpected vendor internal error + scenario */ + int SYSTEM_ERR = 39; /* Hit platform or system error */ + int MODEM_ERR = 40; /* Hit unexpected modem error */ + int INVALID_STATE = 41; /* Unexpected request for the current state */ + int NO_RESOURCES = 42; /* Not sufficient resource to process the + request */ + int SIM_ERR = 43; /* Received error from SIM card */ + int INVALID_ARGUMENTS = 44; /* Received invalid arguments in request */ + int INVALID_SIM_STATE = 45; /* Can not process the request in current SIM + state */ + int INVALID_MODEM_STATE = 46; /* Can not process the request in current Modem + state */ + int INVALID_CALL_ID = 47; /* Received invalid call id in request */ + int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */ + int NETWORK_ERR = 49; /* Received error from network */ + int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent + requests */ + int SIM_BUSY = 51; /* SIM is busy */ + int SIM_FULL = 52; /* The target EF is full */ + int NETWORK_REJECT = 53; /* Request is rejected by network */ + int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */ + int EMPTY_RECORD = 55; /* The request record is empty */ + int INVALID_SMS_FORMAT = 56; /* Invalid sms format */ + int ENCODING_ERR = 57; /* Message not encoded properly */ + int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */ + int NO_SUCH_ENTRY = 59; /* No such entry present to perform the + request */ + int NETWORK_NOT_READY = 60; /* Network is not ready to perform the + request */ + int NOT_PROVISIONED = 61; /* Device doesnot have this value + provisioned */ + int NO_SUBSCRIPTION = 62; /* Device doesnot have subscription */ + int NO_NETWORK_FOUND = 63; /* Network cannot be found */ + int DEVICE_IN_USE = 64; /* Operation cannot be performed because the + device is currently in use */ + int ABORTED = 65; /* Operation aborted */ + int INVALID_RESPONSE = 66; /* Invalid response sent by vendor code */ + int SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 67; /* 1X voice and SMS are not allowed + simulteneously */ + int ACCESS_BARRED = 68; /* SMS access is barred */ + int BLOCKED_DUE_TO_CALL = 69; /* SMS is blocked due to call control */ + int RF_HARDWARE_ISSUE = 70; /* RF HW issue is detected */ + int NO_RF_CALIBRATION_INFO = 71; /* No RF calibration in device */ // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to // reveal particular replacement for Generic failure @@ -494,6 +513,10 @@ public interface RILConstants { int RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS = 210; int RIL_REQUEST_GET_BARRING_INFO = 211; int RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION = 212; + int RIL_REQUEST_ALLOCATE_PDU_SESSION_ID = 215; + int RIL_REQUEST_RELEASE_PDU_SESSION_ID = 216; + int RIL_REQUEST_BEGIN_HANDOVER = 217; + int RIL_REQUEST_CANCEL_HANDOVER = 218; /* Responses begin */ int RIL_RESPONSE_ACKNOWLEDGEMENT = 800; diff --git a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java index 858358c74f80..8b730af76951 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java @@ -22,7 +22,6 @@ import static org.mockito.Mockito.when; import android.Manifest; import android.Manifest.permission; import android.app.AppOpsManager; -import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; @@ -167,13 +166,11 @@ public class NetworkStatsAccessTest { } private void setIsDeviceOwner(boolean isOwner) { - when(mDpmi.isActiveAdminWithPolicy(TEST_UID, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER)) - .thenReturn(isOwner); + when(mDpmi.isActiveDeviceOwner(TEST_UID)).thenReturn(isOwner); } private void setIsProfileOwner(boolean isOwner) { - when(mDpmi.isActiveAdminWithPolicy(TEST_UID, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)) - .thenReturn(isOwner); + when(mDpmi.isActiveProfileOwner(TEST_UID)).thenReturn(isOwner); } private void setHasAppOpsPermission(int appOpsMode, boolean hasPermission) { diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp new file mode 100644 index 000000000000..f967bf0d8f6b --- /dev/null +++ b/tests/vcn/Android.bp @@ -0,0 +1,27 @@ +//######################################################################## +// Build FrameworksVcnTests package +//######################################################################## + +android_test { + name: "FrameworksVcnTests", + srcs: [ + "java/**/*.java", + "java/**/*.kt", + ], + platform_apis: true, + test_suites: ["device-tests"], + certificate: "platform", + static_libs: [ + "androidx.test.rules", + "frameworks-base-testutils", + "framework-protos", + "mockito-target-minus-junit4", + "platform-test-annotations", + "services.core", + ], + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + ], +} diff --git a/tests/vcn/AndroidManifest.xml b/tests/vcn/AndroidManifest.xml new file mode 100644 index 000000000000..2ad9aac67029 --- /dev/null +++ b/tests/vcn/AndroidManifest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.frameworks.tests.vcn"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.frameworks.tests.vcn" + android:label="Frameworks VCN Tests" /> +</manifest> diff --git a/tests/vcn/AndroidTest.xml b/tests/vcn/AndroidTest.xml new file mode 100644 index 000000000000..dc521fd7bcd9 --- /dev/null +++ b/tests/vcn/AndroidTest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Runs VCN Tests."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="FrameworksVcnTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-tag" value="FrameworksVcnTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.frameworks.tests.vcn" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration> diff --git a/tests/vcn/TEST_MAPPING b/tests/vcn/TEST_MAPPING new file mode 100644 index 000000000000..54fa411e3570 --- /dev/null +++ b/tests/vcn/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "FrameworksVcnTests" + } + ] +}
\ No newline at end of file |